package compass import ( "os" "path/filepath" "strings" "testing" "testing/fstest" ) func TestSetWinsOverPersistedOverrides(t *testing.T) { dir := writeConfigTree(t, map[string]string{ "app.yaml": "name: base\n", "env/development/overrides.yaml": "app:\n name: persisted\n", }) cfg, err := Open(Options{Dir: dir, Env: "development", Environ: []string{}}) if err != nil { t.Fatalf("Open: %v", err) } if got := cfg.String("app.name"); got != "persisted" { t.Fatalf("loaded persisted name = %q, want persisted", got) } if err := cfg.Set("app.name", "runtime"); err != nil { t.Fatalf("Set: %v", err) } if got := cfg.String("app.name"); got != "runtime" { t.Fatalf("Set should win, got %q", got) } } func TestPersistWritesEnvOverridesAtomicallyWithRestrictivePerms(t *testing.T) { dir := writeConfigTree(t, map[string]string{ "app.yaml": "name: base\n", }) cfg, err := Open(Options{Dir: dir, Env: "development", Environ: []string{}}) if err != nil { t.Fatalf("Open: %v", err) } if err := cfg.Set("app.name", "saved"); err != nil { t.Fatalf("Set: %v", err) } if err := cfg.Persist(); err != nil { t.Fatalf("Persist: %v", err) } path := filepath.Join(dir, "env", "development", "overrides.yaml") info, err := os.Stat(path) if err != nil { t.Fatalf("stat overrides: %v", err) } if info.Mode().Perm() != 0o600 { t.Fatalf("overrides perm = %o, want 0600", info.Mode().Perm()) } body, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if !strings.Contains(string(body), "saved") { t.Fatalf("overrides.yaml = %q, want to contain saved", body) } tmp := filepath.Join(dir, "env", "development", "overrides.yaml.tmp") if _, err := os.Stat(tmp); !os.IsNotExist(err) { t.Fatalf("temporary persist file should not remain: %v", err) } } func TestReloadClearsSetAndRereadsFiles(t *testing.T) { dir := writeConfigTree(t, map[string]string{ "app.yaml": "name: base\n", }) cfg, err := Open(Options{Dir: dir, Env: "development", Environ: []string{}}) if err != nil { t.Fatalf("Open: %v", err) } fsys := fstest.MapFS{ "config/config.yaml": {Data: []byte("posts_per_page: 10\n")}, } if err := cfg.MergePlugin("golem15.hello", fsys); err != nil { t.Fatalf("MergePlugin: %v", err) } if err := cfg.Set("app.name", "runtime"); err != nil { t.Fatalf("Set: %v", err) } if err := cfg.Persist(); err != nil { t.Fatalf("Persist: %v", err) } if err := cfg.Set("app.name", "runtime2"); err != nil { t.Fatalf("Set runtime2: %v", err) } if err := cfg.Set("golem15.hello.posts_per_page", 99); err != nil { t.Fatalf("Set posts: %v", err) } if err := os.WriteFile(filepath.Join(dir, "app.yaml"), []byte("name: disk\n"), 0o644); err != nil { t.Fatal(err) } if err := cfg.Reload(); err != nil { t.Fatalf("Reload: %v", err) } if got := cfg.String("app.name"); got != "runtime" { t.Fatalf("after Reload, name = %q, want persisted runtime (Set cleared)", got) } if got := cfg.Int("golem15.hello.posts_per_page"); got != 10 { t.Fatalf("after Reload, posts_per_page = %d, want plugin default 10", got) } } func TestPersistRejectsInvalidEnvName(t *testing.T) { dir := writeConfigTree(t, map[string]string{ "app.yaml": "name: base\n", }) _, err := Open(Options{Dir: dir, Env: "../etc", Environ: []string{}}) if err == nil { t.Fatal("expected invalid environment name to fail") } if strings.Contains(strings.ToLower(err.Error()), "etc") { t.Fatalf("error should not echo unsanitized env path: %v", err) } }