1
0
Fork 0
hswro-alarm-bot/filters_test.go

291 lines
9.8 KiB
Go
Raw Normal View History

2024-02-13 22:20:15 +00:00
package main
import (
2024-02-15 19:06:06 +00:00
"io"
"log"
"os"
2024-02-13 22:20:15 +00:00
"sync"
"testing"
2024-03-04 20:11:34 +00:00
"git.sr.ht/~michalr/go-satel"
2024-02-13 22:20:15 +00:00
"github.com/stretchr/testify/assert"
)
func TestSatelEventTypeFiltering(t *testing.T) {
tested := MakeFilterByTypeOrIndex([]SatelChangeType{{satel.ArmedPartition}, {satel.PartitionFireAlarm}},
[]int{})
mock := &GenericSyncMockFilter[satel.Event]{}
tested.Then(mock)
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.DoorOpened, 2, true))
tested.Call(makeTestSatelEvent(satel.PartitionAlarm, 3, true))
tested.Call(makeTestSatelEvent(satel.PartitionFireAlarm, 4, true))
tested.Call(makeTestSatelEvent(satel.TroublePart1, 5, true))
tested.Call(makeTestSatelEvent(satel.ZoneTamper, 6, true))
assert.Len(t, mock.collected, 2)
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.PartitionFireAlarm, 4, true))
2024-02-13 22:20:15 +00:00
}
2024-02-14 20:34:16 +00:00
2024-02-18 17:44:08 +00:00
func TestSatelEventTypeFiltering_NoAllowedEventTypesMeansAllAreAllowed(t *testing.T) {
tested := MakeFilterByTypeOrIndex([]SatelChangeType{},
[]int{})
mock := &GenericSyncMockFilter[satel.Event]{}
2024-02-18 17:44:08 +00:00
tested.Then(mock)
2024-02-18 17:44:08 +00:00
for index, ct := range SUPPORTED_CHANGE_TYPES {
tested.Call(makeTestSatelEvent(ct, index, true))
2024-02-18 17:44:08 +00:00
}
assert.Len(t, mock.collected, len(SUPPORTED_CHANGE_TYPES))
2024-02-18 17:44:08 +00:00
for index, ct := range SUPPORTED_CHANGE_TYPES {
assert.Contains(t, mock.collected, makeTestSatelEvent(ct, index, true))
2024-02-18 17:44:08 +00:00
}
}
2024-02-18 18:00:49 +00:00
func TestSatelIndexFiltering(t *testing.T) {
tested := MakeFilterByTypeOrIndex([]SatelChangeType{}, []int{1, 3})
mock := &GenericSyncMockFilter[satel.Event]{}
tested.Then(mock)
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.DoorOpened, 2, true))
tested.Call(makeTestSatelEvent(satel.PartitionAlarm, 3, true))
tested.Call(makeTestSatelEvent(satel.PartitionFireAlarm, 4, true))
tested.Call(makeTestSatelEvent(satel.TroublePart1, 5, true))
tested.Call(makeTestSatelEvent(satel.ZoneTamper, 6, true))
assert.Len(t, mock.collected, 2)
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.PartitionAlarm, 3, true))
2024-02-18 18:00:49 +00:00
}
func TestSatelIndexFiltering_NoAllowedEventTypesMeansAllAreAllowed(t *testing.T) {
tested := MakeFilterByTypeOrIndex([]SatelChangeType{{satel.ArmedPartition}, {satel.PartitionFireAlarm}},
[]int{})
mock := &GenericSyncMockFilter[satel.Event]{}
2024-02-18 18:00:49 +00:00
myReasonableMaxIndex := 100 // I wanted to use math.MaxInt at first, but it's kind of a waste of time here
tested.Then(mock)
2024-02-18 18:00:49 +00:00
for i := 0; i < myReasonableMaxIndex; i++ {
tested.Call(makeTestSatelEvent(satel.ArmedPartition, i, true))
2024-02-18 18:00:49 +00:00
}
assert.Len(t, mock.collected, myReasonableMaxIndex)
2024-02-18 18:00:49 +00:00
for i := 0; i < myReasonableMaxIndex; i++ {
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, i, true))
2024-02-18 18:00:49 +00:00
}
}
2024-02-14 20:34:16 +00:00
func TestSatelLastSeenFiltering(t *testing.T) {
2024-02-15 19:06:06 +00:00
f, err := os.CreateTemp("", "TestSatelLastSeenFiltering")
assert.NoError(t, err)
tempFileName := f.Name()
assert.NoError(t, f.Close())
defer os.Remove(f.Name())
fakeLog := log.New(io.Discard, "", log.Ltime)
ds := MakeDataStore(fakeLog, tempFileName)
2024-02-14 20:34:16 +00:00
tested := MakeFilterByLastSeen(&ds)
mock := &GenericSyncMockFilter[satel.Event]{}
tested.Then(mock)
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
assert.Len(t, mock.collected, 3)
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 2, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, false))
2024-02-14 20:34:16 +00:00
}
2024-02-15 19:06:06 +00:00
func TestSatelLastSeenFilteringWithPersistence(t *testing.T) {
f, err := os.CreateTemp("", "TestSatelLastSeenFilteringWithPersistence")
assert.NoError(t, err)
tempFileName := f.Name()
assert.NoError(t, f.Close())
defer os.Remove(f.Name())
fakeLog := log.New(io.Discard, "", log.Ltime)
ds := MakeDataStore(fakeLog, tempFileName)
2024-02-15 19:06:06 +00:00
tested := MakeFilterByLastSeen(&ds)
mock := &GenericSyncMockFilter[satel.Event]{}
tested.Then(mock)
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
tested.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
assert.Len(t, mock.collected, 3)
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 2, true))
assert.Contains(t, mock.collected, makeTestSatelEvent(satel.ArmedPartition, 1, false))
tested = nil
mock = nil
ds2 := MakeDataStore(fakeLog, tempFileName)
tested2 := MakeFilterByLastSeen(&ds2)
mock2 := &GenericSyncMockFilter[satel.Event]{}
tested2.Then(mock2)
tested2.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
tested2.Call(makeTestSatelEvent(satel.ArmedPartition, 1, false))
tested2.Call(makeTestSatelEvent(satel.ArmedPartition, 1, true))
tested2.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
tested2.Call(makeTestSatelEvent(satel.ArmedPartition, 2, true))
assert.Len(t, mock2.collected, 1)
assert.Contains(t, mock2.collected, makeTestSatelEvent(satel.ArmedPartition, 1, true))
2024-02-15 19:06:06 +00:00
}
2024-03-10 09:52:27 +00:00
type MockSleeper struct {
ch *chan<- interface{}
callCount int
}
func (self *MockSleeper) Sleep(ch chan<- interface{}) {
if self.ch == nil {
self.ch = &ch
}
self.callCount += 1
}
type GenericSyncMockFilter[T any] struct {
SyncFilterImpl[T]
collected []T
2025-01-06 13:55:08 +00:00
}
func (self *GenericSyncMockFilter[T]) Call(msg T) {
2025-01-06 13:55:08 +00:00
self.collected = append(self.collected, msg)
2025-01-06 19:53:08 +00:00
self.CallNext(msg)
2025-01-06 13:55:08 +00:00
}
type SyncMockFilter = GenericSyncMockFilter[GenericMessage]
2025-01-06 13:55:08 +00:00
func TestSyncCollect(t *testing.T) {
testEvents := make(chan GenericMessage)
wg := sync.WaitGroup{}
2025-01-06 23:10:21 +00:00
tested := CollectFromChannel[GenericMessage]{}
2025-01-06 13:55:08 +00:00
mock := &SyncMockFilter{}
mock2 := &SyncMockFilter{}
tested.Then(mock).Then(mock2)
2025-01-06 23:10:21 +00:00
wg.Add(1)
tested.Collect(testEvents, &wg, func() { wg.Done() })
2025-01-06 13:55:08 +00:00
testEvents <- makeGenericMessage(satel.ArmedPartition, 1, true)
testEvents <- makeGenericMessage(satel.DoorOpened, 2, true)
testEvents <- makeGenericMessage(satel.PartitionAlarm, 3, true)
testEvents <- makeGenericMessage(satel.PartitionFireAlarm, 4, true)
testEvents <- makeGenericMessage(satel.TroublePart1, 5, true)
testEvents <- makeGenericMessage(satel.ZoneTamper, 6, true)
close(testEvents)
wg.Wait()
assert.Len(t, mock.collected, 6)
assert.Contains(t, mock.collected, makeGenericMessage(satel.ArmedPartition, 1, true))
assert.Contains(t, mock.collected, makeGenericMessage(satel.DoorOpened, 2, true))
assert.Contains(t, mock.collected, makeGenericMessage(satel.PartitionAlarm, 3, true))
assert.Contains(t, mock.collected, makeGenericMessage(satel.PartitionFireAlarm, 4, true))
assert.Contains(t, mock.collected, makeGenericMessage(satel.TroublePart1, 5, true))
assert.Contains(t, mock.collected, makeGenericMessage(satel.ZoneTamper, 6, true))
assert.Len(t, mock2.collected, 6)
assert.Contains(t, mock2.collected, makeGenericMessage(satel.ArmedPartition, 1, true))
assert.Contains(t, mock2.collected, makeGenericMessage(satel.DoorOpened, 2, true))
assert.Contains(t, mock2.collected, makeGenericMessage(satel.PartitionAlarm, 3, true))
assert.Contains(t, mock2.collected, makeGenericMessage(satel.PartitionFireAlarm, 4, true))
assert.Contains(t, mock2.collected, makeGenericMessage(satel.TroublePart1, 5, true))
assert.Contains(t, mock2.collected, makeGenericMessage(satel.ZoneTamper, 6, true))
}
2025-01-06 23:09:41 +00:00
func TestThrottleSync(t *testing.T) {
wg := sync.WaitGroup{}
fakeLog := log.New(io.Discard, "", log.Ltime)
mockSleeper := MockSleeper{nil, 0}
var (
tplMessageTest1 = satel.BasicEventElement{Type: satel.ArmedPartition, Index: 1, Value: true}
tplMessageTest2 = satel.BasicEventElement{Type: satel.ZoneViolation, Index: 2, Value: true}
tplMessageTest3 = satel.BasicEventElement{Type: satel.ArmedPartition, Index: 1, Value: false}
tplMessageTest4 = satel.BasicEventElement{Type: satel.ZoneViolation, Index: 2, Value: false}
)
tested := MakeThrottleSync(&mockSleeper, fakeLog, &wg)
mock := &SyncMockFilter{}
tested.Then(mock)
tested.Call(GenericMessage{[]satel.BasicEventElement{tplMessageTest1}})
tested.Call(GenericMessage{[]satel.BasicEventElement{tplMessageTest2}})
tested.Call(GenericMessage{[]satel.BasicEventElement{tplMessageTest3}})
*mockSleeper.ch <- nil
tested.Call(GenericMessage{[]satel.BasicEventElement{tplMessageTest4}})
tested.Close()
wg.Wait()
assert.Equal(t, 2, mockSleeper.callCount)
assert.Len(t, mock.collected, 2)
assert.Contains(t, mock.collected[0].Messages, tplMessageTest2)
assert.Contains(t, mock.collected[0].Messages, tplMessageTest3)
assert.Len(t, mock.collected[0].Messages, 2)
assert.Contains(t, mock.collected[1].Messages, tplMessageTest4)
assert.Len(t, mock.collected[1].Messages, 1)
}
func TestConvert_failsWhenNotConverting(t *testing.T) {
a := assert.New(t)
2025-01-08 21:48:10 +00:00
tested := MakeConvert(func(in int) GenericMessage {
a.Equal(in, 1)
return GenericMessage{}
})
mock := &GenericSyncMockFilter[int]{}
a.Panics(func() {
tested.Then(mock)
tested.Call(1)
})
}
func TestConvert(t *testing.T) {
a := assert.New(t)
numCalled := 0
2025-01-08 21:48:10 +00:00
tested := MakeConvert(func(in int) GenericMessage {
a.Equal(in, 1)
numCalled += 1
return GenericMessage{}
})
mock := &SyncMockFilter{}
tested.ConvertTo(mock)
tested.Call(1)
a.Equal(numCalled, 1)
}