carlos / platform Public

edge: pin rule-1 discrimination and fleet activator exclusion

Review fixes: TestFleetRouteProxiesToBoundBox bound to pi-1 while both
pi-1 and pi-2 were connected — since ConnectedOfFleet sorts ascending,
the fallback branch would also answer pi-1, so the test couldn't tell
rule 1 from rule 2 apart (verified: deleting fleetChannelFor's rule-1
branch left it green). Rebound to pi-2 (sorts last), so only rule 1 can
produce that answer; verified FAIL with the branch removed, PASS
restored. Also added TestFleetRouteIsNeverActivatorManaged, mirroring
TestTunnelRouteIsNeverActivatorManaged for the fleet dispatch case, so
the hibernation exclusion is pinned directly rather than resting only on
switch-case ordering.
Paul Campbell 0a40b94efc6f31c6a2d4a6162a268a2b350a1b00 parent d587832
1 file changed, +48 −5
  • internal/edge/fleet_route_test.go +48 −5
diff --git a/internal/edge/fleet_route_test.go b/internal/edge/fleet_route_test.go
index c27053362..a1764b490 100644
--- a/internal/edge/fleet_route_test.go
+++ b/internal/edge/fleet_route_test.go
@@ -85,12 +85,17 @@ func getHostFull(t *testing.T, edgeURL, host string) *http.Response {
}
// TestFleetRouteProxiesToBoundBox: rule 1 — a route bound (FleetBox) to a
-// box whose channel is connected rides that exact channel, even though a
-// second box of the same fleet is also connected and would sort first.
+// box whose channel is connected rides that exact channel. Bound to pi-2
+// DELIBERATELY, not pi-1: ConnectedOfFleet sorts ascending, so with both
+// connected the fallback rule (rule 2) would ALSO pick "acme/pi-1" — binding
+// there would make rule 1 and rule 2 indistinguishable (both answer "pi-1"),
+// and this test would stay green even with the entire rule-1 branch deleted
+// from fleetChannelFor. Binding to pi-2 (which sorts LAST) means only rule 1
+// can produce "pi-2" here — the fallback alone would answer "pi-1".
func TestFleetRouteProxiesToBoundBox(t *testing.T) {
edgeURL, hub := fleetTestEdge(t, map[string]string{"pi-1": "tok1", "pi-2": "tok2"}, registry.Route{
Host: "app.example", Kind: "instance", Status: "ready",
- Region: registry.PlacementTarget("acme"), FleetBox: "pi-1",
+ Region: registry.PlacementTarget("acme"), FleetBox: "pi-2",
})
stop1 := startFakeRemoteHost(t, edgeURL, "acme/pi-1", "tok1", namedHandler("pi-1"))
defer stop1()
@@ -100,8 +105,8 @@ func TestFleetRouteProxiesToBoundBox(t *testing.T) {
waitForTunnelState(t, hub, "acme/pi-2", "connected", e2eReconnectBound)
code, body := getHost(t, edgeURL, "app.example")
- if code != http.StatusOK || body != "pi-1" {
- t.Fatalf("got %d %q, want 200 %q (the bound box, not the fallback)", code, body, "pi-1")
+ if code != http.StatusOK || body != "pi-2" {
+ t.Fatalf("got %d %q, want 200 %q (the bound box, which sorts LAST — a fallback-only implementation would answer pi-1 instead)", code, body, "pi-2")
}
}
@@ -235,6 +240,44 @@ func TestNonFleetRoutesUntouchedByFleetDispatch(t *testing.T) {
}
}
+// TestFleetRouteIsNeverActivatorManaged mirrors
+// TestTunnelRouteIsNeverActivatorManaged (tunnel_test.go) for the fleet
+// dispatch case: a fleet-placed, Hibernate:true route must never be
+// activator-managed on THIS box — whichever box ends up serving it wakes its
+// OWN local instance, so a platform-side wake here would start a second copy
+// beside it. Today this rests on viaTunnel being set for the fleet case too
+// (edge.go); this test is the regression pin so a future reorder or refactor
+// of that switch can't silently drop it — the exclusion would otherwise only
+// be caught by the tunnel-specific test above, which a fleet-only regression
+// wouldn't touch at all.
+func TestFleetRouteIsNeverActivatorManaged(t *testing.T) {
+ reg := openReg(t)
+ if err := reg.Upsert(registry.Route{
+ Host: "fleet-hib.example", Kind: "instance", Status: "ready",
+ Region: registry.PlacementTarget("acme"), FleetBox: "pi-1", Hibernate: true,
+ }); err != nil {
+ t.Fatal(err)
+ }
+ act := &fakeActivator{}
+ e, err := New(reg, act)
+ if err != nil {
+ t.Fatal(err)
+ }
+ e.EnableTunnels(NewTunnelHub("tunnel.test", nil))
+ if err := e.Reload(); err != nil {
+ t.Fatal(err)
+ }
+ if last := act.retired[len(act.retired)-1]; last["fleet-hib.example"] {
+ t.Fatalf("fleet-served host kept in the activator's managed set: %v", last)
+ }
+ req := httptest.NewRequest("GET", "http://fleet-hib.example/", nil)
+ req.Host = "fleet-hib.example"
+ e.ServeHTTP(httptest.NewRecorder(), req)
+ if act.served != 0 {
+ t.Fatalf("activator woke a local process for a fleet-served host (%d call(s))", act.served)
+ }
+}
+
// TestConnectedOfFleetSortedAndFiltered pins ConnectedOfFleet directly: only
// names under "<fleet>/" come back, sorted, and a same-prefixed different
// fleet ("acme2") is never mistaken for a member of "acme".