diff --git a/test/cctest/test_environment_shared_isolate.cc b/test/cctest/test_environment_shared_isolate.cc index 3e86063b064c..b3807b7bb709 100644 --- a/test/cctest/test_environment_shared_isolate.cc +++ b/test/cctest/test_environment_shared_isolate.cc @@ -354,9 +354,13 @@ TEST_P(SharedIsolateTest, EnvironmentsComeAndGoWhileSiblingsRun) { " return 0;\n" "})()"), 0); - for (int turn = 0; turn < 10000; turn++) { + // Loop turns do not bound Worker startup time. Yield to the Worker and + // allow it to finish even when the main thread pumps the loop quickly. + const uint64_t deadline = uv_hrtime() + 30ULL * 1000 * 1000 * 1000; + while (uv_hrtime() < deadline) { PumpLoop(1); if (EvaluateInt(third.get(), "state.workerExit") == 7) break; + uv_sleep(1); } EXPECT_EQ(EvaluateInt(third.get(), "state.workerExit"), 7); } diff --git a/test/parallel/test-fastutf8stream-periodicflush.js b/test/parallel/test-fastutf8stream-periodicflush.js index 4889fa8b19eb..ed9f8aef883b 100644 --- a/test/parallel/test-fastutf8stream-periodicflush.js +++ b/test/parallel/test-fastutf8stream-periodicflush.js @@ -85,13 +85,12 @@ function runTests(sync) { minLength: 5000, periodicFlush: common.platformTimeout(10), }); - const timeout = setTimeout( - common.mustNotCall('periodic flush did not complete'), - common.platformTimeout(1000), - ); + // Periodic flush timers are unrefed. Keep the event loop alive until the + // write completes, and let the test runner enforce the timeout. + const keepAlive = setInterval(() => {}, 1000); stream.once('drain', common.mustCall(() => { - clearTimeout(timeout); + clearInterval(keepAlive); stream.destroy(); readFile(dest, 'utf8', common.mustSucceed((data) => { assert.strictEqual(data, 'periodic flush\n'); diff --git a/test/parallel/test-inspector-debug-end.js b/test/parallel/test-inspector-debug-end.js index 328f15628e3c..fe5a62430fde 100644 --- a/test/parallel/test-inspector-debug-end.js +++ b/test/parallel/test-inspector-debug-end.js @@ -22,18 +22,23 @@ async function testNoSessionNoCrash() { async function testSessionNoCrash() { console.log('Test there\'s no crash stopping server after connecting'); const script = `process._debugEnd(); - process._debugProcess(process.pid); - setTimeout(() => { - console.log("Done"); - process.exit(42); - });`; + process.stdin.once('data', () => { + console.log("Done"); + process.exit(42); + }); + process._debugProcess(process.pid);`; const instance = new NodeInstance('--inspect-brk=0', script); const session = await instance.connectInspectorSession(); await session.send({ method: 'NodeRuntime.enable' }); await session.waitForNotification('NodeRuntime.waitingForDebugger'); + instance.resetPort(); await session.send({ 'method': 'Runtime.runIfWaitingForDebugger' }); await session.waitForServerDisconnect(); + // _debugProcess() starts the inspector asynchronously. Wait for the new + // server to listen before asking the child to exit. + await instance.portPromise; + instance.write('exit'); assert.strictEqual((await instance.expectShutdown()).exitCode, 42); } diff --git a/test/parallel/test-net-autoselectfamily-local-port.js b/test/parallel/test-net-autoselectfamily-local-port.js index ba3ae408dfb5..ef13d8a70825 100644 --- a/test/parallel/test-net-autoselectfamily-local-port.js +++ b/test/parallel/test-net-autoselectfamily-local-port.js @@ -13,12 +13,17 @@ TCP.prototype.connect6 = function() { }; const reserved = createServer(); -reserved.listen(0, '127.0.0.1', common.mustCall(() => { +// Reserve both address families: an IPv4-only reservation may choose a port +// that is already in use by an IPv6-only socket. +reserved.listen(0, '::', common.mustCall(() => { const localPort = reserved.address().port; - reserved.close(common.mustCall(() => { - const server = createServer(common.mustCall((socket) => socket.end())); - server.listen(0, '127.0.0.1', common.mustCall(() => { - const port = server.address().port; + const server = createServer(common.mustCall((socket) => socket.end())); + // Keep the reservation until the destination listens so it cannot take + // the source port that the client is about to use. + server.listen(0, '127.0.0.1', common.mustCall(() => { + const port = server.address().port; + assert.notStrictEqual(port, localPort); + reserved.close(common.mustCall(() => { const connection = createConnection({ host: 'example.org', port, diff --git a/test/parallel/test-sqlite-statement.js b/test/parallel/test-sqlite-statement.js index 79e72a89d18a..a66ef9585be8 100644 --- a/test/parallel/test-sqlite-statement.js +++ b/test/parallel/test-sqlite-statement.js @@ -1,13 +1,11 @@ // Flags: --expose-gc 'use strict'; -const { enoughTestMem, skipIfSQLiteMissing } = require('../common'); +const { skipIfSQLiteMissing } = require('../common'); skipIfSQLiteMissing(); const { Database, Statement, - constants: { SQLITE_OK }, } = require('node:sqlite'); -const { constants } = require('node:buffer'); const { suite, test } = require('node:test'); suite('Statement() constructor', () => { @@ -1447,54 +1445,3 @@ suite('options.persistent', () => { t.assert.deepStrictEqual(stmt.get(), { __proto__: null, val: 42n }); }); }); - -suite('values larger than the maximum string length', { skip: !enoughTestMem }, () => { - // hex() doubles its input, so this is the smallest blob whose text form - // exceeds what V8 can hold in a string. - const blobSize = (constants.MAX_STRING_LENGTH >>> 1) + 1; - // '\u20ac' is 1 UTF-16 code unit but 3 UTF-8 bytes, so this identifier is a - // valid JS string whose UTF-8 form exceeds the limit. - const longIdentifier = '\u20ac'.repeat(Math.ceil(constants.MAX_STRING_LENGTH / 3) + 10); - const tooLong = { code: 'ERR_STRING_TOO_LONG', name: 'Error' }; - - test('get() throws instead of returning undefined', (t) => { - using db = new Database(':memory:'); - using stmt = db.prepare('SELECT hex(zeroblob(?))'); - t.assert.throws(() => { - stmt.get(blobSize); - }, tooLong); - }); - - test('prepare() throws when the SQLite error message is too long', (t) => { - using db = new Database(':memory:'); - // SQLite repeats the identifier in the error. - t.assert.throws(() => { - db.prepare(`SELECT 1 FROM "${longIdentifier}"`); - }, tooLong); - }); - - test('prepare() throws for an oversized authorizer argument', (t) => { - using db = new Database(':memory:'); - db.setAuthorizer(() => SQLITE_OK); - t.assert.throws(() => db.prepare(`CREATE TABLE "${longIdentifier}" (x)`), tooLong); - }); - - test('columns() throws for an oversized declared type', (t) => { - using db = new Database(':memory:'); - db.exec(`CREATE TABLE t (x "${longIdentifier}")`); - using stmt = db.prepare('SELECT x FROM t'); - t.assert.throws(() => stmt.columns(), tooLong); - }); - - test('exec() surfaces the error from a user-defined function', (t) => { - using db = new Database(':memory:'); - db.exec('CREATE TABLE data(val TEXT)'); - db.function('identity', (val) => val); - - t.assert.throws(() => { - db.exec(`INSERT INTO data (val) VALUES (identity(hex(zeroblob(${blobSize}))))`); - }, tooLong); - using stmt = db.prepare('SELECT count(*) AS count FROM data'); - t.assert.deepStrictEqual(stmt.get(), { __proto__: null, count: 0 }); - }); -}); diff --git a/test/pummel/test-sqlite-statement-too-long.js b/test/pummel/test-sqlite-statement-too-long.js new file mode 100644 index 000000000000..02c3faf0ac38 --- /dev/null +++ b/test/pummel/test-sqlite-statement-too-long.js @@ -0,0 +1,60 @@ +'use strict'; + +const { enoughTestMem, skipIfSQLiteMissing } = require('../common'); +skipIfSQLiteMissing(); +const { Database, constants: { SQLITE_OK } } = require('node:sqlite'); +const { constants } = require('node:buffer'); +const { suite, test } = require('node:test'); + +// These queries allocate strings and blobs of several hundred megabytes. +// Run them separately from the ordinary statement tests. +suite('values larger than the maximum string length', { skip: !enoughTestMem }, () => { + // hex() doubles its input, so this is the smallest blob whose text form + // exceeds what V8 can hold in a string. + const blobSize = (constants.MAX_STRING_LENGTH >>> 1) + 1; + // '\u20ac' is 1 UTF-16 code unit but 3 UTF-8 bytes, so this identifier is a + // valid JS string whose UTF-8 form exceeds the limit. + const longIdentifier = '\u20ac'.repeat(Math.ceil(constants.MAX_STRING_LENGTH / 3) + 10); + const tooLong = { code: 'ERR_STRING_TOO_LONG', name: 'Error' }; + + test('get() throws instead of returning undefined', (t) => { + using db = new Database(':memory:'); + using stmt = db.prepare('SELECT hex(zeroblob(?))'); + t.assert.throws(() => { + stmt.get(blobSize); + }, tooLong); + }); + + test('prepare() throws when the SQLite error message is too long', (t) => { + using db = new Database(':memory:'); + // SQLite repeats the identifier in the error. + t.assert.throws(() => { + db.prepare(`SELECT 1 FROM "${longIdentifier}"`); + }, tooLong); + }); + + test('prepare() throws for an oversized authorizer argument', (t) => { + using db = new Database(':memory:'); + db.setAuthorizer(() => SQLITE_OK); + t.assert.throws(() => db.prepare(`CREATE TABLE "${longIdentifier}" (x)`), tooLong); + }); + + test('columns() throws for an oversized declared type', (t) => { + using db = new Database(':memory:'); + db.exec(`CREATE TABLE t (x "${longIdentifier}")`); + using stmt = db.prepare('SELECT x FROM t'); + t.assert.throws(() => stmt.columns(), tooLong); + }); + + test('exec() surfaces the error from a user-defined function', (t) => { + using db = new Database(':memory:'); + db.exec('CREATE TABLE data(val TEXT)'); + db.function('identity', (val) => val); + + t.assert.throws(() => { + db.exec(`INSERT INTO data (val) VALUES (identity(hex(zeroblob(${blobSize}))))`); + }, tooLong); + using stmt = db.prepare('SELECT count(*) AS count FROM data'); + t.assert.deepStrictEqual(stmt.get(), { __proto__: null, count: 0 }); + }); +}); diff --git a/test/report/test-report-process-timeout-worker.js b/test/report/test-report-process-timeout-worker.js index a42e2513ccba..d7fe24a7a0d0 100644 --- a/test/report/test-report-process-timeout-worker.js +++ b/test/report/test-report-process-timeout-worker.js @@ -31,6 +31,12 @@ for (let timeout = common.platformTimeout(1000); ; timeout *= 2) { marker, ], { cwd: tmpdir.path, encoding: 'utf8' }); + // If startup did not reach the blocked Worker, the watchdog may have + // interrupted report generation too. Retry before reading that report. + if (!fs.existsSync(marker) && timeout < common.platformTimeout(16000)) { + continue; + } + const reports = helper.findReports(child.pid, tmpdir.path); assert.strictEqual(reports.length, 1, child.stderr); helper.validate(reports[0], [