Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions tests/e2e/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { RspackDevServer: Server } = require('@rspack/dev-server');
const config = require('../fixtures/client-config/rspack.config');
const runBrowser = require('../helpers/run-browser');
const sessionSubscribe = require('../helpers/session-subscribe');
const { getRandomPorts } = require('../helpers/get-random-port');
const port = require('../helpers/ports-map').api;

describe('API', () => {
Expand Down Expand Up @@ -337,12 +338,19 @@ describe('API', () => {
});

describe('Server.getFreePort', () => {
let basePort;
let reservedPorts;
let dummyServers = [];
let devServerPort;

beforeEach(async () => {
reservedPorts = await getRandomPorts(8, '0.0.0.0');
[basePort] = reservedPorts;
});

afterEach(() => {
process.env.RSPACK_DEV_SERVER_BASE_PORT = undefined;
process.env.RSPACK_DEV_SERVER_PORT_RETRY = undefined;
delete process.env.RSPACK_DEV_SERVER_BASE_PORT;
delete process.env.RSPACK_DEV_SERVER_PORT_RETRY;

return dummyServers
.reduce(
Expand All @@ -363,14 +371,14 @@ describe('API', () => {
});

function createDummyServers(n) {
process.env.RSPACK_DEV_SERVER_BASE_PORT = 60000;
process.env.RSPACK_DEV_SERVER_BASE_PORT = `${basePort}`;

return (Array.isArray(n) ? n : [...new Array(n)]).reduce(
(p, _, i) =>
p.then(
() =>
new Promise((resolve) => {
devServerPort = 60000 + i;
devServerPort = basePort + i;
const compiler = rspack(config);
const server = new Server(
{ port: devServerPort, host: '0.0.0.0' },
Expand Down Expand Up @@ -407,7 +415,7 @@ describe('API', () => {

const freePort = await Server.getFreePort(null);

expect(freePort).toEqual(60000 + retryCount);
expect(freePort).toEqual(basePort + retryCount);

const { page, browser } = await runBrowser();

Expand Down Expand Up @@ -447,7 +455,7 @@ describe('API', () => {
// eslint-disable-next-line no-undefined
const freePort = await Server.getFreePort(undefined);

expect(freePort).toEqual(60000 + retryCount);
expect(freePort).toEqual(basePort + retryCount);

const { page, browser } = await runBrowser();

Expand Down Expand Up @@ -486,7 +494,7 @@ describe('API', () => {

const freePort = await Server.getFreePort();

expect(freePort).toEqual(60000 + retryCount);
expect(freePort).toEqual(basePort + retryCount);

const { page, browser } = await runBrowser();

Expand Down Expand Up @@ -525,7 +533,7 @@ describe('API', () => {

const freePort = await Server.getFreePort();

expect(freePort).toEqual(60000 + retryCount);
expect(freePort).toEqual(basePort + retryCount);

const { page, browser } = await runBrowser();

Expand Down Expand Up @@ -556,15 +564,15 @@ describe('API', () => {
});

it('should retry finding the port when serial ports are busy', async () => {
const busyPorts = [60000, 60001, 60002, 60003, 60004, 60005];
const busyPorts = reservedPorts.slice(0, 6);

process.env.RSPACK_DEV_SERVER_PORT_RETRY = 1000;

await createDummyServers(busyPorts);

const freePort = await Server.getFreePort();

expect(freePort).toBeGreaterThan(60005);
expect(freePort).toBeGreaterThan(busyPorts[busyPorts.length - 1]);

const { page, browser } = await runBrowser();

Expand Down
87 changes: 87 additions & 0 deletions tests/helpers/get-random-port.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
const net = require('node:net');

function isPortAvailable(port, host = '0.0.0.0') {
try {
const server = net.createServer();

server.unref();

return new Promise((resolve) => {
server.on('listening', () => {
server.close(() => {
resolve(true);
});
});
server.on('error', () => {
resolve(false);
});
server.listen(port, host);
});
} catch {
return false;
}
}

const portMap = new Map();

/**
* Get a random port.
* Available port ranges: 1024 ~ 65535
* `10080` is not available on macOS CI, `> 50000` gets "permission denied" on Windows,
* so we use `15000` ~ `45000`.
*/
async function getRandomPort(
defaultPort = Math.ceil(Math.random() * 30000) + 15000,
host,
) {
let port = defaultPort;

while (true) {
if (!portMap.get(port) && (await isPortAvailable(port, host))) {
portMap.set(port, 1);

return port;
}

port += 1;
}
}

async function getRandomPorts(count, host) {
let port = await getRandomPort(undefined, host);

while (true) {
let isAvailable = true;

for (let index = 0; index < count; index += 1) {
const currentPort = port + index;

if (
portMap.get(currentPort) ||
!(await isPortAvailable(currentPort, host))
) {
isAvailable = false;
port = currentPort + 1;
break;
}
}

if (isAvailable) {
const ports = [];

for (let index = 0; index < count; index += 1) {
const currentPort = port + index;

portMap.set(currentPort, 1);
ports.push(currentPort);
}

return ports;
}
}
}

module.exports = {
getRandomPort,
getRandomPorts,
};
Loading