Files
llmgw/internal/cli/status_test.go
T
Ilker ManapandClaude Opus 5 d07dddb1bb Say plainly whether a model is serving, and why not
Reported after watching a model appear in ctl models before it could answer
anything. Checked: clients are not told early — /v1/models listed it only
once a replica was ready, and the chat picker reads the same source. The
operator view showing it is deliberate, because a model coming up is
exactly what someone running the cluster wants to see.

But the report pointed at something real. That view distinguished "a
replica is coming up" from "nothing could be placed" by a parenthetical —
"0/1 ready (1 total)" against "0/1 ready" — and those need opposite
responses: one means wait, the other means look at explain-placement. On
four models the difference is findable. On forty it is invisible, and a
model that will never start reads exactly like one that is thirty seconds
away.

SERVING now answers the question that was being asked of the replica counts
— can a client use this right now — and STATUS says which of ready,
starting, not placed or stopped is the case.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 06:34:04 +02:00

62 lines
2.1 KiB
Go

package cli
import (
"strings"
"testing"
"gitea.mynodes.xyz/ilker/llmgw/internal/control/adminapi"
)
func TestBarStaysWithinItsWidth(t *testing.T) {
// It is drawn from counts that can disagree briefly — a GPU freed between
// two reads — and a bar that overruns its column wrecks the table it is in.
for _, tc := range [][2]int{{0, 0}, {0, 8}, {8, 8}, {9, 8}, {100, 8}} {
got := bar(tc[0], tc[1])
if tc[1] == 0 {
if got != "" {
t.Errorf("bar(%d,%d) = %q, want empty for an empty class", tc[0], tc[1], got)
}
continue
}
if n := strings.Count(got, "#") + strings.Count(got, "."); n != 20 {
t.Errorf("bar(%d,%d) drew %d cells: %q", tc[0], tc[1], n, got)
}
}
}
func TestIdleColumnDistinguishesUnknownFromIdle(t *testing.T) {
// Every replica looks unreported before its first request and after a
// router restart. Showing that as a very large duration would make an
// untouched fleet read as an abandoned one.
if got := idleColumn(-1); got != "-" {
t.Errorf("idleColumn(-1) = %q, want a dash", got)
}
if got := idleColumn(90); got != "1m30s" {
t.Errorf("idleColumn(90) = %q", got)
}
}
func TestModelStatusSeparatesWaitingFromBroken(t *testing.T) {
// These used to differ by a parenthetical — "0/1 ready (1 total)" against
// "0/1 ready" — and they need opposite responses: one means wait, the other
// means look at explain-placement. On forty models that difference is
// invisible.
for _, tc := range []struct {
name string
view adminapi.ModelView
want string
}{
{"serving what it asked for", adminapi.ModelView{Min: 2, Ready: 2, Total: 2}, "ready"},
{"a replica is coming up", adminapi.ModelView{Min: 1, Ready: 0, Total: 1}, "starting"},
{"nothing could be placed", adminapi.ModelView{Min: 1, Ready: 0, Total: 0}, "not placed"},
{"deliberately not running", adminapi.ModelView{Min: 0, Ready: 0, Total: 0}, "stopped"},
{"short but rebuilding", adminapi.ModelView{Min: 2, Ready: 1, Total: 2}, "starting"},
} {
t.Run(tc.name, func(t *testing.T) {
if got := modelStatus(tc.view); got != tc.want {
t.Errorf("modelStatus(%+v) = %q, want %q", tc.view, got, tc.want)
}
})
}
}