|
- package decoder
-
- import (
- "context"
- "testing"
-
- "github.com/AFASystems/presence/internal/pkg/common/appcontext"
- "github.com/AFASystems/presence/internal/pkg/model"
- "github.com/segmentio/kafka-go"
- )
-
- // MockKafkaWriter is a mock implementation of kafkaWriter for testing
- type MockKafkaWriter struct {
- Messages []kafka.Message
- }
-
- func (m *MockKafkaWriter) WriteMessages(ctx context.Context, msgs ...kafka.Message) error {
- m.Messages = append(m.Messages, msgs...)
- return nil
- }
-
- // TestHelper provides utility functions for decoder testing
- type TestHelper struct {
- t *testing.T
- appState *appcontext.AppState
- parserRegistry *model.ParserRegistry
- }
-
- // NewTestHelper creates a new test helper instance
- func NewTestHelper(t *testing.T) *TestHelper {
- return &TestHelper{
- t: t,
- appState: appcontext.NewAppState(),
- parserRegistry: &model.ParserRegistry{},
- }
- }
-
- // GetAppState returns the appState instance
- func (th *TestHelper) GetAppState() *appcontext.AppState {
- return th.appState
- }
-
- // GetParserRegistry returns the parser registry
- func (th *TestHelper) GetParserRegistry() *model.ParserRegistry {
- return th.parserRegistry
- }
-
- // RegisterTestParser registers a parser with default test configuration
- func (th *TestHelper) RegisterTestParser(name string) {
- config := model.Config{
- Name: name,
- Min: 2,
- Max: 20,
- Pattern: []string{"02"},
- Configs: map[string]model.ParserConfig{
- "length": {Length: 2, Offset: 0, Order: "big"},
- },
- }
- th.parserRegistry.Register(name, config)
- }
-
- // CreateBeaconAdvertisement creates a test beacon advertisement
- func (th *TestHelper) CreateBeaconAdvertisement(id, data string) model.BeaconAdvertisement {
- return model.BeaconAdvertisement{
- ID: id,
- Data: data,
- }
- }
-
- // CreateValidHexAdvertisement creates a beacon with valid hex data
- func (th *TestHelper) CreateValidHexAdvertisement(id string) model.BeaconAdvertisement {
- return model.BeaconAdvertisement{
- ID: id,
- Data: "020106",
- }
- }
-
- // CreateInvalidHexAdvertisement creates a beacon with invalid hex data
- func (th *TestHelper) CreateInvalidHexAdvertisement(id string) model.BeaconAdvertisement {
- return model.BeaconAdvertisement{
- ID: id,
- Data: "INVALID_HEX",
- }
- }
-
- // CreateEmptyAdvertisement creates a beacon with empty data
- func (th *TestHelper) CreateEmptyAdvertisement(id string) model.BeaconAdvertisement {
- return model.BeaconAdvertisement{
- ID: id,
- Data: "",
- }
- }
-
- // AssertParserExists asserts that a parser exists in the registry
- func (th *TestHelper) AssertParserExists(name string) {
- if _, exists := th.parserRegistry.ParserList[name]; !exists {
- th.t.Errorf("Parser '%s' should exist in registry", name)
- }
- }
-
- // AssertParserNotExists asserts that a parser does not exist in the registry
- func (th *TestHelper) AssertParserNotExists(name string) {
- if _, exists := th.parserRegistry.ParserList[name]; exists {
- th.t.Errorf("Parser '%s' should not exist in registry", name)
- }
- }
-
- // AssertEventExists asserts that an event exists in appState
- func (th *TestHelper) AssertEventExists(id string) model.BeaconEvent {
- event, exists := th.appState.GetBeaconEvent(id)
- if !exists {
- th.t.Errorf("Event for beacon '%s' should exist in appState", id)
- return model.BeaconEvent{}
- }
- return event
- }
-
- // AssertEventNotExists asserts that an event does not exist in appState
- func (th *TestHelper) AssertEventNotExists(id string) {
- _, exists := th.appState.GetBeaconEvent(id)
- if exists {
- th.t.Errorf("Event for beacon '%s' should not exist in appState", id)
- }
- }
-
- // AssertParserCount asserts the number of parsers in the registry
- func (th *TestHelper) AssertParserCount(expected int) {
- if len(th.parserRegistry.ParserList) != expected {
- th.t.Errorf("Expected %d parsers in registry, got %d", expected, len(th.parserRegistry.ParserList))
- }
- }
-
- // Helper functions for creating test configurations
-
- // CreateTestConfig creates a test parser configuration
- func CreateTestConfig(name string, min, max int, pattern []string) model.Config {
- return model.Config{
- Name: name,
- Min: min,
- Max: max,
- Pattern: pattern,
- Configs: map[string]model.ParserConfig{
- "length": {Length: 2, Offset: 0, Order: "big"},
- },
- }
- }
-
- // CreateKafkaParserMessage creates a Kafka parser message for testing
- func CreateKafkaParserMessage(id, name string, config model.Config) model.KafkaParser {
- return model.KafkaParser{
- ID: id,
- Name: name,
- Config: config,
- }
- }
-
- // AssertNoError asserts that an error is nil
- func AssertNoError(t *testing.T, err error, msg string) {
- if err != nil {
- t.Errorf("%s: %v", msg, err)
- }
- }
-
- // AssertError asserts that an error is not nil
- func AssertError(t *testing.T, err error, msg string) {
- if err == nil {
- t.Errorf("%s: expected error but got nil", msg)
- }
- }
-
- // Common test data
-
- // Valid hex strings for testing
- var ValidHexStrings = []string{
- "020106", // Simple AD structure
- "0201060302A0", // AD structure with flags
- "1AFF0C01", // iBeacon-like data
- "0201061AFF0C01", // Multiple AD structures
- }
-
- // Invalid hex strings for testing
- var InvalidHexStrings = []string{
- "INVALID_HEX",
- "02016ZZZ",
- "GGGGGG",
- "NOT-HEX",
- }
-
- // Empty or whitespace data for testing
- var EmptyTestData = []string{
- "",
- " ",
- "\t\n",
- }
-
- // CreateMockWriter creates a mock Kafka writer
- func CreateMockWriter() *MockKafkaWriter {
- return &MockKafkaWriter{Messages: []kafka.Message{}}
- }
-
- // Beacon event test helpers
-
- // AssertEventFields asserts that event fields match expected values
- func AssertEventFields(t *testing.T, event model.BeaconEvent, expectedID, expectedType string) {
- if event.ID != expectedID {
- t.Errorf("Expected event ID '%s', got '%s'", expectedID, event.ID)
- }
-
- if event.Type != expectedType {
- t.Errorf("Expected event type '%s', got '%s'", expectedType, event.Type)
- }
- }
-
- // SetupTestParsers registers a standard set of test parsers
- func SetupTestParsers(registry *model.ParserRegistry) {
- parsers := []model.Config{
- {Name: "parser-1", Min: 2, Max: 20, Pattern: []string{"02"}},
- {Name: "parser-2", Min: 3, Max: 25, Pattern: []string{"03"}},
- {Name: "parser-3", Min: 4, Max: 30, Pattern: []string{"04"}},
- }
-
- for _, p := range parsers {
- registry.Register(p.Name, p)
- }
- }
-
- // CleanupTestParsers removes all parsers from the registry
- func CleanupTestParsers(registry *model.ParserRegistry) {
- for name := range registry.ParserList {
- registry.Unregister(name)
- }
- }
-
- // CreateTestBeaconEvent creates a test beacon event
- func CreateTestBeaconEvent(id, eventType string) model.BeaconEvent {
- return model.BeaconEvent{
- ID: id,
- Type: eventType,
- Battery: 100,
- Event: 1,
- AccX: 0,
- AccY: 0,
- AccZ: 0,
- }
- }
-
- // AssertKafkaMessageCount asserts the number of Kafka messages
- func AssertKafkaMessageCount(t *testing.T, writer *MockKafkaWriter, expected int) {
- if len(writer.Messages) != expected {
- t.Errorf("Expected %d Kafka message(s), got %d", expected, len(writer.Messages))
- }
- }
-
- // AssertNoKafkaMessages asserts that no messages were written to Kafka
- func AssertNoKafkaMessages(t *testing.T, writer *MockKafkaWriter) {
- AssertKafkaMessageCount(t, writer, 0)
- }
-
- // Parser registry test helpers
-
- // SimulateEventLoopParserUpdate simulates the event loop's parser update logic
- func SimulateEventLoopParserUpdate(msg model.KafkaParser, registry *model.ParserRegistry) {
- switch msg.ID {
- case "add":
- config := msg.Config
- registry.Register(config.Name, config)
- case "delete":
- registry.Unregister(msg.Name)
- case "update":
- config := msg.Config
- registry.Register(config.Name, config)
- }
- }
-
- // CreateParserAddMessage creates a parser add message
- func CreateParserAddMessage(name string, min, max int) model.KafkaParser {
- return model.KafkaParser{
- ID: "add",
- Name: name,
- Config: model.Config{
- Name: name,
- Min: min,
- Max: max,
- Pattern: []string{"02"},
- },
- }
- }
-
- // CreateParserDeleteMessage creates a parser delete message
- func CreateParserDeleteMessage(name string) model.KafkaParser {
- return model.KafkaParser{
- ID: "delete",
- Name: name,
- }
- }
-
- // CreateParserUpdateMessage creates a parser update message
- func CreateParserUpdateMessage(name string, min, max int) model.KafkaParser {
- return model.KafkaParser{
- ID: "update",
- Name: name,
- Config: model.Config{
- Name: name,
- Min: min,
- Max: max,
- Pattern: []string{"02"},
- },
- }
- }
-
- // GenerateTestBeaconID generates a test beacon ID
- func GenerateTestBeaconID(index int) string {
- return "test-beacon-" + string(rune('A'+index))
- }
-
- // GenerateTestHexData generates test hex data
- func GenerateTestHexData(index int) string {
- prefix := "02"
- value := string(rune('6' + index))
- return prefix + "01" + value
- }
|