test: extract AI Gateway test helpers for chatd#26639
Conversation
|
/coder-agents-review |
|
Chat: Review posted | View chat Review historydeep-review v0.9.0 | Round 3 | Last posted: Round 3, 10 findings (1 P2, 3 P3, 6 Nit), APPROVE. Review Finding inventoryFindings
| CRF-11 | Nit | Open | mock_aibridge_transport.go:29 | "when one was set" implies APIKeyID can be empty; RoundTrip errors before recording when key is absent | R3 | Gon P3, Leorio Nit | Yes | Round logRound 1Netero-only. 1 P2, 1 P3. Reviewed against 44f2a77..0c0ee00. Round 2Panel (17 reviewers). CRF-1, CRF-2 addressed. 2 P3, 3 Nit new. 3 dropped. Reviewed against 44f2a77..d858ca7. Round 3Panel (10 reviewers). CRF-3 through CRF-7 addressed. 3 Nit new. Reviewed against 44f2a77..28189d1. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
There was a problem hiding this comment.
First-pass review (Netero). This is a mechanical review only; the full review panel has not yet reviewed this PR and will review after these findings are addressed.
Severity summary: 1 P2, 1 P3.
The extraction itself is clean. Both new packages compile, tests pass, and the deleted code has no orphaned references. Two things to address before the panel reviews.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
Panel review (17 reviewers). CRF-1 and CRF-2 from round 1 are verified fixed in d858ca7.
Severity summary: 2 P3, 3 Nit.
Clean extraction. The PR description's framing (sharing test helpers across package boundaries, avoiding import cycles) matches what the code does. The secondary improvements are all directionally correct: caller-controlled context and metrics on the daemon helper, enforced delegated API key invariant in the mock transport, and *http.Request recording that eliminates future struct-change churn. The RecordedRequest redesign is a genuine improvement over the flat struct it replaced.
Notes from the panel:
-
(Ryosuke)
coderd/aibridgedtestimportscli, reaching upward in the dependency graph. No cycle, but the direction is unusual. If the 3-PR stack makesaibridgedtesta long-term fixture, relocatingBuildProviderstocoderd/aibridged(or a sibling) would eliminate the upward reach. Not a problem for this PR. -
(Ryosuke)
RecordedRequest.Requestis a shallow clone; the body reader is shared with the forwarded request. Current tests only inspect headers and URL, so this is inert. The doc says "shallow clone" which is accurate. A future test inspecting.Bodywould get EOF. -
(Gon)
MockAIBridgeTransportimplementsaibridge.TransportFactorybut is namedTransport. The existing convention (stubTransportFactoryincoderd/aibridge_test.go) uses the interface name. Not filed as a finding because the name is established and referenced in the PR; renaming would cascade. -
(Leorio) The PR description shows
StartTestAIBridgeDaemon(t *testing.T, ctx context.Context, ...)but the actual signature is(ctx context.Context, t *testing.T, ...)after the revive lint fix. Worth updating the description. -
(Leorio) "That mock aibridged transport error message is a masterpiece of test diagnostics" (paraphrased): names the constraint, the fix function, and where it belongs.
-
(Komugi) Stress-tested all four affected tests with
-race -count=10at GOMAXPROCS=1 and GOMAXPROCS=2. All green.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
All prior findings (CRF-1 through CRF-7) verified fixed across three rounds. 10 reviewers, 7 returned no findings. CI pending.
Clean extraction. The fixes over the three rounds were all genuine: build tag added, loop-all assertions restored, defer ordering corrected, docs rewritten with parameter coverage, slices.Clone restored, testing.TB adopted. No fix introduced a regression.
3 Nits below for optional polish. None blocking.
"A mock that silently accepts missing invariants is costume jewelry pretending to be a safety net." (Bisky, on the delegated API key enforcement upgrade)
🤖 This review was automatically generated with Coder Agents.
Extracts test infrastructure for AI Gateway routing into shared helpers so both AGPL and enterprise tests can use them.
Two helpers:
aibridgedtest.StartTestAIBridgeDaemon(incoderd/aibridgedtest/aibridgedtest.go,!slimbuild tag) — a real in-process aibridged daemon wired to fake upstream providers. Extracted fromenterprise/coderd/aibridge_reload_test.go'sstartTestAIBridgeDaemon. Stands up the real aibridge stack: cached bridge pool, DRPC backend, provider reload subscription, in-memory HTTP handler. Tests that create AI provider rows withBaseURLpointing athttptest.ServerURLs get their requests proxied through the real aibridged transport: auth header injection, SSE streaming, request recording, and path rewriting all run as they would in production. No mock maintenance, no drift.Signature:
StartTestAIBridgeDaemon(ctx context.Context, t testing.TB, api *coderd.API, metrics *aibridged.Metrics). Caller controls context cancellation and owns the metrics instance (passaibridged.NewMetrics(prometheus.NewRegistry())or nil for a throwaway).Lives in a separate
coderd/aibridgedtestpackage to avoid an import cycle:coderdtestis imported byclitest files, and the helper needscli.BuildProviders, so it cannot live incoderdtest.chattest.MockAIBridgeTransport(incoderd/x/chatd/chattest/mock_aibridge_transport.go) — a mockaibridge.TransportFactoryfor the 3 bare-chatd tests that usenewActiveTestServer(no full coderd API, can't callCreateInMemoryAIBridgeServer). Extracted fromchatd_test.go'schatAIGatewayTestFactory. Redirects requests to a target URL (mock provider server) and records each request via a cloned*http.Request. Mirrors the real aibridged transport's delegated API key invariant. Uses functional options:NewMockAIBridgeTransport(t, url, opts...)withWithPreservePath()option.Why both: The 19 full-server tests have a
coderd.APIavailable and can use the real daemon viaapi.RegisterInMemoryAIBridgedHTTPHandler. The 3 bare-chatd tests usenewActiveTestServer(no coderd API) and can't callCreateInMemoryAIBridgeServer, so they need the mock transport. The real daemon approach uses realaibridge.Providerimplementations pointing athttptest.ServerURLs — the "fake" is the upstream HTTP server, not a mocked interface. No drift risk.No production code changes. All existing tests pass.
This is PR 1 of a 3-PR stack that removes the
AIGatewayRoutingEnabledflag and its dead direct routing paths.