package main import ( "testing" "time" "frame" "gocv.io/x/gocv" ) func makeMotionClip(t *testing.T, fill0, fill1 float64) frame.Clip { t.Helper() mat := gocv.NewMatWithSize(4, 4, gocv.MatTypeCV8UC1) defer mat.Close() mat.SetTo(gocv.NewScalar(fill0, 0, 0, 0)) bytes0 := mat.ToBytes() mat.SetTo(gocv.NewScalar(fill1, 0, 0, 0)) bytes1 := mat.ToBytes() return frame.Clip{ PixelMats: [][]byte{bytes0, bytes1}, Width: 4, Height: 4, Types: gocv.MatTypeCV8UC1, Channels: 1, Guids: [][]byte{{1}, {2}}, Timestamps: []uint64{0, 1}, } } func TestClassifyClip_MotionGateDropsBelowThreshold(t *testing.T) { clip := makeMotionClip(t, 0, 0) sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, nil, 50, "") select { case <-sendoff: t.Error("clip should have been dropped by motion gate (0% motion, threshold 50%)") default: } } func TestClassifyClip_MotionGatePassesForwardsWithoutDetections(t *testing.T) { clip := makeMotionClip(t, 0, 255) sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, nil, 0, "") select { case <-sendoff: case <-time.After(5 * time.Second): t.Error("motion clip with no detections should still be forwarded") } } func TestClassifyClip_NoClassifiersForwards(t *testing.T) { clip := makeMotionClip(t, 0, 255) sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, []frame.Classifier{}, 0, "") select { case <-sendoff: case <-time.After(5 * time.Second): t.Error("motion clip with empty classifier list should still be forwarded") } } func TestClassifyClip_WithPassphrase(t *testing.T) { mat := gocv.NewMatWithSize(4, 4, gocv.MatTypeCV8UC1) defer mat.Close() mat.SetTo(gocv.NewScalar(100, 0, 0, 0)) plainBytes := mat.ToBytes() f := frame.Frame{ PixelBytes: plainBytes, Width: 4, Height: 4, GocvImageType: gocv.MatTypeCV8UC1, Channels: 1, Guid: []byte{1}, Timestamp: 0, } if err := f.Encrypt("test-pass"); err != nil { t.Fatalf("encrypt: %v", err) } encryptedBytes := make([]byte, len(f.PixelBytes)) copy(encryptedBytes, f.PixelBytes) f2 := frame.Frame{ PixelBytes: plainBytes, Width: 4, Height: 4, GocvImageType: gocv.MatTypeCV8UC1, Channels: 1, Guid: []byte{2}, Timestamp: 1, } if err := f2.Encrypt("test-pass"); err != nil { t.Fatalf("encrypt: %v", err) } encryptedBytes2 := make([]byte, len(f2.PixelBytes)) copy(encryptedBytes2, f2.PixelBytes) clip := frame.Clip{ PixelMats: [][]byte{encryptedBytes, encryptedBytes2}, Width: 4, Height: 4, Types: gocv.MatTypeCV8UC1, Channels: 1, Guids: [][]byte{{1}, {2}}, Timestamps: []uint64{0, 1}, } sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, nil, 0, "test-pass") select { case <-sendoff: case <-time.After(5 * time.Second): t.Error("motion clip with passphrase should decrypt and forward even without detections") } } func TestClassifyClip_ZeroMotionForwardsAtZeroThreshold(t *testing.T) { clip := makeMotionClip(t, 0, 0) sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, nil, 0, "") select { case <-sendoff: case <-time.After(5 * time.Second): t.Error("with threshold 0 the motion gate does not drop; clip should forward") } } func TestClassifyClip_PassphraseWrongKey(t *testing.T) { f := frame.Frame{ PixelBytes: []byte{1, 2, 3, 4}, Width: 2, Height: 2, GocvImageType: gocv.MatTypeCV8UC1, Channels: 1, Guid: []byte{1}, Timestamp: 0, } if err := f.Encrypt("real-key"); err != nil { t.Fatalf("encrypt: %v", err) } clip := frame.Clip{ PixelMats: [][]byte{f.PixelBytes}, Width: 2, Height: 2, Types: gocv.MatTypeCV8UC1, Channels: 1, Guids: [][]byte{{1}}, Timestamps: []uint64{0}, } sendoff := make(chan frame.Clip, 1) classifyClip(clip, sendoff, nil, 0, "wrong-key") select { case <-sendoff: t.Error("clip with wrong passphrase should not be forwarded") default: } }