Quellcode durchsuchen

fix: tests

master
Blaz Smehov vor 4 Tagen
Ursprung
Commit
536c959d76
19 geänderte Dateien mit 140 neuen und 121 gelöschten Zeilen
  1. +5
    -0
      internal/app/server/events.go
  2. +39
    -35
      internal/pkg/service/beacon_service.go
  3. BIN
      location
  4. BIN
      server
  5. +5
    -6
      tests/appcontext/appcontext_test.go
  6. +2
    -2
      tests/bridge/bridge_test.go
  7. +5
    -3
      tests/bridge/event_loop_test.go
  8. +2
    -2
      tests/bridge/integration_test.go
  9. +5
    -5
      tests/bridge/mqtt_handler_test.go
  10. +1
    -1
      tests/bridge/testutil.go
  11. +15
    -8
      tests/controller/controller_test.go
  12. +12
    -12
      tests/decoder/decode_test.go
  13. +3
    -3
      tests/decoder/decoder_test.go
  14. +7
    -7
      tests/decoder/event_loop_test.go
  15. +8
    -8
      tests/decoder/integration_test.go
  16. +17
    -17
      tests/decoder/testutil.go
  17. +2
    -2
      tests/location/location_test.go
  18. +6
    -5
      tests/model/model_test.go
  19. +6
    -5
      tests/utils/utils_test.go

+ 5
- 0
internal/app/server/events.go Datei anzeigen

@@ -3,6 +3,7 @@ package server
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"time"

@@ -55,6 +56,10 @@ func RunEventLoop(ctx context.Context, a *ServerApp) {
slog.Error("saving decoder event for beacon", "id", id, "err", err)
continue
}
if msg.Type == "Eddystone" && msg.Battery < 3000 {
fmt.Printf("Sending alert for battery low: %+v\n", msg)
service.SendAlert(id, "BatteryLow", a.KafkaManager.GetWriter("alert"), ctx, a.DB)
}
case <-beaconTicker.C:
var list []model.Tracker
a.DB.Find(&list)


+ 39
- 35
internal/pkg/service/beacon_service.go Datei anzeigen

@@ -88,7 +88,7 @@ func LocationToBeaconService(msg model.HTTPLocation, db *gorm.DB, writer *kafka.
return
}

sendAlert(gw.ID, msg.ID, writer, ctx, allowedZones, db)
sendRestrictedZoneAlert(gw.ID, msg.ID, writer, ctx, allowedZones, db)
}

func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafka.Writer, ctx context.Context) {
@@ -126,48 +126,52 @@ func LocationToBeaconServiceAI(msg model.HTTPLocation, db *gorm.DB, writer *kafk
return
}

sendAlert(gw.ID, tracker.ID, writer, ctx, allowedZones, db)
sendRestrictedZoneAlert(gw.ID, tracker.ID, writer, ctx, allowedZones, db)
}

