fix(test-runner): WebServer: use socket for reuseExistingServer to detect servers that aren't using SO_REUSEADDR (#8537)

This commit is contained in:
Fokke Zandbergen 2021-09-02 18:39:41 +02:00 committed by GitHub
parent bafa426231
commit 0ae38b5aec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 20 deletions

View File

@ -54,7 +54,7 @@ export class WebServer {
let processExitedReject = (error: Error) => { };
this._processExitedPromise = new Promise((_, reject) => processExitedReject = reject);
const portIsUsed = !await canBindPort(this.config.port);
const portIsUsed = await isPortUsed(this.config.port);
if (portIsUsed) {
if (this.config.reuseExistingServer)
return;
@ -104,31 +104,23 @@ export class WebServer {
}
}
async function canBindPort(port: number): Promise<boolean> {
async function isPortUsed(port: number): Promise<boolean> {
return new Promise<boolean>(resolve => {
const server = net.createServer();
server.on('error', () => resolve(false));
server.listen(port, () => {
server.close(() => {
resolve(true);
});
});
const conn = net
.connect(port)
.on('error', () => {
resolve(false);
})
.on('connect', () => {
conn.end();
resolve(true);
});
});
}
async function waitForSocket(port: number, delay: number, cancellationToken: { canceled: boolean }) {
while (!cancellationToken.canceled) {
const connected = await new Promise(resolve => {
const conn = net
.connect(port)
.on('error', () => {
resolve(false);
})
.on('connect', () => {
conn.end();
resolve(true);
});
});
const connected = await isPortUsed(port);
if (connected)
return;
await new Promise(x => setTimeout(x, delay));

View File

@ -225,3 +225,37 @@ test('should throw when a server is already running on the given port and strict
expect(result.output).toContain(`Port ${port} is used, make sure that nothing is running on the port`);
await new Promise(resolve => server.close(resolve));
});
for (const host of ['localhost', '127.0.0.1', '0.0.0.0']) {
test(`should detect the server if a web-server is already running on ${host}`, async ({ runInlineTest }, { workerIndex }) => {
const port = workerIndex + 10500;
const server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
res.end('<html><body>hello</body></html>');
});
await new Promise(resolve => server.listen(port, host, resolve));
try {
const result = await runInlineTest({
'test.spec.ts': `
const { test } = pwt;
test('connect to the server via the baseURL', async ({baseURL, page}) => {
await page.goto('/hello');
expect(await page.textContent('body')).toBe('hello');
});
`,
'playwright.config.ts': `
module.exports = {
webServer: {
command: 'node -e "process.exit(1)"',
port: ${port},
reuseExistingServer: false,
}
};
`,
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`Port ${port} is used, make sure that nothing is running on the port`);
} finally {
await new Promise(resolve => server.close(resolve));
}
});
}