mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-14 14:23:14 -06:00
The subprocess-booting test suites hand-picked fixed ports in a cramped ~3955-4021 range, and 156-schedule-read-path deviated to a RANDOM port (3900 + rand%90) that overlapped those fixed ports. Under CI load two servers could race on the same port, surfacing as flaky "no such table: devices" / "FOREIGN KEY constraint failed" (a server answering a request against a half-migrated or wrong DB). It's environmental — the suites pass locally and in isolation. Fix: a shared test/helpers/free-port.js (bind :0 on loopback, read the OS-assigned port, release) called in before() so every suite gets a guaranteed-unique ephemeral port — concurrent suites can no longer collide, and no one has to hand-assign ports. - Codemod converted 30 suites: const PORT = <fixed|random> -> let PORT (+ BASE) assigned via `PORT = await freePort()` at the top of before(). - 3 hand-fixed (different structure): 148-eviction-storm (lowercase `base`), boot-health (no before() — allocates PORT + a throwaway SEED_PORT inside the test, replacing the hardcoded 3894), totp-keyrotation (no before() — allocates at the test start before bootServer()). No fixed 39xx/40xx ports remain. Full server suite 435/435; the 4 hand-touched suites pass in isolation. Pure test-infra change — no app code touched.
22 lines
809 B
JavaScript
22 lines
809 B
JavaScript
'use strict';
|
|
const net = require('net');
|
|
|
|
// Allocate a free TCP port from the OS (bind :0 on loopback, read it back, release it).
|
|
// Subprocess test suites call this in before() instead of hand-picking a fixed/random port —
|
|
// the old 39xx scheme collided under CI load (a random port in the shared range, or a new
|
|
// suite reusing one), surfacing as flaky "no such table: devices" / FK errors when two servers
|
|
// raced on the same port. An OS-assigned ephemeral port per suite can't collide.
|
|
function freePort() {
|
|
return new Promise((resolve, reject) => {
|
|
const srv = net.createServer();
|
|
srv.unref();
|
|
srv.on('error', reject);
|
|
srv.listen(0, '127.0.0.1', () => {
|
|
const port = srv.address().port;
|
|
srv.close(() => resolve(port));
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports = { freePort };
|