Skip to content

Commit 7cf35cf

Browse files
h-a-n-aclaude
andauthored
fix(cli): resolve port conflicts in parallel test execution (#11363)
* fix(cli): resolve port conflicts in parallel test execution Fixes EADDRINUSE errors when running rspack-cli tests in parallel by: 1. Auto-assigning random ports to serve commands that don't specify --port 2. Using Jest worker ID to ensure unique port ranges per worker (similar to e2e tests) 3. Preventing multiple test workers from competing for default port 8080 This resolves flaky test failures in tests/serve/basic/serve-basic.test.ts and other serve tests when run concurrently. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * docs: improve getRandomPort function documentation Add comprehensive JSDoc explaining the port allocation strategy and how it prevents EADDRINUSE conflicts in parallel test execution. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 4b96924 commit 7cf35cf

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

packages/rspack-cli/tests/utils/test-utils.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,16 @@ const runWatch = (
114114
options: Record<string, any> = {},
115115
env: Record<string, any> = {}
116116
): any => {
117-
return new Promise((resolve, reject) => {
117+
return new Promise(async (resolve, reject) => {
118+
// For serve commands, automatically add random port if no --port specified
119+
if (args.includes("serve") && !args.some(arg => arg.startsWith("--port"))) {
120+
const randomPort = await getRandomPort();
121+
args.push(`--port=${randomPort}`);
122+
console.log(
123+
`[runWatch] Auto-assigned random port ${randomPort} for serve command`
124+
);
125+
}
126+
118127
const process = createProcess(cwd, args, options, env);
119128
const outputKillStr = options.killString || /rspack \d+\.\d+\.\d/;
120129

@@ -411,13 +420,26 @@ function isPortAvailable(port: number) {
411420

412421
const portMap = new Map();
413422

414-
// Available port ranges: 1024 ~ 65535
415-
// `10080` is not available in macOS CI, `> 50000` get 'permission denied' in Windows.
416-
// so we use `15000` ~ `45000`.
417-
export async function getRandomPort(
418-
defaultPort = Math.ceil(Math.random() * 30000) + 15000
419-
) {
420-
let port = defaultPort;
423+
/**
424+
* Get a random available port for testing.
425+
*
426+
* Uses Jest worker ID to assign unique base ports per worker to prevent conflicts
427+
* in parallel test execution. Similar to e2e tests approach:
428+
* - Worker 1 gets ports starting from 15000
429+
* - Worker 2 gets ports starting from 15100
430+
* - Worker 3 gets ports starting from 15200
431+
* - etc.
432+
*
433+
* Available port ranges: 1024 ~ 65535
434+
* `10080` is not available in macOS CI, `> 50000` get 'permission denied' in Windows.
435+
* So we use `15000` ~ `45000`.
436+
*/
437+
export async function getRandomPort(defaultPort?: number) {
438+
// Use Jest workerIndex to assign unique base ports, similar to e2e tests
439+
const workerIndex = parseInt(process.env.JEST_WORKER_ID || "1", 10);
440+
const basePort = defaultPort || 15000 + (workerIndex - 1) * 100;
441+
442+
let port = basePort;
421443
while (true) {
422444
if (!portMap.get(port) && (await isPortAvailable(port))) {
423445
portMap.set(port, 1);

0 commit comments

Comments
 (0)