From 248d2045fd51a7190858e33ecd3da91fb0c973a1 Mon Sep 17 00:00:00 2001 From: n30nex Date: Wed, 30 Sep 2026 05:39:25 -0400 Subject: [PATCH] test(server): await indexes before node-path regression requests (#2084) Fixes #2083. Node-path regression tests could request `/paths` while background indexes were still loading, intermittently receiving HTTP 503 instead of exercising hop resolution or sorting. Seven fixture loads now await the existing bounded `WaitIndexesReady` signal. The anchor-bias test uses the same signal instead of polling. This changes five test files only. Production readiness behavior and every HTTP/content assertion are preserved. No dependencies, configuration or customizer changes. ## Validation - Unchanged baseline: 94 passed / 6 failed across 100 targeted executions; failures were actual HTTP 503 assertions. - Fixed setup: 200/200 targeted executions passed. - Parent independently ran the entire server suite: exit 0, 83.4 seconds. - All 183 standalone frontend suites and 20 real Chromium route-map checks passed. - Formatting, whitespace and PII checks passed. TDD justification: test-fixture synchronization repair, with no production logic change. The existing unchanged behavioral assertions supplied the before/after failure proof; no fabricated failing test was added. Local browser checks used Chromium against the unchanged production source; OpenClaw profile/external preflight were unavailable. The unrelated ingestor symlink test requires a Windows privilege absent locally; Linux CI validates that suite. Final CI must pass before merge. --- cmd/server/paths_anchor_bias_test.go | 13 ++----------- cmd/server/paths_hop_name_test.go | 3 +++ cmd/server/paths_sort_test.go | 6 ++++++ cmd/server/paths_through_collision_1352_test.go | 6 ++++++ cmd/server/paths_through_test.go | 3 +++ 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cmd/server/paths_anchor_bias_test.go b/cmd/server/paths_anchor_bias_test.go index 5678c404..1a966c5d 100644 --- a/cmd/server/paths_anchor_bias_test.go +++ b/cmd/server/paths_anchor_bias_test.go @@ -78,17 +78,8 @@ func TestHandleNodePaths_AnchorBiasInconsistency_Issue1278(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } - // The path-hop index that /paths reads is built in a background goroutine - // (#1008); querying before it is ready races the build and yields a - // non-deterministic membership/canonical result (the flake). Wait for - // readiness so the test asserts against the fully-built index. - pathHopDeadline := time.After(5 * time.Second) - for !store.PathHopIndexReady() { - select { - case <-pathHopDeadline: - t.Fatal("path-hop index not ready within 5s") - case <-time.After(10 * time.Millisecond): - } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") } srv.store = store router := mux.NewRouter() diff --git a/cmd/server/paths_hop_name_test.go b/cmd/server/paths_hop_name_test.go index cee2fd06..56d6408e 100644 --- a/cmd/server/paths_hop_name_test.go +++ b/cmd/server/paths_hop_name_test.go @@ -45,6 +45,9 @@ func TestHandleNodePaths_HopName_CanonicalPathShowsTarget_1144(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } srv.store = store router := mux.NewRouter() srv.RegisterRoutes(router) diff --git a/cmd/server/paths_sort_test.go b/cmd/server/paths_sort_test.go index 1e9efcc2..aad84c1f 100644 --- a/cmd/server/paths_sort_test.go +++ b/cmd/server/paths_sort_test.go @@ -80,6 +80,9 @@ func TestHandleNodePaths_SortByRecency_1145(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } srv.store = store router := mux.NewRouter() srv.RegisterRoutes(router) @@ -155,6 +158,9 @@ func TestHandleNodePaths_SortCountTiebreaker_1145(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } srv.store = store router := mux.NewRouter() srv.RegisterRoutes(router) diff --git a/cmd/server/paths_through_collision_1352_test.go b/cmd/server/paths_through_collision_1352_test.go index 013e15e8..00545bde 100644 --- a/cmd/server/paths_through_collision_1352_test.go +++ b/cmd/server/paths_through_collision_1352_test.go @@ -91,6 +91,9 @@ func (sc *collisionScenario) reloadStore(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } sc.srv.store = store router := mux.NewRouter() sc.srv.RegisterRoutes(router) @@ -222,6 +225,9 @@ func TestHandleNodePaths_FallbackUniquePrefix_1352(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } srv.store = store router := mux.NewRouter() srv.RegisterRoutes(router) diff --git a/cmd/server/paths_through_test.go b/cmd/server/paths_through_test.go index e60cd84d..ee049b85 100644 --- a/cmd/server/paths_through_test.go +++ b/cmd/server/paths_through_test.go @@ -49,6 +49,9 @@ func TestHandleNodePaths_PrefixCollisionExclusion(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load: %v", err) } + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatal("background indexes not ready within 5s") + } srv.store = store router := mux.NewRouter() srv.RegisterRoutes(router)