clone

an offline map explorer where each world, from a game map to a city's open data, ships as one .atlas file

feat/atlas-next-horizon
atlas / internal / authoring / semantic_budget_test.go
semantic_budget_test.go 3.7K
1package authoring23import (4 "math"5 "strings"6 "testing"78 "github.com/FelineStateMachine/atlas/format/vnext"9)1011func TestSemanticBudgetsAcceptExactEmittedBoundary(t *testing.T) {12 volume := semanticBudgetVolume(13 vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{1, 1}}}}}},14 vnext.Geometry{Kind: vnext.GeometryLineString, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{0, 0}, {1, 1}, {2, 2}}}}}},15 )16 budgets := defaultBuildBudgets17 budgets.Features = 218 budgets.GeometryPositions = 41920 if err := enforceSemanticBudgets(volume, budgets); err != nil {21 t.Fatalf("exact semantic budget boundary: %v", err)22 }23}2425func TestSemanticBudgetsRejectWithoutTruncating(t *testing.T) {26 volume := semanticBudgetVolume(27 vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{1, 1}}}}}},28 vnext.Geometry{Kind: vnext.GeometryLineString, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{0, 0}, {1, 1}, {2, 2}}}}}},29 )30 tests := []struct {31 name string32 budget BuildBudgets33 message string34 }{35 {name: "features", budget: BuildBudgets{Features: 1, GeometryPositions: 4}, message: "emits 2 features, budget is 1"},36 {name: "positions", budget: BuildBudgets{Features: 2, GeometryPositions: 3}, message: "emits 4 geometry positions, budget is 3"},37 }38 for _, test := range tests {39 t.Run(test.name, func(t *testing.T) {40 if err := enforceSemanticBudgets(volume, test.budget); err == nil || !strings.Contains(err.Error(), test.message) {41 t.Fatalf("semantic budget error = %v, want %q", err, test.message)42 }43 })44 }45 if got := len(volume.Worlds[0].FeatureSets[0].Features); got != 2 {46 t.Fatalf("refusal truncated volume to %d features", got)47 }48}4950func TestSemanticBudgetsCountFusedOutputRatherThanObservations(t *testing.T) {51 project := contractTestProject()52 geometry := vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{1, 1}}}}}}53 observations := []observation{54 {SourceOrder: 0, Source: "page-one", NativeID: "one", FeatureSet: "places", Title: "One", Geometry: geometry, Values: map[string]vnext.Value{"kind": vnext.StringValue("sample")}},55 {SourceOrder: 0, Source: "page-two", NativeID: "two", FeatureSet: "places", Title: "Two", Geometry: geometry, Values: map[string]vnext.Value{"kind": vnext.StringValue("sample")}},56 {SourceOrder: 1, Source: "secondary", NativeID: "one", FeatureSet: "places", Title: "One", Geometry: geometry, Values: map[string]vnext.Value{"kind": vnext.StringValue("alternate")}},57 }58 volume, err := assemble(project, observations)59 if err != nil {60 t.Fatal(err)61 }62 budgets := defaultBuildBudgets63 budgets.Features = 264 budgets.GeometryPositions = 265 if err := enforceSemanticBudgets(volume, budgets); err != nil {66 t.Fatalf("fused output at exact boundary: %v", err)67 }68 if got := len(volume.Worlds[0].FeatureSets[0].Features[0].Provenance); got != 2 {69 t.Fatalf("fused feature provenance = %d, want both sources", got)70 }71}7273func TestSemanticBudgetArithmeticRefusesOverflow(t *testing.T) {74 if got, err := checkedSemanticAdd(math.MaxInt64-1, 1); err != nil || got != math.MaxInt64 {75 t.Fatalf("checked boundary = %d, %v", got, err)76 }77 if _, err := checkedSemanticAdd(math.MaxInt64-1, 2); err == nil || !strings.Contains(err.Error(), "overflows") {78 t.Fatalf("checked overflow = %v", err)79 }80}8182func semanticBudgetVolume(geometries ...vnext.Geometry) vnext.Volume {83 features := make([]vnext.Feature, 0, len(geometries))84 for index, geometry := range geometries {85 features = append(features, vnext.Feature{ID: string(rune('a' + index)), Geometry: geometry})86 }87 return vnext.Volume{Worlds: []vnext.World{{FeatureSets: []vnext.FeatureSet{{Features: features}}}}}88}