Skip to content

test(proxy-stress-protocol): share proxy pair across concurrent tests - #33987

Merged
Jarred-Sumner merged 1 commit into
mainfrom
farm/f9371dab/deflake-proxy-stress-protocol
Jul 12, 2026
Merged

Jarred-Sumner merged 1 commit into
mainfrom
farm/f9371dab/deflake-proxy-stress-protocol

Conversation

@robobun

@robobun robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

test/js/bun/http/proxy-stress-protocol.test.ts has been flaking on darwin since it was added in #32635. Always exactly 1 of 102 tests, across darwin 14 x64 and 26 aarch64:

build 71945 (darwin 14 x64): the proxy's upstream dial reached an unrelated Express server instead of the test origin:

- "early"
+ "... Error ... Cannot POST / ..."
✗ early reply during upload > https-proxy → http-origin, 413 after 1KB of a 1MB upload

build 71690 (darwin 14 x64): reached a Verdaccio registry from another job on the same box:

- "final-5"
+ "... Verdaccio ... window.__VERDACCIO_BASENAME_UI_OPTIONS={...,\"base\":\"http://localhost:58343/\",...}"
✗ multi-hop redirect through proxy > https-proxy, 5-hop [s→h→s→h→s]

build 71696 (darwin 26 aarch64): 200 response from a server that was not the test origin:

TypeError: undefined is not an object (evaluating 'origin.requests[0].headers')
✗ large request headers through tunnel > http-proxy → http-origin, request header 512B

build 71727, build 71795: ConnectionRefused on the origin URL. All failed on the single CI retry.

Cause

Same mechanism #33975 diagnosed for proxy-stress-headers.test.ts and #33984 for proxy-stress-matrix.test.ts: 102 test.concurrent cases each create a fresh adversarial proxy + origin, issuing ~200 listen(0, "127.0.0.1") calls per file under the test runner's rolling concurrency window. As early tests dispose their servers, a later test's listen(0) can be handed a just-freed port while a sibling is still mid-dial (the proxy's net.connect(port, "localhost") goes through autoSelectFamily, adding async hops between port capture and connect). On the persistent darwin runners the "localhost" dial can additionally land on an unrelated IPv6 listener (Verdaccio / Express from another job), which is why builds 71690 and 71945 received recognisable third-party HTML.

Fix

Share one {http, https} proxy pair from beforeAll across the 68 tests that do not inspect proxy.connections (early-reply, large-headers, 1xx, HTTP/1.0, body-consumer matrices). The 32 tests that assert on the proxy's connection log (multi-hop redirect, IPv6, many proxy.headers, redirect manual/error) keep dedicated proxies. Per-file listen(0) churn drops from ~200 to ~134.

Coverage is unchanged: 102 tests, 508 expect() calls, identical to main. Same approach as the two open sibling PRs.

Introduced by #32635; sibling fixes are #33975 and #33984.

Verification

bun bd test test/js/bun/http/proxy-stress-protocol.test.ts   # 102 pass, 508 expect() (debug+ASAN)

15 consecutive debug+ASAN runs and 30 release runs on linux, all clean.


[stamp-90s] gate passed · iteration 0 · 1 files touched

passes on PR (with fix)
Test-only change.

Debug/ASAN (expected pass):
$ bun bd test 'test/js/bun/http/proxy-stress-protocol.test.ts'
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/js/bun/http/proxy-stress-protocol.test.ts
info: syncing channel updates for nightly-2026-05-06-x86_64-unknown-linux-gnu
info: latest update on 2026-05-06 for version 1.97.0-nightly (e95e73209 2026-05-05)
info: component rust-src is up to date
info: checking for self-update (current version: 1.29.0)
bun test v1.4.0 (e926c3577)

test/js/bun/http/proxy-stress-protocol.test.ts:
(pass) early reply during upload > http-proxy → http-origin, 413 after 1KB of a 1MB upload [818.20ms]
(pass) early reply during upload > http-proxy → http-origin, 400 after 1KB of a 1MB upload [787.76ms]
(pass) early reply during upload > http-proxy → http-origin, 500 after 1KB of a 1MB upload [788.48ms]
(pass) early reply during upload > http-proxy → https-origin, 413 after 1KB of a 1MB upload [988.57ms]
(pass) early reply during upload > http-proxy → https-origin, 400 after 1KB of a 1MB upload [1089.31ms]
(pass) early reply during upload > https-proxy → http-origin, 413 after 1KB of a 1MB upload [522.18ms]
(pass) early reply during upload > https-proxy → http-origin, 400 after 1KB of a 1MB upload [526.23ms]
(pass) early reply during upload > https-proxy → http-origin, 500 after 1KB of a 1MB upload [366.37ms]
(pass) early reply during upload > http-proxy → https-origin, 500 after 1KB of a 1MB upload [687.29ms]
(pass) early reply during upload > https-proxy → https-origin, 413 after 1KB of a 1MB upload [545.75ms]
(pass) early reply during upload > https-proxy → https-origin, 400 after 1KB of a 1MB upload [521.02ms]
(pass) early reply during upload > https-proxy → https-origin, 500 after 1KB of a 1MB upload [520.15ms]
(pass) multi-hop redirect through proxy > http-proxy, 3-hop [h→h→h] [915.91ms]
(pass) multi-hop redirect through proxy > http-proxy, 3-hop [s→s→s] [1297.09ms]
(pass) multi-hop redirect through proxy > https-proxy, 3-hop [h→h→h] [932.18ms]
(pass) multi-ho
... (truncated)
Exit: 0
diff hotspot
test/js/bun/http/proxy-stress-protocol.test.ts | 34 ++++++++++++++++++++------
 1 file changed, 26 insertions(+), 8 deletions(-)