func sendAlert(gwId, trackerId string, writer *kafka.Writer, ctx context.Context, allowedZones []string, db *gorm.DB) {
if len(allowedZones) != 0 && !slices.Contains(allowedZones, gwId) {
var existingAlert model.Alert
result := db.Select("status").Where("tracker_id = ? AND type = ?", trackerId, "Restricted zone").Order("timestamp DESC").First(&existingAlert)

if result.Error == gorm.ErrRecordNotFound || existingAlert.Status == "resolved" {
alert := model.Alert{
ID: uuid.New().String(),
TrackerID: trackerId,
Type: "Restricted zone",
Status: "new",
Timestamp: time.Now(),
}
func SendAlert(trackerId, alertType string, writer *kafka.Writer, ctx context.Context, db *gorm.DB) {
var existingAlert model.Alert
result := db.Select("status").Where("tracker_id = ? AND type = ?", trackerId, alertType).Order("timestamp DESC").First(&existingAlert)

if result.Error == gorm.ErrRecordNotFound || existingAlert.Status == "resolved" {
alert := model.Alert{
ID: uuid.New().String(),
TrackerID: trackerId,
Type: alertType,
Status: "new",
Timestamp: time.Now(),
}

if err := InsertAlert(alert, db, ctx); err != nil {
msg := fmt.Sprintf("Error in inserting alert: %v", err)
slog.Error(msg)
return
}
if err := InsertAlert(alert, db, ctx); err != nil {
msg := fmt.Sprintf("Error in inserting alert: %v", err)
slog.Error(msg)
return
}

eMsg, err := json.Marshal(alert)
if err != nil {
msg := "Error in marshaling"
eMsg, err := json.Marshal(alert)
if err != nil {
msg := "Error in marshaling"
slog.Error(msg)
return
} else {
msg := kafka.Message{
Value: eMsg,
}
if err := kafkaclient.Write(ctx, writer, msg); err != nil {
msg := fmt.Sprintf("Error in writing message: %v", err)
slog.Error(msg)
return
} else {
msg := kafka.Message{
Value: eMsg,
}
if err := kafkaclient.Write(ctx, writer, msg); err != nil {
msg := fmt.Sprintf("Error in writing message: %v", err)
slog.Error(msg)
return
}
}
return
} else {
return
}
return
} else {
return
}
}

func sendRestrictedZoneAlert(gwId, trackerId string, writer *kafka.Writer, ctx context.Context, allowedZones []string, db *gorm.DB) {
if len(allowedZones) != 0 && !slices.Contains(allowedZones, gwId) {
SendAlert(trackerId, "Restricted zone", writer, ctx, db)
}
}



BIN
location Datei anzeigen


BIN
server Datei anzeigen


+ 5
- 6
tests/appcontext/appcontext_test.go Datei anzeigen

@@ -5,7 +5,6 @@ import (
"testing"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/model"
)

func TestNewAppState(t *testing.T) {
@@ -64,7 +63,7 @@ func TestBeaconLookup_CleanLookup(t *testing.T) {

func TestBeacon_GetAndUpdate(t *testing.T) {
state := appcontext.NewAppState()
beacon := model.Beacon{
beacon := appcontext.Beacon{
ID: "test-beacon",
Name: "Test",
}
@@ -81,7 +80,7 @@ func TestBeacon_GetAndUpdate(t *testing.T) {

func TestBeaconEvent_GetAndUpdate(t *testing.T) {
state := appcontext.NewAppState()
event := model.BeaconEvent{
event := appcontext.BeaconEvent{
ID: "beacon-1",
Type: "iBeacon",
Battery: 85,
@@ -99,8 +98,8 @@ func TestBeaconEvent_GetAndUpdate(t *testing.T) {

func TestGetAllBeacons(t *testing.T) {
state := appcontext.NewAppState()
state.UpdateBeacon("b1", model.Beacon{ID: "b1"})
state.UpdateBeacon("b2", model.Beacon{ID: "b2"})
state.UpdateBeacon("b1", appcontext.Beacon{ID: "b1"})
state.UpdateBeacon("b2", appcontext.Beacon{ID: "b2"})

all := state.GetAllBeacons()
if len(all) != 2 {
@@ -111,7 +110,7 @@ func TestGetAllBeacons(t *testing.T) {
func TestUpdateSettings(t *testing.T) {
state := appcontext.NewAppState()
state.UpdateSettings(map[string]any{
"current_algorithm": "ai",
"current_algorithm": "ai",
"location_confidence": int64(5),
})



+ 2
- 2
tests/bridge/bridge_test.go Datei anzeigen

@@ -9,8 +9,8 @@ import (

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/model"
"github.com/segmentio/kafka-go"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/segmentio/kafka-go"
)

// mqtthandler is extracted from main.go for testing purposes
@@ -36,7 +36,7 @@ func mqtthandler(writer kafkaWriter, topic string, message []byte, appState *app
continue
}

adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: val,
Hostname: hostname,
MAC: reading.MAC,


+ 5
- 3
tests/bridge/event_loop_test.go Datei anzeigen

@@ -180,9 +180,11 @@ func TestEventLoop_AlertMessage(t *testing.T) {

// Create an alert message
msg := model.Alert{
ID: "tracker-123",
Type: "battery_low",
Value: "15",
ID: "tracker-123",
Type: "battery_low",
Status: "new",
Timestamp: time.Now(),
TrackerID: "tracker-123",
}

go func() {


+ 2
- 2
tests/bridge/integration_test.go Datei anzeigen

@@ -75,7 +75,7 @@ func TestIntegration_EndToEnd(t *testing.T) {
}

// Verify
var adv model.BeaconAdvertisement
var adv appcontext.BeaconAdvertisement
err = json.Unmarshal(msg.Value, &adv)
if err != nil {
t.Fatalf("Failed to unmarshal beacon advertisement: %v", err)
@@ -155,7 +155,7 @@ func TestIntegration_MultipleMessages(t *testing.T) {
t.Fatalf("Failed to read message %d from Kafka: %v", i+1, err)
}

var adv model.BeaconAdvertisement
var adv appcontext.BeaconAdvertisement
err = json.Unmarshal(msg.Value, &adv)
if err != nil {
t.Fatalf("Failed to unmarshal beacon advertisement %d: %v", i+1, err)


+ 5
- 5
tests/bridge/mqtt_handler_test.go Datei anzeigen

@@ -35,7 +35,7 @@ func TestMQTTHandler_SingleReading(t *testing.T) {
t.Errorf("Expected 1 message, got %d", len(mockWriter.Messages))
}

var adv model.BeaconAdvertisement
var adv appcontext.BeaconAdvertisement
err := json.Unmarshal(mockWriter.Messages[0].Value, &adv)
if err != nil {
t.Fatalf("Failed to unmarshal beacon advertisement: %v", err)
@@ -175,8 +175,8 @@ func TestMQTTHandler_HostnameExtraction(t *testing.T) {

// Test various topic formats
testCases := []struct {
topic string
expectedHost string
topic string
expectedHost string
}{
{"publish_out/gateway-1", "gateway-1"},
{"publish_out/gateway-prod-02", "gateway-prod-02"},
@@ -202,7 +202,7 @@ func TestMQTTHandler_HostnameExtraction(t *testing.T) {
t.Fatalf("Expected 1 message, got %d", len(mockWriter.Messages))
}

var adv model.BeaconAdvertisement
var adv appcontext.BeaconAdvertisement
err := json.Unmarshal(mockWriter.Messages[0].Value, &adv)
if err != nil {
t.Fatalf("Failed to unmarshal beacon advertisement: %v", err)
@@ -242,7 +242,7 @@ func TestMQTTHandler_PreservesRawData(t *testing.T) {
t.Fatalf("Expected 1 message, got %d", len(mockWriter.Messages))
}

var adv model.BeaconAdvertisement
var adv appcontext.BeaconAdvertisement
err := json.Unmarshal(mockWriter.Messages[0].Value, &adv)
if err != nil {
t.Fatalf("Failed to unmarshal beacon advertisement: %v", err)


+ 1
- 1
tests/bridge/testutil.go Datei anzeigen

@@ -94,7 +94,7 @@ func (th *TestHelper) CreateMQTTMessage(topic string, readings []model.RawReadin
}

// AssertBeaconAdvertisement asserts that a beacon advertisement matches expected values
func (th *TestHelper) AssertBeaconAdvertisement(adv model.BeaconAdvertisement, expectedID, expectedHostname, expectedMAC string, expectedRSSI int64) {
func (th *TestHelper) AssertBeaconAdvertisement(adv appcontext.BeaconAdvertisement, expectedID, expectedHostname, expectedMAC string, expectedRSSI int64) {
if adv.ID != expectedID {
th.t.Errorf("Expected ID '%s', got '%s'", expectedID, adv.ID)
}


+ 15
- 8
tests/controller/controller_test.go Datei anzeigen

@@ -2,11 +2,13 @@ package controller

import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/controller"
"github.com/AFASystems/presence/internal/pkg/model"
"github.com/gorilla/mux"
@@ -19,7 +21,7 @@ func setupTestDB(t *testing.T) *gorm.DB {
if err != nil {
t.Fatalf("Failed to open test DB: %v", err)
}
if err := db.AutoMigrate(&model.Gateway{}, &model.Zone{}, &model.Tracker{}, &model.TrackerZones{}, &model.Config{}, &model.Settings{}, &model.Tracks{}); err != nil {
if err := db.AutoMigrate(&model.Gateway{}, &model.Zone{}, &model.Tracker{}, &model.TrackerZones{}, &model.Config{}, appcontext.Settings{}, &model.Tracks{}); err != nil {
t.Fatalf("Failed to migrate: %v", err)
}
return db
@@ -27,7 +29,8 @@ func setupTestDB(t *testing.T) *gorm.DB {

func TestGatewayListController_Empty(t *testing.T) {
db := setupTestDB(t)
handler := controller.GatewayListController(db)
context := context.Background()
handler := controller.GatewayListController(db, context)

req := httptest.NewRequest(http.MethodGet, "/gateways", nil)
rec := httptest.NewRecorder()
@@ -47,7 +50,8 @@ func TestGatewayListController_Empty(t *testing.T) {

func TestGatewayAddController(t *testing.T) {
db := setupTestDB(t)
handler := controller.GatewayAddController(db)
context := context.Background()
handler := controller.GatewayAddController(db, context)

gateway := model.Gateway{
ID: "gw-1",
@@ -77,11 +81,11 @@ func TestGatewayAddController(t *testing.T) {
func TestGatewayDeleteController(t *testing.T) {
db := setupTestDB(t)
db.Create(&model.Gateway{ID: "gw-1", Name: "G1", MAC: "AA:BB:CC:DD:EE:FF"})
context := context.Background()
req := httptest.NewRequest(http.MethodDelete, "/gateways/gw-1", nil)
req = mux.SetURLVars(req, map[string]string{"id": "gw-1"})
rec := httptest.NewRecorder()
controller.GatewayDeleteController(db).ServeHTTP(rec, req)
controller.GatewayDeleteController(db, context).ServeHTTP(rec, req)

if rec.Code != http.StatusOK {
t.Errorf("Expected 200, got %d", rec.Code)
@@ -96,7 +100,8 @@ func TestGatewayDeleteController(t *testing.T) {

func TestTrackerListController_Empty(t *testing.T) {
db := setupTestDB(t)
handler := controller.TrackerList(db)
context := context.Background()
handler := controller.TrackerList(db, context)

req := httptest.NewRequest(http.MethodGet, "/trackers", nil)
rec := httptest.NewRecorder()
@@ -116,7 +121,8 @@ func TestTrackerListController_Empty(t *testing.T) {

func TestZoneListController_Empty(t *testing.T) {
db := setupTestDB(t)
handler := controller.ZoneListController(db)
context := context.Background()
handler := controller.ZoneListController(db, context)

req := httptest.NewRequest(http.MethodGet, "/zones", nil)
rec := httptest.NewRecorder()
@@ -129,7 +135,8 @@ func TestZoneListController_Empty(t *testing.T) {

func TestSettingsListController(t *testing.T) {
db := setupTestDB(t)
handler := controller.SettingsListController(db)
context := context.Background()
handler := controller.SettingsListController(db, context)

req := httptest.NewRequest(http.MethodGet, "/settings", nil)
rec := httptest.NewRecorder()


+ 12
- 12
tests/decoder/decode_test.go Datei anzeigen

@@ -15,7 +15,7 @@ func TestDecodeBeacon_EmptyData(t *testing.T) {
mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}

adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "", // Empty data
}
@@ -39,7 +39,7 @@ func TestDecodeBeacon_WhitespaceOnly(t *testing.T) {
mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}

adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: " ", // Whitespace only
}
@@ -63,7 +63,7 @@ func TestDecodeBeacon_InvalidHex(t *testing.T) {
mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}

adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "INVALID_HEX_DATA!!!",
}
@@ -88,7 +88,7 @@ func TestDecodeBeacon_ValidHexNoParser(t *testing.T) {
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)} // No parsers registered

// Valid hex but no matching parser (03 02 FF 06 - type 0x02, no parser registered for it)
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "0302FF06", // Valid AD structure
}
@@ -126,7 +126,7 @@ func TestDecodeBeacon_Deduplication(t *testing.T) {
parserRegistry.Register("test-parser", config)

// Create an event that will be parsed (03 02 FF 06 - not removed by RemoveFlagBytes)
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "0302FF06",
}
@@ -171,7 +171,7 @@ func TestDecodeBeacon_DifferentDataPublishes(t *testing.T) {
parserRegistry.Register("test-parser", config)

// First processing
adv1 := model.BeaconAdvertisement{
adv1 := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "020106",
}
@@ -184,7 +184,7 @@ func TestDecodeBeacon_DifferentDataPublishes(t *testing.T) {
firstMessageCount := len(mockWriter.Messages)

// Second processing with different data - should publish again
adv2 := model.BeaconAdvertisement{
adv2 := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "0302FF07", // Different data
}
@@ -220,7 +220,7 @@ func TestDecodeBeacon_WithFlagBytes(t *testing.T) {
parserRegistry.Register("test-parser", config)

// Data with flag bytes first (02 01 06), then our structure (03 02 FF 08)
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "0201060302FF08", // Flags removed, then 03 02 FF 08 remains
}
@@ -254,7 +254,7 @@ func TestDecodeBeacon_MultipleBeacons(t *testing.T) {
parserRegistry.Register("test-parser", config)

// Process multiple different beacons (03 02 FF xx - not removed by RemoveFlagBytes)
beacons := []model.BeaconAdvertisement{
beacons := []appcontext.BeaconAdvertisement{
{ID: "beacon-1", Data: "0302FF06"},
{ID: "beacon-2", Data: "0302FF07"},
{ID: "beacon-3", Data: "0302FF08"},
@@ -280,7 +280,7 @@ func TestProcessIncoming_ErrorHandling(t *testing.T) {
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}

// Invalid data that will cause an error
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "INVALID_HEX",
}
@@ -313,7 +313,7 @@ func TestDecodeBeacon_EventHashing(t *testing.T) {
}
parserRegistry.Register("test-parser", config)

adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "0302FF06",
}
@@ -369,7 +369,7 @@ func TestDecodeBeacon_VariousHexFormats(t *testing.T) {

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: tc.hexData,
}


+ 3
- 3
tests/decoder/decoder_test.go Datei anzeigen

@@ -14,7 +14,7 @@ import (
)

// processIncoming processes incoming beacon advertisements
func processIncoming(adv model.BeaconAdvertisement, appState *appcontext.AppState, writer kafkaWriter, parserRegistry *model.ParserRegistry) {
func processIncoming(adv appcontext.BeaconAdvertisement, appState *appcontext.AppState, writer kafkaWriter, parserRegistry *model.ParserRegistry) {
err := decodeBeacon(adv, appState, writer, parserRegistry)
if err != nil {
eMsg := fmt.Sprintf("Error in decoding: %v", err)
@@ -24,7 +24,7 @@ func processIncoming(adv model.BeaconAdvertisement, appState *appcontext.AppStat
}

// decodeBeacon decodes beacon data and publishes events
func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, writer kafkaWriter, parserRegistry *model.ParserRegistry) error {
func decodeBeacon(adv appcontext.BeaconAdvertisement, appState *appcontext.AppState, writer kafkaWriter, parserRegistry *model.ParserRegistry) error {
beacon := strings.TrimSpace(adv.Data)
id := adv.ID
if beacon == "" {
@@ -39,7 +39,7 @@ func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState,
b = utils.RemoveFlagBytes(b)

indeces := utils.ParseADFast(b)
event := utils.LoopADStructures(b, indeces, id, parserRegistry)
event := utils.LoopADStructures(b, indeces, id, parserRegistry, "")

if event.ID == "" {
return nil


+ 7
- 7
tests/decoder/event_loop_test.go Datei anzeigen

@@ -16,12 +16,12 @@ func TestEventLoop_RawMessageProcessing(t *testing.T) {
mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
parserRegistry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}

chRaw := make(chan model.BeaconAdvertisement, 10)
chRaw := make(chan appcontext.BeaconAdvertisement, 10)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Create a test message
msg := model.BeaconAdvertisement{
msg := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "020106",
}
@@ -242,7 +242,7 @@ func TestEventLoop_ContextCancellation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

chRaw := make(chan model.BeaconAdvertisement, 10)
chRaw := make(chan appcontext.BeaconAdvertisement, 10)
chParser := make(chan model.KafkaParser, 10)

// Cancel immediately
@@ -264,7 +264,7 @@ func TestEventLoop_ContextCancellation(t *testing.T) {

func TestEventLoop_ChannelBuffering(t *testing.T) {
// Setup - create buffered channels (like in main)
chRaw := make(chan model.BeaconAdvertisement, 2000)
chRaw := make(chan appcontext.BeaconAdvertisement, 2000)
chParser := make(chan model.KafkaParser, 200)

_, cancel := context.WithCancel(context.Background())
@@ -272,7 +272,7 @@ func TestEventLoop_ChannelBuffering(t *testing.T) {

// Send multiple messages without blocking
for i := 0; i < 100; i++ {
msg := model.BeaconAdvertisement{
msg := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "020106",
}
@@ -310,14 +310,14 @@ func TestEventLoop_ChannelBuffering(t *testing.T) {

func TestEventLoop_ParserAndRawChannels(t *testing.T) {
// Setup
chRaw := make(chan model.BeaconAdvertisement, 10)
chRaw := make(chan appcontext.BeaconAdvertisement, 10)
chParser := make(chan model.KafkaParser, 10)

_, cancel := context.WithCancel(context.Background())
defer cancel()

// Send both raw and parser messages
rawMsg := model.BeaconAdvertisement{
rawMsg := appcontext.BeaconAdvertisement{
ID: "test-beacon",
Data: "020106",
}


+ 8
- 8
tests/decoder/integration_test.go Datei anzeigen

@@ -56,7 +56,7 @@ func TestIntegration_DecoderEndToEnd(t *testing.T) {
defer reader.Close()

// Create a test beacon advertisement
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "integration-test-beacon",
Data: "020106", // Valid hex data
}
@@ -104,7 +104,7 @@ func TestIntegration_ParserRegistryOperations(t *testing.T) {
ID: "add",
Name: "kafka-test-parser",
Config: model.Config{
Name: "kafka-test-parser",
Name: "kafka-test-parser",
Min: 2,
Max: 20,
Pattern: []string{"0x02", "0x01"},
@@ -177,7 +177,7 @@ func TestIntegration_MultipleBeaconsSequential(t *testing.T) {
defer reader.Close()

// Process multiple beacons
beacons := []model.BeaconAdvertisement{
beacons := []appcontext.BeaconAdvertisement{
{ID: "beacon-1", Data: "020106"},
{ID: "beacon-2", Data: "020107"},
{ID: "beacon-3", Data: "020108"},
@@ -243,7 +243,7 @@ func TestIntegration_EventDeduplication(t *testing.T) {
defer reader.Close()

// Create identical beacon advertisement
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "dedup-test-beacon",
Data: "020106",
}
@@ -319,7 +319,7 @@ func TestIntegration_AppStatePersistence(t *testing.T) {
defer writer.Close()

// Process beacon
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "persist-test-beacon",
Data: "020106",
}
@@ -381,7 +381,7 @@ func TestIntegration_ParserUpdateFlow(t *testing.T) {
parserRegistry.Register("update-test-parser", config1)

// Process with initial config
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
ID: "update-test-beacon",
Data: "020106",
}
@@ -391,7 +391,7 @@ func TestIntegration_ParserUpdateFlow(t *testing.T) {

// Update parser config
config2 := model.Config{
Name: "update-test-parser",
Name: "update-test-parser",
Min: 3,
Max: 25,
Pattern: []string{"0x03"},
@@ -400,7 +400,7 @@ func TestIntegration_ParserUpdateFlow(t *testing.T) {
parserRegistry.Register("update-test-parser", config2)

// Process again with updated config
adv2 := model.BeaconAdvertisement{
adv2 := appcontext.BeaconAdvertisement{
ID: "update-test-beacon-2",
Data: "030107",
}


+ 17
- 17
tests/decoder/testutil.go Datei anzeigen

@@ -60,32 +60,32 @@ func (th *TestHelper) RegisterTestParser(name string) {
}

// CreateBeaconAdvertisement creates a test beacon advertisement
func (th *TestHelper) CreateBeaconAdvertisement(id, data string) model.BeaconAdvertisement {
return model.BeaconAdvertisement{
func (th *TestHelper) CreateBeaconAdvertisement(id, data string) appcontext.BeaconAdvertisement {
return appcontext.BeaconAdvertisement{
ID: id,
Data: data,
}
}

// CreateValidHexAdvertisement creates a beacon with valid hex data
func (th *TestHelper) CreateValidHexAdvertisement(id string) model.BeaconAdvertisement {
return model.BeaconAdvertisement{
func (th *TestHelper) CreateValidHexAdvertisement(id string) appcontext.BeaconAdvertisement {
return appcontext.BeaconAdvertisement{
ID: id,
Data: "020106",
}
}

// CreateInvalidHexAdvertisement creates a beacon with invalid hex data
func (th *TestHelper) CreateInvalidHexAdvertisement(id string) model.BeaconAdvertisement {
return model.BeaconAdvertisement{
func (th *TestHelper) CreateInvalidHexAdvertisement(id string) appcontext.BeaconAdvertisement {
return appcontext.BeaconAdvertisement{
ID: id,
Data: "INVALID_HEX",
}
}

// CreateEmptyAdvertisement creates a beacon with empty data
func (th *TestHelper) CreateEmptyAdvertisement(id string) model.BeaconAdvertisement {
return model.BeaconAdvertisement{
func (th *TestHelper) CreateEmptyAdvertisement(id string) appcontext.BeaconAdvertisement {
return appcontext.BeaconAdvertisement{
ID: id,
Data: "",
}
@@ -106,11 +106,11 @@ func (th *TestHelper) AssertParserNotExists(name string) {
}

// AssertEventExists asserts that an event exists in appState
func (th *TestHelper) AssertEventExists(id string) model.BeaconEvent {
func (th *TestHelper) AssertEventExists(id string) appcontext.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 appcontext.BeaconEvent{}
}
return event
}
@@ -172,10 +172,10 @@ func AssertError(t *testing.T, err error, msg string) {

// 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
"020106", // Simple AD structure
"0201060302A0", // AD structure with flags
"1AFF0C01", // iBeacon-like data
"0201061AFF0C01", // Multiple AD structures
}

// Invalid hex strings for testing
@@ -201,7 +201,7 @@ func CreateMockWriter() *MockKafkaWriter {
// Beacon event test helpers

// AssertEventFields asserts that event fields match expected values
func AssertEventFields(t *testing.T, event model.BeaconEvent, expectedID, expectedType string) {
func AssertEventFields(t *testing.T, event appcontext.BeaconEvent, expectedID, expectedType string) {
if event.ID != expectedID {
t.Errorf("Expected event ID '%s', got '%s'", expectedID, event.ID)
}
@@ -232,8 +232,8 @@ func CleanupTestParsers(registry *model.ParserRegistry) {
}

// CreateTestBeaconEvent creates a test beacon event
func CreateTestBeaconEvent(id, eventType string) model.BeaconEvent {
return model.BeaconEvent{
func CreateTestBeaconEvent(id, eventType string) appcontext.BeaconEvent {
return appcontext.BeaconEvent{
ID: id,
Type: eventType,
Battery: 100,


+ 2
- 2
tests/location/location_test.go Datei anzeigen

@@ -3,8 +3,8 @@ package location
import (
"testing"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/common/utils"
"github.com/AFASystems/presence/internal/pkg/model"
)

// Test location algorithm scoring formula: seenW + (rssiW * (1.0 - (rssi / -100.0)))
@@ -30,7 +30,7 @@ func TestLocationScoringFormula(t *testing.T) {
}

func TestCalculateDistance_ForLocation(t *testing.T) {
adv := model.BeaconAdvertisement{
adv := appcontext.BeaconAdvertisement{
RSSI: -65,
TXPower: "C5",
}


+ 6
- 5
tests/model/model_test.go Datei anzeigen

@@ -4,11 +4,12 @@ import (
"encoding/json"
"testing"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/model"
)

func TestBeaconEvent_Hash(t *testing.T) {
e := model.BeaconEvent{
e := appcontext.BeaconEvent{
ID: "beacon-1",
Name: "beacon-1",
Type: "iBeacon",
@@ -28,8 +29,8 @@ func TestBeaconEvent_Hash(t *testing.T) {
}

func TestBeaconEvent_Hash_BatteryRounded(t *testing.T) {
e1 := model.BeaconEvent{ID: "1", Battery: 84, Event: 1}
e2 := model.BeaconEvent{ID: "1", Battery: 89, Event: 1}
e1 := appcontext.BeaconEvent{ID: "1", Battery: 84, Event: 1}
e2 := appcontext.BeaconEvent{ID: "1", Battery: 89, Event: 1}
hash1 := e1.Hash()
hash2 := e2.Hash()
// Battery is rounded to nearest 10, so 84 and 89 should produce same hash
@@ -39,7 +40,7 @@ func TestBeaconEvent_Hash_BatteryRounded(t *testing.T) {
}

func TestBeaconEvent_ToJSON(t *testing.T) {
e := model.BeaconEvent{
e := appcontext.BeaconEvent{
ID: "beacon-1",
Name: "Test",
Type: "iBeacon",
@@ -49,7 +50,7 @@ func TestBeaconEvent_ToJSON(t *testing.T) {
if err != nil {
t.Fatalf("ToJSON failed: %v", err)
}
var decoded model.BeaconEvent
var decoded appcontext.BeaconEvent
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}


+ 6
- 5
tests/utils/utils_test.go Datei anzeigen

@@ -3,6 +3,7 @@ package utils
import (
"testing"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/AFASystems/presence/internal/pkg/common/utils"
"github.com/AFASystems/presence/internal/pkg/model"
)
@@ -80,17 +81,17 @@ func TestRemoveFlagBytes_TooShort(t *testing.T) {

func TestCalculateDistance(t *testing.T) {
tests := []struct {
name string
rssi int64
name string
rssi int64
txPower string
}{
{"typical beacon", -65, "C5"}, // -59 in two's complement
{"typical beacon", -65, "C5"}, // -59 in two's complement
{"weak signal", -90, "C5"},
{"strong signal", -40, "C5"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
adv := model.BeaconAdvertisement{RSSI: tt.rssi, TXPower: tt.txPower}
adv := appcontext.BeaconAdvertisement{RSSI: tt.rssi, TXPower: tt.txPower}
d := utils.CalculateDistance(adv)
if d < 0 {
t.Errorf("Distance should be non-negative, got %f", d)
@@ -103,7 +104,7 @@ func TestLoopADStructures_NoParsers(t *testing.T) {
registry := &model.ParserRegistry{ParserList: make(map[string]model.BeaconParser)}
data := []byte{0x02, 0x01, 0x06}
indices := utils.ParseADFast(data)
event := utils.LoopADStructures(data, indices, "beacon-1", registry)
event := utils.LoopADStructures(data, indices, "beacon-1", registry, "")
if event.ID != "" {
t.Errorf("Expected empty event with no parsers, got ID %s", event.ID)
}


Laden…
Abbrechen
Speichern