package geospatial import ( "testing" ) func TestGeospatialCalculator_CalculateDistance(t *testing.T) { calc := NewCalculatorWithDefaults() p1 := Point{Latitude: 52.5200, Longitude: 13.4050} p2 := Point{Latitude: 52.5300, Longitude: 13.4150} result, err := calc.CalculateDistance(p1, p2) if err != nil { t.Fatalf("CalculateDistance() error = %v", err) } if result.DistanceKm <= 0 { t.Error("CalculateDistance() distance should be positive") } if result.DistanceMeters != result.DistanceKm*1000 { t.Error("CalculateDistance() DistanceMeters should equal DistanceKm * 1000") } if result.Bearing < 0 || result.Bearing >= 360 { t.Errorf("CalculateDistance() bearing should be 0-360, got %v", result.Bearing) } } func TestGeospatialCalculator_CalculateDistanceMatrix(t *testing.T) { calc := NewCalculatorWithDefaults() points := []Point{ {Latitude: 52.5200, Longitude: 13.4050}, {Latitude: 52.5300, Longitude: 13.4150}, {Latitude: 52.5100, Longitude: 13.3950}, } matrix, err := calc.CalculateDistanceMatrix(points) if err != nil { t.Fatalf("CalculateDistanceMatrix() error = %v", err) } if len(matrix.Points) != len(points) { t.Errorf("CalculateDistanceMatrix() Points length = %v, want %v", len(matrix.Points), len(points)) } if len(matrix.Distances) != len(points) { t.Errorf("CalculateDistanceMatrix() Distances rows = %v, want %v", len(matrix.Distances), len(points)) } // Diagonal should be zero for i := 0; i < len(points); i++ { if matrix.Distances[i][i] != 0 { t.Errorf("CalculateDistanceMatrix() diagonal[%d] = %v, want 0", i, matrix.Distances[i][i]) } } // Matrix should be symmetric for i := 0; i < len(points); i++ { for j := 0; j < len(points); j++ { if matrix.Distances[i][j] != matrix.Distances[j][i] { t.Errorf("CalculateDistanceMatrix() matrix[%d][%d] = %v, matrix[%d][%d] = %v (should be equal)", i, j, matrix.Distances[i][j], j, i, matrix.Distances[j][i]) } } } } func TestGeospatialCalculator_CalculateDistanceMatrix_EmptyList(t *testing.T) { calc := NewCalculatorWithDefaults() _, err := calc.CalculateDistanceMatrix([]Point{}) if err == nil { t.Error("CalculateDistanceMatrix() expected error for empty point list") } } func TestGeospatialCalculator_CalculateRoute(t *testing.T) { calc := NewCalculatorWithDefaults() points := []Point{ {Latitude: 52.5200, Longitude: 13.4050}, {Latitude: 52.5300, Longitude: 13.4150}, {Latitude: 52.5100, Longitude: 13.3950}, } route, err := calc.CalculateRoute(points) if err != nil { t.Fatalf("CalculateRoute() error = %v", err) } if len(route.Points) != len(points) { t.Errorf("CalculateRoute() Points length = %v, want %v", len(route.Points), len(points)) } if len(route.Segments) != len(points)-1 { t.Errorf("CalculateRoute() Segments length = %v, want %v", len(route.Segments), len(points)-1) } if route.TotalDistanceKm <= 0 { t.Error("CalculateRoute() TotalDistanceKm should be positive") } // Verify segment distances sum to total distance var sumDist float64 for _, seg := range route.Segments { sumDist += seg.DistanceKm } if sumDist != route.TotalDistanceKm { t.Errorf("CalculateRoute() segment distances sum = %v, want %v", sumDist, route.TotalDistanceKm) } } func TestGeospatialCalculator_CalculateRoute_InsufficientPoints(t *testing.T) { calc := NewCalculatorWithDefaults() tests := []struct { name string points []Point }{ { name: "Empty list", points: []Point{}, }, { name: "Single point", points: []Point{{Latitude: 52.5200, Longitude: 13.4050}}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err := calc.CalculateRoute(tt.points) if err == nil { t.Error("CalculateRoute() expected error for insufficient points") } }) } } func TestGeospatialCalculator_ValidatePoint(t *testing.T) { calc := NewCalculatorWithDefaults() tests := []struct { name string point Point wantErr bool }{ { name: "Valid point", point: Point{Latitude: 52.5200, Longitude: 13.4050}, wantErr: false, }, { name: "Invalid latitude - too high", point: Point{Latitude: 91.0, Longitude: 13.4050}, wantErr: true, }, { name: "Invalid latitude - too low", point: Point{Latitude: -91.0, Longitude: 13.4050}, wantErr: true, }, { name: "Invalid longitude - too high", point: Point{Latitude: 52.5200, Longitude: 181.0}, wantErr: true, }, { name: "Invalid longitude - too low", point: Point{Latitude: 52.5200, Longitude: -181.0}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := calc.ValidatePoint(tt.point) if (err != nil) != tt.wantErr { t.Errorf("ValidatePoint() error = %v, wantErr %v", err, tt.wantErr) } }) } }