package models import ( "strings" "testing" ) func testRouter(t *testing.T) *Router { t.Helper() tiers := map[string]string{ "mopac-study": "glm-4.7-flash", "mopac-code": "glm-5.2", "mopac-review": "glm-5-turbo", "mopac-primary": "glm-5.3", "mopac-vision": "glm-4.6v", } classes := map[string]string{ "study": "mopac-study", "read": "mopac-study", "code": "mopac-code", "review": "mopac-review", "primary": "mopac-primary", } r, err := NewRouter(tiers, classes, "mopac-primary") if err != nil { t.Fatalf("NewRouter: %v", err) } return r } func TestResolve(t *testing.T) { cases := []struct { class string tier string model string }{ {"study", "mopac-study", "glm-4.7-flash"}, {"read", "mopac-study", "glm-4.7-flash"}, {"code", "mopac-code", "glm-5.2"}, {"review", "mopac-review", "glm-5-turbo"}, {"primary", "mopac-primary", "glm-5.3"}, {"", "mopac-primary", "glm-5.3"}, // no class -> default tier } r := testRouter(t) for _, tc := range cases { d, err := r.Resolve(tc.class) if err != nil { t.Fatalf("Resolve(%q): %v", tc.class, err) } if d.Tier != tc.tier || d.Model != tc.model { t.Errorf("Resolve(%q) = %s/%s, want %s/%s", tc.class, d.Tier, d.Model, tc.tier, tc.model) } } } func TestResolveUnknownClassIsError(t *testing.T) { r := testRouter(t) _, err := r.Resolve("urgent") if err == nil { t.Fatal("unknown class must error (routing stays auditable)") } if !strings.Contains(err.Error(), `[models.classes]`) { t.Errorf("error should point at the config section: %v", err) } } func TestNewRouterValidation(t *testing.T) { tiers := map[string]string{"mopac-primary": "glm-5.3"} if _, err := NewRouter(tiers, nil, "mopac-missing"); err == nil || !strings.Contains(err.Error(), "default tier") { t.Errorf("missing default tier: err=%v", err) } if _, err := NewRouter(tiers, map[string]string{"x": "mopac-nope"}, "mopac-primary"); err == nil || !strings.Contains(err.Error(), "unknown tier") { t.Errorf("class to unknown tier: err=%v", err) } if _, err := NewRouter(nil, nil, "mopac-primary"); err == nil { t.Errorf("empty tiers must error") } } func TestClasses(t *testing.T) { // The serve front door builds its catalog from the sorted class list; // it must be complete and ordered for stable /v1/models output. got := testRouter(t).Classes() want := "code primary read review study" if strings.Join(got, " ") != want { t.Errorf("Classes() = %v, want %v", got, want) } }