package iotmock import ( "context" "testing" "git.yeij.top/AskaEth/Cyrene_v2/internal/plugin" ) func TestNewPlugin(t *testing.T) { p := New() if p.Name() != "iot-mock" { t.Errorf("expected name iot-mock, got %s", p.Name()) } if p.Version() != "1.0.0" { t.Errorf("expected version 1.0.0, got %s", p.Version()) } if !p.Enabled() { t.Error("plugin should be enabled by default") } } func TestListDevices(t *testing.T) { p := New() devices, err := p.ListDevices(context.Background()) if err != nil { t.Fatalf("ListDevices failed: %v", err) } if len(devices) != 8 { t.Errorf("expected 8 devices, got %d", len(devices)) } // Verify devices are clones (modifying returned device doesn't affect internal state) devices[0].State["power"] = true d, _ := p.GetDevice(context.Background(), "light-livingroom") if d.State["power"] != false { t.Error("returned devices should be clones, internal state modified") } } func TestGetDevice(t *testing.T) { p := New() d, err := p.GetDevice(context.Background(), "light-livingroom") if err != nil { t.Fatalf("GetDevice failed: %v", err) } if d.Name != "客厅灯" { t.Errorf("expected name 客厅灯, got %s", d.Name) } if d.Type != plugin.DeviceLight { t.Errorf("expected type light, got %s", d.Type) } // Unknown device _, err = p.GetDevice(context.Background(), "nonexistent") if err == nil { t.Error("expected error for unknown device") } } func TestToggleDevice(t *testing.T) { p := New() // Initially off d, _ := p.GetDevice(context.Background(), "light-livingroom") if d.State["power"] != false { t.Error("expected light to be off initially") } // Toggle on err := p.ToggleDevice(context.Background(), "light-livingroom") if err != nil { t.Fatalf("ToggleDevice failed: %v", err) } d, _ = p.GetDevice(context.Background(), "light-livingroom") if d.State["power"] != true { t.Error("expected light to be on after toggle") } // Toggle off p.ToggleDevice(context.Background(), "light-livingroom") d, _ = p.GetDevice(context.Background(), "light-livingroom") if d.State["power"] != false { t.Error("expected light to be off after second toggle") } } func TestSetDevice(t *testing.T) { p := New() err := p.SetDevice(context.Background(), "light-livingroom", "brightness", 50) if err != nil { t.Fatalf("SetDevice failed: %v", err) } d, _ := p.GetDevice(context.Background(), "light-livingroom") if d.State["brightness"] != 50 { t.Errorf("expected brightness=50, got %v", d.State["brightness"]) } // History should have an entry if len(d.History) != 1 { t.Errorf("expected 1 history entry, got %d", len(d.History)) } } func TestSetDeviceNotFound(t *testing.T) { p := New() err := p.SetDevice(context.Background(), "nonexistent", "power", true) if err == nil { t.Error("expected error for unknown device") } } func TestSubscribeChanges(t *testing.T) { p := New() ch, err := p.SubscribeChanges(context.Background()) if err != nil { t.Fatalf("SubscribeChanges failed: %v", err) } // Toggle should emit an event go p.ToggleDevice(context.Background(), "light-livingroom") event := <-ch if event.DeviceID != "light-livingroom" { t.Errorf("expected event for light-livingroom, got %s", event.DeviceID) } if event.Field != "power" { t.Errorf("expected event field power, got %s", event.Field) } if event.NewValue != true { t.Errorf("expected new value true, got %v", event.NewValue) } } func TestInitAndClose(t *testing.T) { p := New() err := p.Init(context.Background(), plugin.PluginConfig{}) if err != nil { t.Fatalf("Init failed: %v", err) } err = p.Close() if err != nil { t.Fatalf("Close failed: %v", err) } // Second close should be safe err = p.Close() if err != nil { t.Errorf("second Close should not error: %v", err) } } func TestDeviceHistoryLimit(t *testing.T) { p := New() // Generate 25 events (limit is 20) for i := range 25 { p.SetDevice(context.Background(), "light-livingroom", "brightness", i) } d, _ := p.GetDevice(context.Background(), "light-livingroom") if len(d.History) > 20 { t.Errorf("history should be capped at 20, got %d", len(d.History)) } } func TestAllDevicesExist(t *testing.T) { p := New() expectedIDs := []string{ "light-livingroom", "light-bedroom", "ac-livingroom", "ac-bedroom", "curtain-livingroom", "sensor-temperature", "sensor-humidity", "lock-door", } for _, id := range expectedIDs { _, err := p.GetDevice(context.Background(), id) if err != nil { t.Errorf("expected device %s to exist", id) } } } func TestPluginInterface(t *testing.T) { p := New() // Verify it implements the IoTProvider interface var _ plugin.IoTProvider = p // Verify it implements the base Plugin interface var _ plugin.Plugin = p }