|
- package test
-
- import (
- "testing"
-
- "github.com/AFASystems/presence/internal/pkg/common/utils"
- "github.com/AFASystems/presence/internal/pkg/model"
- )
-
- func TestCalculateDistance(t *testing.T) {
- tests := []struct {
- name string
- adv model.BeaconAdvertisement
- expected float64
- }{
- {
- name: "Strong signal - close distance",
- adv: model.BeaconAdvertisement{
- RSSI: -30,
- TXPower: "59", // 89 in decimal
- },
- expected: 0.89976, // Close to minimum
- },
- {
- name: "Medium signal",
- adv: model.BeaconAdvertisement{
- RSSI: -65,
- TXPower: "59",
- },
- expected: 1.5, // Medium distance
- },
- {
- name: "Weak signal - far distance",
- adv: model.BeaconAdvertisement{
- RSSI: -95,
- TXPower: "59",
- },
- expected: 8.0, // Far distance
- },
- {
- name: "Equal RSSI and TX power",
- adv: model.BeaconAdvertisement{
- RSSI: -59,
- TXPower: "59",
- },
- expected: 1.0, // Ratio = 1.0
- },
- {
- name: "Very strong signal",
- adv: model.BeaconAdvertisement{
- RSSI: -10,
- TXPower: "59",
- },
- expected: 0.89976, // Minimum distance
- },
- {
- name: "Negative TX power (two's complement)",
- adv: model.BeaconAdvertisement{
- RSSI: -70,
- TXPower: "C6", // -58 in decimal
- },
- expected: 1.2, // Medium distance
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := utils.CalculateDistance(tt.adv)
- // Allow for small floating point differences
- if result < tt.expected*0.9 || result > tt.expected*1.1 {
- t.Errorf("CalculateDistance() = %v, expected around %v", result, tt.expected)
- }
- })
- }
- }
-
- func TestCalculateDistanceEdgeCases(t *testing.T) {
- tests := []struct {
- name string
- adv model.BeaconAdvertisement
- expected float64
- }{
- {
- name: "Zero RSSI",
- adv: model.BeaconAdvertisement{
- RSSI: 0,
- TXPower: "59",
- },
- expected: 0.0,
- },
- {
- name: "Invalid TX power",
- adv: model.BeaconAdvertisement{
- RSSI: -50,
- TXPower: "XYZ",
- },
- expected: 0.0, // twosComp returns 0 for invalid input
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := utils.CalculateDistance(tt.adv)
- if result != tt.expected {
- t.Errorf("CalculateDistance() = %v, expected %v", result, tt.expected)
- }
- })
- }
- }
-
- func TestValidateRSSI(t *testing.T) {
- tests := []struct {
- name string
- rssi int64
- expected bool
- }{
- {
- name: "Valid RSSI - strong signal",
- rssi: -30,
- expected: true,
- },
- {
- name: "Valid RSSI - weak signal",
- rssi: -100,
- expected: true,
- },
- {
- name: "Valid RSSI - boundary low",
- rssi: -120,
- expected: true,
- },
- {
- name: "Valid RSSI - boundary high",
- rssi: 0,
- expected: true,
- },
- {
- name: "Invalid RSSI - too strong",
- rssi: 10,
- expected: false,
- },
- {
- name: "Invalid RSSI - too weak",
- rssi: -130,
- expected: false,
- },
- {
- name: "Invalid RSSI - just below boundary",
- rssi: -121,
- expected: false,
- },
- {
- name: "Invalid RSSI - just above boundary",
- rssi: 1,
- expected: false,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := utils.ValidateRSSI(tt.rssi)
- if result != tt.expected {
- t.Errorf("ValidateRSSI() = %v, expected %v", result, tt.expected)
- }
- })
- }
- }
-
- func TestValidateTXPower(t *testing.T) {
- tests := []struct {
- name string
- txPower string
- expected bool
- }{
- {
- name: "Valid TX power - positive",
- txPower: "59",
- expected: true,
- },
- {
- name: "Valid TX power - negative",
- txPower: "C6",
- expected: true,
- },
- {
- name: "Valid TX power - zero",
- txPower: "00",
- expected: true,
- },
- {
- name: "Valid TX power - max positive",
- txPower: "7F",
- expected: true,
- },
- {
- name: "Valid TX power - max negative",
- txPower: "80",
- expected: true,
- },
- {
- name: "Valid TX power - boundary negative",
- txPower: "81", // -127
- expected: true,
- },
- {
- name: "Invalid TX power string",
- txPower: "XYZ",
- expected: true, // twosComp returns 0, which is valid
- },
- {
- name: "Empty TX power",
- txPower: "",
- expected: true, // twosComp returns 0, which is valid
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := utils.ValidateTXPower(tt.txPower)
- if result != tt.expected {
- t.Errorf("ValidateTXPower() = %v, expected %v", result, tt.expected)
- }
- })
- }
- }
-
- func TestCalculateDistanceConsistency(t *testing.T) {
- // Test that the function is deterministic
- adv := model.BeaconAdvertisement{
- RSSI: -65,
- TXPower: "59",
- }
-
- result1 := utils.CalculateDistance(adv)
- result2 := utils.CalculateDistance(adv)
-
- if result1 != result2 {
- t.Errorf("CalculateDistance() is not deterministic: %v != %v", result1, result2)
- }
- }
-
- func TestCalculateDistanceRealWorldScenarios(t *testing.T) {
- scenarios := []struct {
- name string
- rssi int64
- txPower string
- expectedRange [2]float64 // min, max expected range
- }{
- {
- name: "Beacon very close (1m)",
- rssi: -45,
- txPower: "59", // 89 decimal
- expectedRange: [2]float64{0.5, 1.5},
- },
- {
- name: "Beacon at medium distance (5m)",
- rssi: -75,
- txPower: "59",
- expectedRange: [2]float64{3.0, 8.0},
- },
- {
- name: "Beacon far away (15m)",
- rssi: -95,
- txPower: "59",
- expectedRange: [2]float64{10.0, 25.0},
- },
- }
-
- for _, scenario := range scenarios {
- t.Run(scenario.name, func(t *testing.T) {
- adv := model.BeaconAdvertisement{
- RSSI: scenario.rssi,
- TXPower: scenario.txPower,
- }
- result := utils.CalculateDistance(adv)
-
- if result < scenario.expectedRange[0] || result > scenario.expectedRange[1] {
- t.Errorf("CalculateDistance() = %v, expected range %v", result, scenario.expectedRange)
- }
- })
- }
- }
-
- // Benchmark tests
- func BenchmarkCalculateDistance(b *testing.B) {
- adv := model.BeaconAdvertisement{
- RSSI: -65,
- TXPower: "59",
- }
-
- for i := 0; i < b.N; i++ {
- utils.CalculateDistance(adv)
- }
- }
|