diff --git a/internal/tuic/server_test.go b/internal/tuic/server_test.go index 5d7f7316a..baf505d79 100644 --- a/internal/tuic/server_test.go +++ b/internal/tuic/server_test.go @@ -196,12 +196,30 @@ func testServerTCPConnectE2E(t *testing.T, controller string) { t.Fatalf("expected active email alice@example.com, got %v", activeEmails) } - deltas := server.CollectClientTraffic() - if len(deltas) == 0 { - t.Fatalf("expected traffic deltas, got none") - } - if deltas[0].Email != "alice@example.com" || deltas[0].Up < int64(len(testMsg)) || deltas[0].Down < int64(len(testMsg)) { - t.Fatalf("unexpected traffic deltas: %+v", deltas[0]) + waitForClientTraffic(t, server, "alice@example.com", int64(len(testMsg))) +} + +// waitForClientTraffic accumulates drained deltas because the up and down counters are +// bumped on different relay goroutines, so the echo can arrive before the upload is counted. +func waitForClientTraffic(t *testing.T, server *Server, email string, minBytes int64) { + t.Helper() + var up, down int64 + deadline := time.Now().Add(4 * time.Second) + for { + for _, delta := range server.CollectClientTraffic() { + if delta.Email != email { + t.Fatalf("unexpected traffic delta for %q: %+v", delta.Email, delta) + } + up += delta.Up + down += delta.Down + } + if up >= minBytes && down >= minBytes { + return + } + if time.Now().After(deadline) { + t.Fatalf("traffic for %s = up %d, down %d; want both >= %d", email, up, down, minBytes) + } + time.Sleep(5 * time.Millisecond) } } @@ -356,13 +374,7 @@ func testServerUDPDatagramE2E(t *testing.T, controller string) { } // 4. Verify traffic - deltas := server.CollectClientTraffic() - if len(deltas) == 0 { - t.Fatalf("expected traffic deltas, got none") - } - if deltas[0].Email != "bob@example.com" || deltas[0].Up < int64(len(udpMsg)) || deltas[0].Down < int64(len(udpMsg)) { - t.Fatalf("unexpected traffic deltas: %+v", deltas[0]) - } + waitForClientTraffic(t, server, "bob@example.com", int64(len(udpMsg))) } func TestServerUDPStreamE2E(t *testing.T) {