| 1 | package serve |
| 2 | |
| 3 | import ( |
| 4 | "bytes" |
| 5 | "context" |
| 6 | "encoding/json" |
| 7 | "net/http" |
| 8 | "net/http/httptest" |
| 9 | "testing" |
| 10 | |
| 11 | "reasonix/internal/boot" |
| 12 | "reasonix/internal/config" |
| 13 | "reasonix/internal/control" |
| 14 | ) |
| 15 | |
| 16 | func TestModelSettingsRejectsUnlistedModelBeforeRebuild(t *testing.T) { |
| 17 | for _, ref := range []string{"p/unlisted", "p/../../outside", "unlisted"} { |
| 18 | t.Run(ref, func(t *testing.T) { |
| 19 | old := control.New(control.Options{ModelRef: "p/m"}) |
| 20 | s := New(old, NewBroadcaster(), config.ServeConfig{AuthMode: "none"}) |
| 21 | t.Cleanup(s.Close) |
| 22 | s.buildControllerWithOptions = func(context.Context, string, boot.Options) (*control.Controller, error) { |
| 23 | t.Fatal("unlisted selector reached the runtime builder") |
| 24 | return nil, nil |
| 25 | } |
| 26 | body, err := json.Marshal(map[string]any{"version": 1, "ref": ref, "settings": config.ModelRuntimeSettings{ |
| 27 | Revision: "new", Providers: []config.ProviderEntry{{Name: "p", Model: "m"}}, |
| 28 | }}) |
| 29 | if err != nil { |
| 30 | t.Fatal(err) |
| 31 | } |
| 32 | w := httptest.NewRecorder() |
| 33 | s.applyModelSettings(w, httptest.NewRequest(http.MethodPost, "/model-settings", bytes.NewReader(body))) |
| 34 | if w.Code != http.StatusBadRequest || s.ctl() != old || s.managedModels != nil { |
| 35 | t.Fatalf("invalid selector changed runtime: status=%d", w.Code) |
| 36 | } |
| 37 | }) |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | func TestModelSettingsCatalogPreservesNamespacedModels(t *testing.T) { |
| 42 | providers := []config.ProviderEntry{{Name: "route", Models: []string{"vendor/model:tag"}}} |
| 43 | ref, ok := modelSettingsCatalogRef(providers, " route/vendor/model:tag ") |
| 44 | if !ok || ref != "route/vendor/model:tag" { |
| 45 | t.Fatalf("catalog model was changed: %q %v", ref, ok) |
| 46 | } |
| 47 | } |
| 48 |