test(fix): reserve the ZAP port in AllocateMiniPorts (fixes multi-master flakiness)

Every ZAP-native service binds THREE ports — http P, grpc P+10000, and its
native ZAP transport pb.ZapPort(grpc)=P+20000 — but AllocateMiniPorts only
reserved/verified P and P+10000. Two masters in one cluster could therefore be
handed colliding ZAP ports; the loser Fatalf's on its ZAP listener at startup
and is later unreachable ("connection refused"). Probabilistic, so it only
surfaced running the multi_master suite in sequence (TestSurvivorKeepsWriting /
TestWriterConsistency failed in the full run though each passed alone).

Reserve and net.Listen-verify the ZAP port too, and require it in-range so the
reserved port equals the master's actual (un-rotated) ZAP port. Benefits every
ZAP-based mini test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zeekay
2026-07-02 22:51:41 -07:00
co-authored by Claude Opus 4.8
parent 539d04023d
commit a6cedd73d5
+19 -2
View File
@@ -100,8 +100,17 @@ func AllocateMiniPorts(count int) ([]int, error) {
for i := 0; i < 1000; i++ {
port := minPort + rand.Intn(maxPort-minPort)
grpcPort := port + GrpcPortOffset
// Every ZAP-native service (master, filer, IAM) serves its native
// transport on grpcPort+GrpcPortOffset (pb.ZapPort). Reserve that third
// port too — otherwise two nodes in one cluster can collide on a ZAP
// port and the loser Fatalf's on its ZAP listener at startup. Require it
// in-range so the reserved port equals the actual (un-rotated) ZAP port.
zapPort := grpcPort + GrpcPortOffset
if zapPort > 65535 {
continue
}
if reserved[port] || reserved[grpcPort] {
if reserved[port] || reserved[grpcPort] || reserved[zapPort] {
continue
}
@@ -116,9 +125,17 @@ func AllocateMiniPorts(count int) ([]int, error) {
continue
}
listeners = append(listeners, l1, l2)
l3, err := net.Listen("tcp", fmt.Sprintf(":%d", zapPort))
if err != nil {
l1.Close()
l2.Close()
continue
}
listeners = append(listeners, l1, l2, l3)
reserved[port] = true
reserved[grpcPort] = true
reserved[zapPort] = true
ports = append(ports, port)
found = true
break