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) {
|
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-13 22:20:15 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-24 17:39:12 +00:00
|
|
|
for e := range FilterByTypeOrIndex(testEvents, &wg, []SatelChangeType{{satel.ArmedPartition}, {satel.PartitionFireAlarm}}, []int{}) {
|
2024-02-13 22:20:15 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.DoorOpened, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.PartitionAlarm, 3, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.PartitionFireAlarm, 4, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.TroublePart1, 5, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ZoneTamper, 6, true)
|
2024-02-13 22:20:15 +00:00
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, 2)
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 1, true))
|
|
|
|
assert.Contains(t, receivedEvents, 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) {
|
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-18 17:44:08 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-24 17:39:12 +00:00
|
|
|
for e := range FilterByTypeOrIndex(testEvents, &wg, []SatelChangeType{}, []int{}) {
|
2024-02-18 17:44:08 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for index, ct := range SUPPORTED_CHANGE_TYPES {
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(ct, index, true)
|
2024-02-18 17:44:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, len(SUPPORTED_CHANGE_TYPES))
|
|
|
|
for index, ct := range SUPPORTED_CHANGE_TYPES {
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, 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) {
|
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-18 18:00:49 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-24 17:39:12 +00:00
|
|
|
for e := range FilterByTypeOrIndex(testEvents, &wg, []SatelChangeType{}, []int{1, 3}) {
|
2024-02-18 18:00:49 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.DoorOpened, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.PartitionAlarm, 3, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.PartitionFireAlarm, 4, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.TroublePart1, 5, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ZoneTamper, 6, true)
|
2024-02-18 18:00:49 +00:00
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, 2)
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 1, true))
|
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.PartitionAlarm, 3, true))
|
2024-02-18 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSatelIndexFiltering_NoAllowedEventTypesMeansAllAreAllowed(t *testing.T) {
|
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
myReasonableMaxIndex := 100 // I wanted to use math.MaxInt at first, but it's kind of a waste of time here
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-18 18:00:49 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-24 17:39:12 +00:00
|
|
|
for e := range FilterByTypeOrIndex(testEvents, &wg, []SatelChangeType{}, []int{}) {
|
2024-02-18 18:00:49 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for i := 0; i < myReasonableMaxIndex; i++ {
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, i, true)
|
2024-02-18 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, myReasonableMaxIndex)
|
|
|
|
for i := 0; i < myReasonableMaxIndex; i++ {
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, 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())
|
2024-02-14 20:34:16 +00:00
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
2024-02-28 20:26:20 +00:00
|
|
|
fakeLog := log.New(io.Discard, "", log.Ltime)
|
|
|
|
ds := MakeDataStore(fakeLog, tempFileName)
|
2024-02-14 20:34:16 +00:00
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-14 20:34:16 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-10 09:12:04 +00:00
|
|
|
for e := range FilterByLastSeen(testEvents, &wg, &ds, fakeLog) {
|
2024-02-14 20:34:16 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
2024-02-14 20:34:16 +00:00
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, 3)
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 1, true))
|
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 2, true))
|
|
|
|
assert.Contains(t, receivedEvents, 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())
|
|
|
|
testEvents := make(chan satel.Event)
|
|
|
|
receivedEvents := make([]satel.Event, 0)
|
|
|
|
wg := sync.WaitGroup{}
|
2024-02-28 20:26:20 +00:00
|
|
|
fakeLog := log.New(io.Discard, "", log.Ltime)
|
|
|
|
ds := MakeDataStore(fakeLog, tempFileName)
|
2024-02-15 19:06:06 +00:00
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-15 19:06:06 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-10 09:12:04 +00:00
|
|
|
for e := range FilterByLastSeen(testEvents, &wg, &ds, fakeLog) {
|
2024-02-15 19:06:06 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
2024-02-15 19:06:06 +00:00
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, 3)
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 1, true))
|
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 2, true))
|
|
|
|
assert.Contains(t, receivedEvents, makeTestSatelEvent(satel.ArmedPartition, 1, false))
|
2024-02-15 19:06:06 +00:00
|
|
|
|
|
|
|
testEvents = make(chan satel.Event)
|
|
|
|
receivedEvents = make([]satel.Event, 0)
|
2024-02-28 20:26:20 +00:00
|
|
|
ds = MakeDataStore(fakeLog, tempFileName)
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-15 19:06:06 +00:00
|
|
|
go func() {
|
2025-01-02 12:40:25 +00:00
|
|
|
defer wg.Done()
|
|
|
|
|
2024-03-10 09:12:04 +00:00
|
|
|
for e := range FilterByLastSeen(testEvents, &wg, &ds, fakeLog) {
|
2024-02-15 19:06:06 +00:00
|
|
|
receivedEvents = append(receivedEvents, e)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
receivedEvents = make([]satel.Event, 0)
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, false)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 1, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
|
|
|
testEvents <- makeTestSatelEvent(satel.ArmedPartition, 2, true)
|
2024-02-15 19:06:06 +00:00
|
|
|
|
|
|
|
close(testEvents)
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
assert.Len(t, receivedEvents, 1)
|
2024-03-05 21:30:48 +00:00
|
|
|
assert.Contains(t, receivedEvents, 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
|
|
|
|
}
|
|
|
|
|
2025-01-06 13:55:08 +00:00
|
|
|
type SyncMockFilter struct {
|
2025-01-06 22:29:54 +00:00
|
|
|
SyncFilterImpl[GenericMessage]
|
2025-01-06 13:55:08 +00:00
|
|
|
collected []GenericMessage
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *SyncMockFilter) Call(msg GenericMessage) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|