test(offered-models): cover ListOfferedModels branches (core#2608) #2815
Reference in New Issue
Block a user
Delete Branch "test/offered-models-coverage"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Tests-only PR that closes a coverage gap on
workspace-server/internal/handlers/offered_models.go(CTO 2026-06-11 model-discovery endpoint, wired atGET /admin/llm/offered-models). The single existing testTestListOfferedModels_ClaudeCode(inmodel_registry_validation_2608_test.go) covers the happy path on?runtime=claude-codeand verifies two representative model entries. This PR adds a focused test file pinning every other branch ofListOfferedModels.Refs #2151 (handler real-infra coverage series — smallest first; the unit-test surface is a strictly smaller increment than the chunk-2/7 real-PG integration work in #2171, and this endpoint is wired in
internal/router/router.go:215as a production surface, not a mock-only one).Branches pinned
TestListOfferedModels_DefaultRuntime— empty / missing?runtimequery defaults to"claude-code"; resolved runtime is echoed in the response.TestListOfferedModels_UnknownRuntime—?runtime=does-not-existreturns 404 with{"error":"unknown runtime","runtime":"<raw>"}body.TestListOfferedModels_RegistryLoadError—providerRegistryreturning an error surfaces as 503 with"provider registry unavailable"body (uses the existing package-levelproviderRegistryswap seam fromllm_billing_mode.go:61, restored viat.Cleanup).TestListOfferedModels_SortOrder— manifest declares zulu/alpha/mike; response must be alphabetic-sorted (the existing test does not pin order, only membership of two entries).TestListOfferedModels_BYOKAuthEnv— platform entries must omitauth_enventirely (omitempty); BYOK entries must surface the BYOK env name. BothPlatformBilledflag andProvidername are asserted per model.TestListOfferedModels_AmbiguousModelSkipped— fixture triggersDeriveProvider's fail-closed ambiguity branch (model id matches two prefixes, not in any exact-list, no auth context); the ambiguous id must be dropped from the response, sibling unambiguous ids must survive.Why a hand-built manifest, not the embedded providers.yaml
workspace_provision_derive_test.goalready establishes the pattern: build a small*providers.Manifestin-test so the assertions are deterministic and do not churn when the embedded registry evolves. The fixture covers the same shapesDeriveProviderexercises end-to-end (native-arm, exact-list, prefix-match, auth-env disambiguation) without depending on the production YAML.Test plan (local)
Pre-existing tests in the same neighborhood still pass:
TestCreate_BYOKModelNoCredential_422,TestCreate_PlatformSlashModel_NoQueries,TestPendingUploads_Ack,TestListOfferedModels_ClaudeCode.The broader
go test ./internal/handlers/run has pre-existing sqlmock-mismatch failures inpending_uploads/workspace_create/delegationtest families (visible on main with this branch reverted — these are the same class #2171 verify-on-main analysis identified as out-of-scope for the chunk-2 PR). They are NOT caused by this PR; the PR only adds a new file.Files changed
workspace-server/internal/handlers/offered_models_test.go(new file, 374 lines) — 6 new test functions + 2 helpers (offeredModelsTestManifest,withSwappedProviderRegistry,callListOfferedModels).No production code, no schema, no migration, no backwards-compat shim. Strictly tests-only.
🤖 Generated with Claude Code
REQUEST_CHANGES on head
87a6d507.Blocking test-quality finding: TestListOfferedModels_AmbiguousModelSkipped does not exercise the branch it claims to cover.
The handler does:
ModelsForRuntime only returns exact model ids listed in the runtime's native provider refs. In this test, shared-gpt-4o is not present in any ref.Models list, so it is never included in models and DeriveProvider is never called for it. The assertion that shared-gpt-4o is absent would pass even if the handler's dErr continue branch were deleted entirely, because the model never entered the loop. That makes the regression test tautological and leaves the claimed branch unpinned.
Please adjust the fixture so an id returned by ModelsForRuntime actually causes DeriveProvider to return an error. One viable shape is a hand-built manifest where the runtime's ModelsForRuntime includes the model through a ref whose provider is not in the provider catalog, while other native refs/providers make the same model prefix ambiguous, so the loop sees the id and DeriveProvider errors. Then assert a sibling valid model survives and the erroring listed model is dropped.
Other added tests look directionally reasonable, but this PR's stated goal is branch coverage for ListOfferedModels, and this branch is currently not covered.
APPROVED on head
33f33740.Reviewed the test-only
offered_models_test.goaddition. The branch coverage is meaningful: default runtime checks the resolved top-level runtime + model count, unknown runtime pins the 404 body, registry load failure pins the 503 path, sort order uses intentionally unsorted fixture data, BYOK checks both populated auth_env and platform omitempty behavior, and the ambiguous/skip test now uses a ghost provider ref whose model is returned byModelsForRuntimebut cannot resolve throughDeriveProvider.The ghost-co fixture is sound for this unit level: it deliberately bypasses manifest load validation to exercise the runtime handler branch where
DeriveProvidererrors for a listed model. The siblingalpha-survivesassertion keeps the test from passing by emptying the whole response, so thedErr { continue }path is load-bearing rather than tautological.I could not run Go tests locally because this container lacks
go, but live CI on33f33740hasCI / Platform (Go),E2E API Smoke Test, andCI / all-requiredgreen. Remaining red statuses are governance/review ceremony.APPROVED on head
33f33740.Re-reviewed the #11570 fix. The ambiguous/unselectable-model test now genuinely reaches the handler's
dErr != nil { continue }branch:ModelsForRuntime("split")returns bothalpha-survivesandghost-drops, thenDeriveProviderresolves the real catalog ref and errors on the danglingghost-coref because it is absent from the provider catalog and no prefix fallback matches. If the continue were removed,ghost-dropswould be appended and the new assertion would fail; the test is no longer tautological.The hand-built
providers.Manifestis acceptable here: this unit is explicitly testing the runtime handler path and DeriveProvider failure behavior, not manifest load validation. The fixture bypasses parse-time validation only to create the runtime-unselectable state needed to pin the branch. The sibling-survives assertion also guards against accidentally dropping the whole response on one bad model.Other branch tests remain scoped to the same new test file. Verified current-head CI: Platform Go, Handlers Postgres, Shellcheck, and
CI / all-requiredare green on33f33740. Remaining gate/review status is review ceremony, not a code/test blocker.