Gisle Aune
2 years ago
9 changed files with 181 additions and 21 deletions
-
2bus.go
-
2events/device.go
-
3go.mod
-
4internal/color/color.go
-
87internal/testutils/eventlogger.go
-
3services/effectenforcer.go
-
66services/effectenforcer_test.go
-
25services/nanoleaf/client.go
-
2services/scenemap.go
@ -0,0 +1,87 @@ |
|||
package testutils |
|||
|
|||
import ( |
|||
"fmt" |
|||
lucifer3 "git.aiterp.net/lucifer3/server" |
|||
"log" |
|||
"math/rand" |
|||
"sync/atomic" |
|||
"testing" |
|||
) |
|||
|
|||
type syncEvent struct { |
|||
id uint64 |
|||
} |
|||
|
|||
func (s syncEvent) EventDescription() string { |
|||
return fmt.Sprintf("syncEvent(%d)", s.id) |
|||
} |
|||
|
|||
type TestEventLogger struct { |
|||
entries []any |
|||
syncN uint64 |
|||
syncCh chan struct{} |
|||
} |
|||
|
|||
func (l *TestEventLogger) Active() bool { |
|||
return true |
|||
} |
|||
|
|||
func (l *TestEventLogger) Sync(bus *lucifer3.EventBus) { |
|||
l.syncCh = make(chan struct{}) |
|||
v := rand.Int63() |
|||
atomic.StoreUint64(&l.syncN, uint64(v)) |
|||
|
|||
bus.RunEvent(syncEvent{id: uint64(v)}) |
|||
|
|||
<-l.syncCh |
|||
} |
|||
|
|||
func (l *TestEventLogger) AssertEvent(t *testing.T, eventStr string) { |
|||
for i, entry := range l.entries { |
|||
if event, ok := entry.(lucifer3.Event); ok && eventStr == event.EventDescription() { |
|||
l.entries = l.entries[i+1:] |
|||
return |
|||
} |
|||
} |
|||
|
|||
t.Errorf("Event not found: %s", eventStr) |
|||
} |
|||
|
|||
func (l *TestEventLogger) AssertCommand(t *testing.T, commandStr string) { |
|||
for i, entry := range l.entries { |
|||
if cmd, ok := entry.(lucifer3.Command); ok { |
|||
log.Println(cmd.CommandDescription() == commandStr) |
|||
} |
|||
if command, ok := entry.(lucifer3.Command); ok && commandStr == command.CommandDescription() { |
|||
l.entries = l.entries[i+1:] |
|||
return |
|||
} |
|||
} |
|||
|
|||
t.Errorf("Command not found: %s", commandStr) |
|||
} |
|||
|
|||
func (l *TestEventLogger) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) { |
|||
if ev, ok := event.(syncEvent); ok { |
|||
if atomic.CompareAndSwapUint64(&l.syncN, ev.id, 0) { |
|||
close(l.syncCh) |
|||
} |
|||
} |
|||
|
|||
l.entries = append(l.entries, event) |
|||
} |
|||
|
|||
func (l *TestEventLogger) HandleCommand(_ *lucifer3.EventBus, command lucifer3.Command) { |
|||
l.entries = append(l.entries, command) |
|||
} |
|||
|
|||
func evStr(ev any) string { |
|||
if ev, ok := ev.(lucifer3.Event); ok { |
|||
return ev.EventDescription() |
|||
} else if ev, ok := ev.(lucifer3.Command); ok { |
|||
return ev.CommandDescription() |
|||
} |
|||
|
|||
panic("Unknown type") |
|||
} |
@ -0,0 +1,66 @@ |
|||
package services |
|||
|
|||
import ( |
|||
lucifer3 "git.aiterp.net/lucifer3/server" |
|||
"git.aiterp.net/lucifer3/server/commands" |
|||
"git.aiterp.net/lucifer3/server/device" |
|||
"git.aiterp.net/lucifer3/server/effects" |
|||
"git.aiterp.net/lucifer3/server/events" |
|||
"git.aiterp.net/lucifer3/server/internal/color" |
|||
"git.aiterp.net/lucifer3/server/internal/gentools" |
|||
"git.aiterp.net/lucifer3/server/internal/testutils" |
|||
"strconv" |
|||
"testing" |
|||
"time" |
|||
) |
|||
|
|||
func TestEffectEnforcer(t *testing.T) { |
|||
bus := lucifer3.EventBus{} |
|||
resolver := NewResolver() |
|||
sceneMap := NewSceneMap(resolver) |
|||
logger := &testutils.TestEventLogger{} |
|||
|
|||
bus.JoinPrivileged(resolver) |
|||
bus.JoinPrivileged(sceneMap) |
|||
bus.Join(NewEffectEnforcer(resolver, sceneMap)) |
|||
bus.Join(logger) |
|||
|
|||
for i := 1; i <= 9; i += 1 { |
|||
bus.RunEvents([]lucifer3.Event{ |
|||
events.HardwareState{ |
|||
ID: "test:" + strconv.Itoa(i), |
|||
InternalName: "Test Device " + strconv.Itoa(i), |
|||
SupportFlags: device.SFlagColor | device.SFlagIntensity | device.SFlagPower, |
|||
ColorFlags: device.CFlagXY | device.CFlagHS | device.CFlagRGB | device.CFlagKelvin, |
|||
ColorGamut: nil, |
|||
ColorKelvinRange: nil, |
|||
Buttons: nil, |
|||
State: device.State{ |
|||
Power: gentools.Ptr(false), |
|||
Intensity: gentools.Ptr(1.0), |
|||
Color: &color.Color{K: gentools.Ptr(2900)}, |
|||
}, |
|||
BatteryPercentage: nil, |
|||
Unreachable: false, |
|||
}, |
|||
events.DeviceReady{ID: "test:" + strconv.Itoa(i)}, |
|||
}) |
|||
} |
|||
|
|||
bus.RunCommand(commands.Assign{ |
|||
Match: "test:*", |
|||
Effect: effects.Pattern{ |
|||
States: []device.State{ |
|||
{Color: &color.Color{XY: &color.XY{X: 0.22, Y: 0.18}}}, |
|||
{Color: &color.Color{XY: &color.XY{X: 0.27, Y: 0.23}}}, |
|||
}, |
|||
}, |
|||
}) |
|||
|
|||
time.Sleep(time.Millisecond * 100) |
|||
logger.Sync(&bus) |
|||
logger.AssertEvent(t, "DeviceReady(id:test:1)") |
|||
logger.AssertEvent(t, "DeviceReady(id:test:9)") |
|||
logger.AssertCommand(t, "Assign(test:*, Pattern(states:[(xy:0.2200,0.1800), (xy:0.2700,0.2300)], anim:0ms))") |
|||
logger.AssertCommand(t, "SetStateBatch(9 devices)") |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue