Files
xiaomihome/miot/miot_client_prop_test.go
T
4566704 3a44cb9e6a feat: 初始化小米 IoT (MIoT) 智能家居 Go 库
- 实现 MIoT 客户端核心功能(MQTT 连接、设备管理、属性读写)
- 支持云端 API 调用与局域网设备发现(mDNS)
- 集成国际化(i18n)多语言支持
- 添加 MIoT 设备规约解析器(spec_parser)
- 包含单元测试与使用示例
2026-06-28 22:05:49 +08:00

194 lines
4.6 KiB
Go

// Package miot provides white-box tests for miot_client_prop.go property refresh.
package miot
import (
"fmt"
"testing"
"time"
)
// ============================================================================
// RequestRefreshProp — queue and timer
// ============================================================================
func TestRequestRefreshProp_QueuesProperty(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.RequestRefreshProp("did1", 2, 1)
c.mu.Lock()
key := fmt.Sprintf("%s|%d|%d", "did1", 2, 1)
_, exists := c.refreshPropsList[key]
queueLen := len(c.refreshPropsList)
timer := c.refreshPropsTimer
c.mu.Unlock()
if !exists {
t.Error("property should be in refreshPropsList")
}
if queueLen != 1 {
t.Errorf("queue len = %d, want 1", queueLen)
}
if timer == nil {
t.Error("refreshPropsTimer should be created")
}
// Clean up
if timer != nil {
timer.Stop()
}
c.refreshPropsList = make(map[string]map[string]interface{})
}
func TestRequestRefreshProp_DuplicateSkipped(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.RequestRefreshProp("did1", 2, 1)
c.RequestRefreshProp("did1", 2, 1) // duplicate
c.mu.Lock()
queueLen := len(c.refreshPropsList)
timer := c.refreshPropsTimer
c.mu.Unlock()
if queueLen != 1 {
t.Errorf("queue len should be 1 after duplicate, got %d", queueLen)
}
if timer != nil {
timer.Stop()
}
c.refreshPropsList = make(map[string]map[string]interface{})
}
func TestRequestRefreshProp_MultipleProperties(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.RequestRefreshProp("did1", 2, 1)
c.RequestRefreshProp("did1", 2, 2)
c.RequestRefreshProp("did2", 3, 1)
c.mu.Lock()
queueLen := len(c.refreshPropsList)
timer := c.refreshPropsTimer
c.mu.Unlock()
if queueLen != 3 {
t.Errorf("queue len = %d, want 3", queueLen)
}
if timer != nil {
timer.Stop()
}
c.refreshPropsList = make(map[string]map[string]interface{})
}
func TestRequestRefreshProp_ReusesTimer(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.RequestRefreshProp("did1", 2, 1)
c.mu.Lock()
firstTimer := c.refreshPropsTimer
c.mu.Unlock()
c.RequestRefreshProp("did2", 3, 1)
c.mu.Lock()
secondTimer := c.refreshPropsTimer
c.mu.Unlock()
if firstTimer != secondTimer {
t.Error("second RequestRefreshProp should reuse the same timer")
}
if firstTimer != nil {
firstTimer.Stop()
}
c.refreshPropsList = make(map[string]map[string]interface{})
}
// ============================================================================
// refreshPropsHandler — empty queue and no HTTP
// ============================================================================
func TestRefreshPropsHandler_EmptyQueue(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
// Handler with empty queue should return immediately
c.mu.Lock()
c.refreshPropsList = make(map[string]map[string]interface{})
c.mu.Unlock()
// Should not panic
c.refreshPropsHandler()
}
func TestRefreshPropsHandler_NoHTTP(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.mu.Lock()
c.refreshPropsList["did1|2|1"] = map[string]interface{}{
"did": "did1",
"siid": 2,
"piid": 1,
}
c.mu.Unlock()
// Should not panic, just return due to no HTTP
c.refreshPropsHandler()
// Queue should be cleared
c.mu.Lock()
queueLen := len(c.refreshPropsList)
c.mu.Unlock()
if queueLen != 0 {
t.Errorf("queue should be cleared after handler, got %d items", queueLen)
}
}
// ============================================================================
// RequestRefreshProp — cancellation
// ============================================================================
func TestRequestRefreshProp_CancelTimer(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.RequestRefreshProp("did1", 2, 1)
c.mu.Lock()
timer := c.refreshPropsTimer
c.mu.Unlock()
// Cancel the timer manually
if timer != nil {
timer.Stop()
}
// Clear to avoid timer firing after Stop
c.mu.Lock()
c.refreshPropsList = make(map[string]map[string]interface{})
c.refreshPropsTimer = nil
c.mu.Unlock()
// Give timer a moment (should be stopped, no action)
time.Sleep(50 * time.Millisecond)
}
// ============================================================================
// refreshRetryCount
// ============================================================================
func TestRefreshProps_InitialRetryCount(t *testing.T) {
c := NewMIoTClient("test", nil, "uid", "cn", CtrlModeCloud)
c.mu.Lock()
retry := c.refreshRetryCount
c.mu.Unlock()
if retry != 0 {
t.Errorf("initial retry count = %d, want 0", retry)
}
}