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 / app / hostenv / hostenv_test.go
hostenv_test.go 2.8K
1package hostenv_test23import (4 "errors"5 "testing"67 "github.com/FelineStateMachine/atlas/internal/app/hostenv"8)910func TestValidName(t *testing.T) {11 tests := []struct {12 name string13 ok bool14 }{15 {"app.json", true},16 {"volume.tunic.json", true},17 {"volume.zelda-tears-of-the-kingdom.json", true},18 {"volume.mojave_wasteland.json", true},19 {"", false},20 {".hidden", false},21 {"-leading", false},22 {"_leading", false},23 {"volume/tunic.json", false},24 {"..", false},25 {"Volume.json", false},26 {"volume tunic.json", false},27 }28 for _, tt := range tests {29 t.Run(tt.name, func(t *testing.T) {30 err := hostenv.ValidName(tt.name)31 if tt.ok && err != nil {32 t.Errorf("ValidName(%q) = %v, want admitted", tt.name, err)33 }34 if !tt.ok && err == nil {35 t.Errorf("ValidName(%q) was admitted", tt.name)36 }37 })38 }39}4041func TestMemorySessions(t *testing.T) {42 store := hostenv.NewMemorySessions()4344 if _, err := store.Load("app.json"); !errors.Is(err, hostenv.ErrNoSession) {45 t.Fatalf("loading a record nobody wrote = %v, want ErrNoSession", err)46 }47 if err := store.Save("app.json", []byte(`{"volume":"tunic"}`)); err != nil {48 t.Fatal(err)49 }50 if err := store.Save("volume.tunic.json", []byte(`{"world":"world"}`)); err != nil {51 t.Fatal(err)52 }53 held, err := store.Load("app.json")54 if err != nil || string(held) != `{"volume":"tunic"}` {55 t.Fatalf("Load = %q, %v", held, err)56 }5758 // A record handed back is a copy: a caller that scribbles on what it read59 // has not edited the store.60 held[0] = '!'61 again, err := store.Load("app.json")62 if err != nil || string(again) != `{"volume":"tunic"}` {63 t.Fatalf("the store was edited through a returned slice: %q, %v", again, err)64 }6566 names, err := store.Names()67 if err != nil {68 t.Fatal(err)69 }70 if len(names) != 2 || names[0] != "app.json" || names[1] != "volume.tunic.json" {71 t.Fatalf("Names = %v, want the two records sorted", names)72 }7374 // Deleting is the contract the file-backed store answers too: the record75 // goes, its neighbours stay, and a record that was never held is already76 // what the caller asked for.77 if err := store.Delete("volume.tunic.json"); err != nil {78 t.Fatal(err)79 }80 if _, err := store.Load("volume.tunic.json"); !errors.Is(err, hostenv.ErrNoSession) {81 t.Errorf("the record survived a delete: %v", err)82 }83 if names, err := store.Names(); err != nil || len(names) != 1 || names[0] != "app.json" {84 t.Errorf("Names = %v, %v, want the pointer left standing", names, err)85 }86 if err := store.Delete("volume.tunic.json"); err != nil {87 t.Errorf("deleting a record twice = %v, want a quiet success", err)88 }8990 if err := store.Save("volume/escape.json", nil); err == nil {91 t.Error("a name with a separator was accepted")92 }93 if err := store.Delete("volume/escape.json"); err == nil {94 t.Error("a name with a separator was accepted for deletion")95 }96}