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 / workbench / bundles_test.go
bundles_test.go 4.2K
1package workbench23import (4 "os"5 "path/filepath"6 "strconv"7 "strings"8 "testing"910 "github.com/FelineStateMachine/atlas/format/semconv"11 "github.com/FelineStateMachine/atlas/format/vnext"12)1314// The native volumes these tests measure are stated here, then compiled by15// the same vNext writer used by production.16type bundleSpec struct {17 slug, title, createdAt, stamp string18 revision, conventions int19 worlds []worldSpec20}2122type worldSpec struct {23 slug, title, icon string24 attrs map[string]string25 features []featureSpec26 merged []map[string]any27 lenses []map[string]any28}2930type featureSpec struct {31 id int6432 title string33 description string34}3536func (b bundleSpec) write(t *testing.T, dir string) string {37 t.Helper()38 if b.slug == "" {39 b.slug = "hollowmere"40 }41 if b.title == "" {42 b.title = "Hollowmere"43 }44 if b.createdAt == "" {45 b.createdAt = "2026-01-01T00:00:00Z"46 }47 if b.stamp == "" {48 b.stamp = strings.Repeat("0", 64)49 }50 volume := vnext.Volume{ID: b.slug, Title: b.title}51 for _, world := range b.worlds {52 volume.Worlds = append(volume.Worlds, world.native())53 if world.icon != "" {54 volume.Assets = append(volume.Assets, vnext.Asset{ID: world.icon, MediaType: "image/png", Data: []byte("icon")})55 }56 }57 compiled, err := vnext.Compile(volume)58 if err != nil {59 t.Fatal(err)60 }61 compiled.Release.CreatedAt = b.createdAt62 compiled.Release.Revision = b.revision63 path := filepath.Join(dir, b.slug+"-"+vnext.ShortStamp(b.stamp)+vnext.Extension)64 file, err := os.Create(path)65 if err != nil {66 t.Fatal(err)67 }68 if err := vnext.Write(file, compiled); err != nil {69 file.Close()70 t.Fatal(err)71 }72 if err := file.Close(); err != nil {73 t.Fatal(err)74 }75 return path76}7778func (w worldSpec) native() vnext.World {79 title := w.title80 if title == "" {81 title = "Overworld"82 }83 attrs := w.attrs84 if attrs == nil {85 attrs = map[string]string{semconv.KeyGeometrySurface: semconv.SurfacePlane}86 }87 setID := w.slug + "/set/markers"88 styleID := w.slug + "/style/markers"89 layerID := w.slug + "/layer/markers"90 set := vnext.FeatureSet{ID: setID, Title: "Markers", SemanticType: "geometry.point"}91 sources := []string{"Test Origin"}92 for _, account := range w.merged {93 if source, ok := account["source"].(string); ok && source != "" {94 sources = append(sources, source)95 }96 }97 for index, item := range w.features {98 feature := vnext.Feature{99 ID: w.slug + "/feature/" + strconv.FormatInt(item.id, 10), Title: item.title, Description: item.description,100 Geometry: vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{float64(index), float64(index)}}}}}},101 }102 for _, source := range sources {103 feature.Provenance = append(feature.Provenance, vnext.Provenance{Source: source, NativeID: strconv.FormatInt(item.id, 10)})104 }105 set.Features = append(set.Features, feature)106 }107 world := vnext.World{108 ID: w.slug, Title: title,109 CoordinateSpace: vnext.CoordinateSpace{ID: w.slug + "/space", Kind: "projected", Unit: "pixel", Definition: "atlas:tile-plane", Extent: [4]float64{0, 0, 8192, 8192}, SourceZoom: 5, TileSize: 256, Size: 8192},110 Claims: testProperties("world", attrs), FeatureSets: []vnext.FeatureSet{set},111 Presentation: vnext.Presentation{ID: w.slug + "/presentation", Title: title},112 }113 world.Presentation.Styles = []vnext.Style{{ID: styleID, IconAsset: w.icon, RenderAs: semconv.RenderAsPin}}114 world.Presentation.Layers = []vnext.Layer{{ID: layerID, FeatureSet: setID, Style: styleID, Group: "Places", Visible: true, MaxZoom: 32}}115 world.Presentation.Legend = []vnext.LegendEntry{{Layer: layerID, Label: "Markers"}}116 world.RasterPyramids = []vnext.RasterPyramid{{ID: w.slug + "/raster/0", Name: "Surface", Codec: "image/jpeg", TileSize: 256, MinZoom: 0, MaxZoom: 2, Formats: []string{"jpg", "jpg", "jpg"}, Template: "tiles/" + w.slug + "/{z}/{x}/{y}.{format}"}}117 return world118}119120func testProperties(owner string, attrs map[string]string) []vnext.Property {121 out := make([]vnext.Property, 0, len(attrs))122 for key, value := range attrs {123 out = append(out, vnext.Property{Field: vnext.Field{ID: vnext.CoreID(owner + ".test." + key), Name: key, Kind: vnext.KindString, Optional: true}, Value: vnext.StringValue(value)})124 }125 return out126}