// 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) } }