package cli import ( "bytes" "io" "net/http" "net/http/httptest" "os" "strings" "testing" "gitea.mynodes.xyz/ilker/llmgw/internal/control/adminapi" "github.com/spf13/cobra" ) func TestAQueuedChangeIsNotReportedAsAnError(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusAccepted) _, _ = w.Write([]byte(`{"queued":["r1"]}`)) })) defer srv.Close() var out struct { Queued []string `json:"queued"` } if err := newCtlClient(srv.URL).post(t.Context(), "/api/v1/restart", []byte(`{}`), &out); err != nil { t.Fatalf("202 read as a failure: %v", err) } if len(out.Queued) != 1 { t.Errorf("the body of a 202 was not read: %+v", out) } } func TestStatusSaysWhoLeadsTheStoreAndWhetherTheRestKeepUp(t *testing.T) { render := func(s adminapi.Summary) string { cmd := &cobra.Command{} var b bytes.Buffer cmd.SetOut(&b) printSummary(cmd, s) return b.String() } out := render(adminapi.Summary{Store: []adminapi.StoreMember{ {Name: "llmgw-ctl02", Role: "replica", State: "streaming", Lag: 2048}, {Name: "llmgw-pg01", Role: "leader", State: "running"}, }}) if !strings.Contains(out, "STORE llmgw-ctl02 streaming (2 KB behind), llmgw-pg01 leads") { t.Errorf("status:\n%s", out) } out = render(adminapi.Summary{Store: []adminapi.StoreMember{{Name: "llmgw-pg01", Role: "replica", State: "stopped"}}}) if !strings.Contains(out, "NO LEADER") { t.Errorf("a store with no leader was not called out:\n%s", out) } if out := render(adminapi.Summary{}); strings.Contains(out, "STORE") { t.Error("a single database got a store line") } } func TestTheSummaryIsWrittenWhereItIsToldNotToTheTerminal(t *testing.T) { // The console draws the summary into its panel. Its GPU table went to // the terminal instead, through the full screen, every three seconds — // on a cluster with a GPU, which the test cluster did not have. r, w, err := os.Pipe() if err != nil { t.Fatal(err) } stdout := os.Stdout os.Stdout = w var b bytes.Buffer cmd := &cobra.Command{} cmd.SetOut(&b) printSummary(cmd, adminapi.Summary{ GPUs: []adminapi.ClassUse{{Class: "6000-24g", Total: 1, Used: 1}}, Fabrics: []adminapi.FabricUse{{Fabric: "ib-a", Nodes: 2}}, IdleReplicas: []adminapi.IdleReplica{{ID: "r1", Model: "m", IdleSec: 3600, GPUs: 1}}, }) os.Stdout = stdout _ = w.Close() leaked, _ := io.ReadAll(r) if len(leaked) > 0 { t.Errorf("written to the terminal: %q", leaked) } for _, want := range []string{"6000-24g", "ib-a", "r1"} { if !strings.Contains(b.String(), want) { t.Errorf("the summary lacks %q:\n%s", want, b.String()) } } }