gate history · 1 passed · 0 rejected · iteration 0

evidence per changed file
file                                            reads  edits  tests
test/js/bun/http/proxy-stress-protocol.test.ts      1     12      0

102 test.concurrent cases each created a fresh adversarial proxy and
origin, so ~200 listen(0, "127.0.0.1") calls per file under the test
runner's rolling concurrency window. On the persistent darwin runners
this has been flaking since #32635 added the suite: the proxy's
net.connect(port, "localhost") occasionally lands on an unrelated
server instead of the test's origin.

Share one {http, https} proxy pair from beforeAll across the 68 tests
that do not inspect proxy.connections. The 32 tests that assert on the
proxy's connection log (multi-hop redirect, IPv6, many proxy.headers,
redirect manual/error) keep dedicated proxies. Same approach as #33975
(proxy-stress-headers) and #33984 (proxy-stress-matrix).

102 tests / 508 expect() calls, identical to main.
@robobun

robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 11:43 AM PT - Jul 11th, 2026

❌ @robobun, your commit e926c35 has 4 failures in Build #71946 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 33987

That installs a local version of the PR into your bun-33987 executable, so you can run:

bun-33987 --bun

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b401d585-bd38-4ee6-8f35-3f6b80059743

📥 Commits

Reviewing files that changed from the base of the PR and between 588da0e and e926c35.

📒 Files selected for processing (1)
  • test/js/bun/http/proxy-stress-protocol.test.ts

Walkthrough

The proxy stress tests now share HTTP and HTTPS adversarial proxies across eligible tests, with lifecycle hooks for setup and cleanup. Tests inspecting connection state continue using dedicated proxies and document that requirement.

Changes

Proxy stress test reuse

Layer / File(s) Summary
Shared proxy lifecycle
test/js/bun/http/proxy-stress-protocol.test.ts
Adds shared HTTP/HTTPS proxy state, a TLS-based selector, and async setup and teardown hooks.
Proxy selection across tests
test/js/bun/http/proxy-stress-protocol.test.ts
Routes eligible protocol tests through shared proxies while retaining dedicated proxies for tests that inspect proxy.connections.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: sharing proxy pairs across concurrent proxy stress tests.
Description check ✅ Passed The description covers the problem, fix, and verification, though it does not use the repository's exact section headings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — test-only de-flake following the same pattern as #33975 and #33984.

Checked that every describe block switched to sharedProxy(...) (early-reply, large request/response headers, 1xx, HTTP/1.0, body consumers) only reads proxy.url and never touches proxy.connections, so sharing across test.concurrent is safe. The five blocks that assert on proxy.connections correctly retain dedicated await using proxies. afterAll uses ?.close() so a beforeAll failure won't throw during teardown.

Extended reasoning...

Overview

Test-only change to test/js/bun/http/proxy-stress-protocol.test.ts. Hoists two AdversarialProxy instances (one HTTP, one HTTPS) into beforeAll/afterAll and reuses them across the 68 concurrent test cases that only need proxy.url, instead of creating a fresh proxy per test. Tests that assert on the proxy's connections log keep dedicated per-test proxies with an explanatory comment. No production code touched.

Security risks

None. Test infrastructure only; no auth, crypto, permissions, or user-facing behavior changed.

Level of scrutiny

Low. This is a mechanical test refactor to reduce ephemeral-port churn causing darwin CI flakes, and it follows an already-established pattern from two sibling PRs (#33975 for proxy-stress-headers, #33984 for proxy-stress-matrix). The diff is small (~30 lines net), the intent is clear, and the PR description documents 15 debug+ASAN + 30 release verification runs with unchanged test/expect counts.

Other factors

  • Verified against proxy-stress-helpers.ts that AdversarialProxy is an exported interface with close(): Promise<void>, so the new import and await sharedHttpProxy?.close() are correct.
  • The shared proxy handles each client connection independently (net.createServer per-socket handler), so concurrent tests hitting the same proxy is safe as long as nothing reads the shared connections array — confirmed none of the switched tests do.
  • The sharedProxy arrow's tls parameter shadows the module-level tls import, but only within that one-line function — harmless.
  • Coverage is preserved: same 102 tests, same assertions; only the proxy lifetime changed.

@robobun

robobun commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

CI build 71946: proxy-stress-protocol.test.ts (the only file this PR touches) passed on every lane, including darwin 14 x64 where it previously flaked. Remaining red is unrelated to this diff and present across other recent builds:

Ready for review.

@Jarred-Sumner
Jarred-Sumner merged commit e77dc53 into main Jul 12, 2026
77 of 80 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the farm/f9371dab/deflake-proxy-stress-protocol branch July 12, 2026 04:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants