package cli import ( "context" "io" "log/slog" "os" "path/filepath" "strings" "testing" "gitea.mynodes.xyz/ilker/llmgw/internal/config" storepkg "gitea.mynodes.xyz/ilker/llmgw/internal/store" ) func settingsFixture(t *testing.T, extra string) (path, store string) { t.Helper() dir := t.TempDir() store = filepath.Join(dir, "llmgw.db") path = filepath.Join(dir, "server.yaml") body := "listen: \":8080\"\nagent_insecure: true\nauth:\n enabled: true\n store: " + store + "\nrouter:\n retries: 2\n" + extra if err := os.WriteFile(path, []byte(body), 0o600); err != nil { t.Fatal(err) } return path, store } var quiet = slog.New(slog.NewTextHandler(io.Discard, nil)) func TestTheFirstStartBringsTheFilesSettingsInWithGuardrails(t *testing.T) { path, store := settingsFixture(t, "") s, err := loadClusterSettings(t.Context(), path, quiet) if err != nil { t.Fatal(err) } if s.version != 1 || s.cfg.Router.Retries != 2 { t.Errorf("version %d retries %d", s.version, s.cfg.Router.Retries) } if len(s.cfg.Guard.Policies) == 0 || s.cfg.Guard.Policies["baseline"].Judge != nil { t.Errorf("a file without guard got %+v, want the baseline without a judge", s.cfg.Guard) } st, _ := storepkg.Open(t.Context(), store) defer st.Close() doc, _ := st.ClusterSettings(t.Context()) if strings.Contains(doc.Body, "listen") || strings.Contains(doc.Body, store) || !strings.Contains(doc.Body, "retries: 2") { t.Errorf("the store holds a machine's keys, or lost the cluster's:\n%s", doc.Body) } // From then on the store's settings are the cluster's, whatever a // file says. _ = os.WriteFile(path, []byte(strings.Replace(mustRead(t, path), "retries: 2", "retries: 9", 1)), 0o600) again, err := loadClusterSettings(t.Context(), path, quiet) if err != nil || again.version != 1 || again.cfg.Router.Retries != 2 { t.Errorf("second start: version %d retries %d err %v", again.version, again.cfg.Router.Retries, err) } } func mustRead(t *testing.T, p string) string { b, err := os.ReadFile(p) if err != nil { t.Fatal(err) } return string(b) } func TestEveryChangeIsAppliedLiveOrByStartingAgain(t *testing.T) { path, store := settingsFixture(t, "") s, err := loadClusterSettings(t.Context(), path, quiet) if err != nil { t.Fatal(err) } st, _ := storepkg.Open(t.Context(), store) defer st.Close() var lived [][]string var restarts []string w := &settingsWatch{path: path, st: st, cur: s, log: quiet, live: func(_ config.Server, changed []string) bool { lived = append(lived, changed) return onlyLive(changed) }, restart: func(why string) { restarts = append(restarts, why) }, } ctx := context.Background() put := func(body string) { t.Helper() v, _ := st.ClusterSettingsVersion(ctx) if _, err := st.PutClusterSettings(ctx, v, body, "test", ""); err != nil { t.Fatal(err) } } cur, _ := st.ClusterSettings(ctx) w.check(ctx) // nothing changed if len(lived)+len(restarts) != 0 { t.Fatalf("acted on no change: %v %v", lived, restarts) } put(strings.Replace(cur.Body, "injection: flag", "injection: block", 1)) w.check(ctx) if len(restarts) != 0 || len(lived) != 1 || lived[0][0] != "guard" { t.Fatalf("a guard change: lived %v restarts %v", lived, restarts) } cur, _ = st.ClusterSettings(ctx) put(strings.Replace(cur.Body, "retries: 2", "retries: 4", 1)) w.check(ctx) if len(restarts) != 1 || !strings.Contains(restarts[0], "router") || w.cur.cfg.Router.Retries != 4 { t.Fatalf("a router change: restarts %v retries %d", restarts, w.cur.cfg.Router.Retries) } // A machine's own key, in its file. _ = os.WriteFile(path, []byte(strings.Replace(mustRead(t, path), `":8080"`, `":8090"`, 1)), 0o600) w.check(ctx) if len(restarts) != 2 || !strings.Contains(restarts[1], "listen") { t.Fatalf("a listener change: %v", restarts) } // Settings that do not load are not put in force. cur, _ = st.ClusterSettings(ctx) put(cur.Body + "control:\n timezone: Mars/Olympus\n") w.check(ctx) if len(restarts) != 2 || w.cur.cfg.Control.Timezone != "" { t.Errorf("bad settings were applied: %v %q", restarts, w.cur.cfg.Control.Timezone) } } func TestAClusterDocumentCannotSetAMachinesKeys(t *testing.T) { path, _ := settingsFixture(t, "") if err := checkClusterSettings(path, []byte("listen: \":1\"\n")); err == nil { t.Error("listen was accepted") } if err := checkClusterSettings(path, []byte("control:\n timezone: Mars/Olympus\n")); err == nil { t.Error("a timezone that is not one was accepted") } if err := checkClusterSettings(path, []byte("router:\n retries: 3\n")); err != nil { t.Error(err) } }