mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-18 05:47:38 +00:00
test(target-health): deterministic yaegi-check and non-blocking sweep tests
exerciseTargetHealth's traffic-sourced assertion (mcpProbeServerName must read healthy/traffic, F5 review) raced its own trigger: GET /admin/api/targets was the first-ever sweep-capable route this harness hit, so the background sweep it started could beat the response encode and overwrite source from traffic to probe under Yaegi's interpreter overhead. exerciseTargetHealthProbeWarmup now runs first, before exerciseHandler, against a dedicated, never- proxied MCP target — its health can only ever be written by the probe, so polling it to healthy/probe both proves the interpreted active-probe path end to end and spends this gateway's one probeInterval-bounded sweep before any traffic runs, making every later target-health assertion in this harness deterministic. probeInterval moves from 10s to 60s so no later exercise can trigger a second sweep mid-run. TARGETHEALTH-1's expected state also updates to unknown, reflecting F4 (a2d152b1): mcpProbeServerName's only observation is a failed tools/call, so it has never once succeeded. mcp_a2a_test.go's ClientCanceled_RecordsNothing test replaces its 30ms-cancel-vs-200ms-sleep timing margin with a channel handshake (cancel only once the handler is genuinely reached, then release it), removing any wall-clock dependence. Claude-Session: https://claude.ai/code/session_01EebV5jyWvYocByNQ3oss1w
This commit is contained in:
+26
-8
@@ -1100,13 +1100,26 @@ func TestHandleTargetProxy_TargetHealth_HangTripsWatchdog_RecordsUnhealthy(t *te
|
||||
// TestHandleTargetProxy_TargetHealth_ClientCanceled_RecordsNothing
|
||||
// proves a canceled CLIENT request records nothing at all — the target's
|
||||
// own health stays "unknown", not "unhealthy", since the client hanging
|
||||
// up says nothing about the target.
|
||||
// up says nothing about the target. F6, feat/target-health review: uses
|
||||
// a channel handshake (cancel only once the handler has genuinely been
|
||||
// reached, then release it) instead of a 30ms-cancel-vs-200ms-sleep
|
||||
// wall-clock margin, which left no slack under load and could either
|
||||
// cancel before the request reached the handler or fail to prove the
|
||||
// cancel raced a still-in-flight request.
|
||||
func TestHandleTargetProxy_TargetHealth_ClientCanceled_RecordsNothing(t *testing.T) {
|
||||
reached := make(chan struct{})
|
||||
release := make(chan struct{})
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
close(reached)
|
||||
<-release
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
// Registered in this order so t.Cleanup's LIFO order unblocks the
|
||||
// handler (closing release) BEFORE srv.Close runs — see
|
||||
// TestMaybeSweepTargetHealth_ConcurrentTriggers_SingleFlight's own
|
||||
// comment (target_health_test.go) for the identical reasoning.
|
||||
t.Cleanup(srv.Close)
|
||||
t.Cleanup(func() { close(release) })
|
||||
|
||||
cfg := newTargetHealthProxyConfig(srv.URL)
|
||||
h, err := New(context.Background(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), cfg, "llmgw")
|
||||
@@ -1116,13 +1129,18 @@ func TestHandleTargetProxy_TargetHealth_ClientCanceled_RecordsNothing(t *testing
|
||||
gw := h.(*Gateway)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
cancel()
|
||||
}()
|
||||
req := httptest.NewRequest(http.MethodGet, "/mcp/alpha/tools/list", nil).WithContext(ctx)
|
||||
req.Header.Set("Authorization", "Bearer sk-alice")
|
||||
h.ServeHTTP(httptest.NewRecorder(), req)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
h.ServeHTTP(httptest.NewRecorder(), req)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
<-reached
|
||||
cancel()
|
||||
<-done
|
||||
|
||||
snap := gw.targetHealth.snapshot(targetKindMCP, "alpha")
|
||||
if snap.state != targetHealthUnknown {
|
||||
|
||||
Reference in New Issue
Block a user