mirror of
https://github.com/oven-sh/bun
synced 2026-02-08 09:58:55 +00:00
Compare commits
3 Commits
dylan/pyth
...
nektro-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87d43696bd | ||
|
|
34f37c59c2 | ||
|
|
1d3cff2dbc |
14
test/js/node/test/parallel/test-common-gc.js
Normal file
14
test/js/node/test/parallel/test-common-gc.js
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
// Flags: --expose-gc
|
||||
const common = require('../common');
|
||||
const { onGC } = require('../common/gc');
|
||||
|
||||
{
|
||||
onGC({}, { ongc: common.mustCall() });
|
||||
global.gc();
|
||||
}
|
||||
|
||||
{
|
||||
onGC(process, { ongc: common.mustNotCall() });
|
||||
global.gc();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Flags: --expose-gc
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
// This test verifies that when a V8 FinalizationRegistryCleanupTask is queue
|
||||
// at the last moment when JavaScript can be executed, the callback of a
|
||||
// FinalizationRegistry will not be invoked and the process should exit
|
||||
// normally.
|
||||
|
||||
const reg = new FinalizationRegistry(
|
||||
common.mustNotCall('This FinalizationRegistry callback should never be called'));
|
||||
|
||||
function register() {
|
||||
// Create a temporary object in a new function scope to allow it to be GC-ed.
|
||||
reg.register({});
|
||||
}
|
||||
|
||||
process.on('exit', () => {
|
||||
// This is the final chance to execute JavaScript.
|
||||
register();
|
||||
// Queue a FinalizationRegistryCleanupTask by a testing gc request.
|
||||
global.gc();
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (common.isIBMi)
|
||||
common.skip('IBMi does not support `fs.watch()`');
|
||||
|
||||
// fs-watch on folders have limited capability in AIX.
|
||||
// The testcase makes use of folder watching, and causes
|
||||
// hang. This behavior is documented. Skip this for AIX.
|
||||
|
||||
if (common.isAIX)
|
||||
common.skip('folder watch capability is limited in AIX.');
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const testDir = tmpdir.path;
|
||||
tmpdir.refresh();
|
||||
|
||||
// Add a file to newly created folder to already watching folder
|
||||
|
||||
const rootDirectory = fs.mkdtempSync(testDir + path.sep);
|
||||
const testDirectory = path.join(rootDirectory, 'test-3');
|
||||
fs.mkdirSync(testDirectory);
|
||||
|
||||
const filePath = path.join(testDirectory, 'folder-3');
|
||||
|
||||
const childrenFile = 'file-4.txt';
|
||||
const childrenAbsolutePath = path.join(filePath, childrenFile);
|
||||
const childrenRelativePath = path.join(path.basename(filePath), childrenFile);
|
||||
let watcherClosed = false;
|
||||
|
||||
const watcher = fs.watch(testDirectory, { recursive: true });
|
||||
watcher.on('change', function(event, filename) {
|
||||
if (filename === childrenRelativePath) {
|
||||
assert.strictEqual(event, 'rename');
|
||||
watcher.close();
|
||||
watcherClosed = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Do the write with a delay to ensure that the OS is ready to notify us.
|
||||
setTimeout(() => {
|
||||
fs.mkdirSync(filePath);
|
||||
fs.writeFileSync(childrenAbsolutePath, 'world');
|
||||
}, common.platformTimeout(200));
|
||||
|
||||
process.once('exit', function() {
|
||||
assert(watcherClosed, 'watcher Object was not closed');
|
||||
});
|
||||
111
test/js/node/test/parallel/test-fs-watch-recursive-symlink.js
Normal file
111
test/js/node/test/parallel/test-fs-watch-recursive-symlink.js
Normal file
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const { setTimeout } = require('timers/promises');
|
||||
|
||||
if (common.isIBMi)
|
||||
common.skip('IBMi does not support `fs.watch()`');
|
||||
|
||||
// fs-watch on folders have limited capability in AIX.
|
||||
// The testcase makes use of folder watching, and causes
|
||||
// hang. This behavior is documented. Skip this for AIX.
|
||||
|
||||
if (common.isAIX)
|
||||
common.skip('folder watch capability is limited in AIX.');
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const testDir = tmpdir.path;
|
||||
tmpdir.refresh();
|
||||
|
||||
(async () => {
|
||||
// Add a recursive symlink to the parent folder
|
||||
|
||||
const testDirectory = fs.mkdtempSync(testDir + path.sep);
|
||||
|
||||
// Do not use `testDirectory` as base. It will hang the tests.
|
||||
const rootDirectory = path.join(testDirectory, 'test-1');
|
||||
fs.mkdirSync(rootDirectory);
|
||||
|
||||
const filePath = path.join(rootDirectory, 'file.txt');
|
||||
|
||||
const symlinkFolder = path.join(rootDirectory, 'symlink-folder');
|
||||
fs.symlinkSync(rootDirectory, symlinkFolder);
|
||||
|
||||
if (common.isMacOS) {
|
||||
// On macOS delay watcher start to avoid leaking previous events.
|
||||
// Refs: https://github.com/libuv/libuv/pull/4503
|
||||
await setTimeout(common.platformTimeout(100));
|
||||
}
|
||||
|
||||
const watcher = fs.watch(rootDirectory, { recursive: true });
|
||||
let watcherClosed = false;
|
||||
watcher.on('change', function(event, filename) {
|
||||
assert.ok(event === 'rename', `Received ${event}`);
|
||||
assert.ok(filename === path.basename(symlinkFolder) || filename === path.basename(filePath), `Received ${filename}`);
|
||||
|
||||
if (filename === path.basename(filePath)) {
|
||||
watcher.close();
|
||||
watcherClosed = true;
|
||||
}
|
||||
});
|
||||
|
||||
await setTimeout(common.platformTimeout(100));
|
||||
fs.writeFileSync(filePath, 'world');
|
||||
|
||||
process.once('exit', function() {
|
||||
assert(watcherClosed, 'watcher Object was not closed');
|
||||
});
|
||||
})().then(common.mustCall());
|
||||
|
||||
(async () => {
|
||||
// This test checks how a symlink to outside the tracking folder can trigger change
|
||||
// tmp/sub-directory/tracking-folder/symlink-folder -> tmp/sub-directory
|
||||
|
||||
const rootDirectory = fs.mkdtempSync(testDir + path.sep);
|
||||
|
||||
const subDirectory = path.join(rootDirectory, 'sub-directory');
|
||||
fs.mkdirSync(subDirectory);
|
||||
|
||||
const trackingSubDirectory = path.join(subDirectory, 'tracking-folder');
|
||||
fs.mkdirSync(trackingSubDirectory);
|
||||
|
||||
const symlinkFolder = path.join(trackingSubDirectory, 'symlink-folder');
|
||||
fs.symlinkSync(subDirectory, symlinkFolder);
|
||||
|
||||
const forbiddenFile = path.join(subDirectory, 'forbidden.txt');
|
||||
const acceptableFile = path.join(trackingSubDirectory, 'acceptable.txt');
|
||||
|
||||
if (common.isMacOS) {
|
||||
// On macOS delay watcher start to avoid leaking previous events.
|
||||
// Refs: https://github.com/libuv/libuv/pull/4503
|
||||
await setTimeout(common.platformTimeout(100));
|
||||
}
|
||||
|
||||
const watcher = fs.watch(trackingSubDirectory, { recursive: true });
|
||||
let watcherClosed = false;
|
||||
watcher.on('change', function(event, filename) {
|
||||
// macOS will only change the following events:
|
||||
// { event: 'rename', filename: 'symlink-folder' }
|
||||
// { event: 'rename', filename: 'acceptable.txt' }
|
||||
assert.ok(event === 'rename', `Received ${event}`);
|
||||
assert.ok(filename === path.basename(symlinkFolder) || filename === path.basename(acceptableFile), `Received ${filename}`);
|
||||
|
||||
if (filename === path.basename(acceptableFile)) {
|
||||
watcher.close();
|
||||
watcherClosed = true;
|
||||
}
|
||||
});
|
||||
|
||||
await setTimeout(common.platformTimeout(100));
|
||||
fs.writeFileSync(forbiddenFile, 'world');
|
||||
await setTimeout(common.platformTimeout(100));
|
||||
fs.writeFileSync(acceptableFile, 'acceptable');
|
||||
|
||||
process.once('exit', function() {
|
||||
assert(watcherClosed, 'watcher Object was not closed');
|
||||
});
|
||||
})().then(common.mustCall());
|
||||
81
test/js/node/test/parallel/test-http-full-response.js
Normal file
81
test/js/node/test/parallel/test-http-full-response.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
// This test requires the program 'ab'
|
||||
const http = require('http');
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
const bodyLength = 12345;
|
||||
|
||||
const body = 'c'.repeat(bodyLength);
|
||||
|
||||
const server = http.createServer(function(req, res) {
|
||||
res.writeHead(200, {
|
||||
'Content-Length': bodyLength,
|
||||
'Content-Type': 'text/plain'
|
||||
});
|
||||
res.end(body);
|
||||
});
|
||||
|
||||
function runAb(opts, callback) {
|
||||
const command = `ab ${opts} http://127.0.0.1:${server.address().port}/`;
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
if (/ab|apr/i.test(stderr)) {
|
||||
common.printSkipMessage(`problem spawning \`ab\`.\n${stderr}`);
|
||||
process.reallyExit(0);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
let m = /Document Length:\s*(\d+) bytes/i.exec(stdout);
|
||||
const documentLength = parseInt(m[1]);
|
||||
|
||||
m = /Complete requests:\s*(\d+)/i.exec(stdout);
|
||||
const completeRequests = parseInt(m[1]);
|
||||
|
||||
m = /HTML transferred:\s*(\d+) bytes/i.exec(stdout);
|
||||
const htmlTransferred = parseInt(m[1]);
|
||||
|
||||
assert.strictEqual(bodyLength, documentLength);
|
||||
assert.strictEqual(completeRequests * documentLength, htmlTransferred);
|
||||
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
runAb('-c 1 -n 10', common.mustCall(function() {
|
||||
console.log('-c 1 -n 10 okay');
|
||||
|
||||
runAb('-c 1 -n 100', common.mustCall(function() {
|
||||
console.log('-c 1 -n 100 okay');
|
||||
|
||||
runAb('-c 1 -n 1000', common.mustCall(function() {
|
||||
console.log('-c 1 -n 1000 okay');
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
44
test/js/node/test/parallel/test-http-no-content-length.js
Normal file
44
test/js/node/test/parallel/test-http-no-content-length.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const http = require('http');
|
||||
|
||||
const server = net.createServer(function(socket) {
|
||||
// Neither Content-Length nor Connection
|
||||
socket.end('HTTP/1.1 200 ok\r\n\r\nHello');
|
||||
}).listen(0, common.mustCall(function() {
|
||||
http.get({ port: this.address().port }, common.mustCall(function(res) {
|
||||
let body = '';
|
||||
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
body += chunk;
|
||||
});
|
||||
res.on('end', common.mustCall(function() {
|
||||
assert.strictEqual(body, 'Hello');
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
// Flags: --expose-gc
|
||||
|
||||
// Check that creating a server without listening does not leak resources.
|
||||
|
||||
require('../common');
|
||||
const { onGC } = require('../common/gc');
|
||||
const Countdown = require('../common/countdown');
|
||||
|
||||
const http = require('http');
|
||||
const max = 100;
|
||||
|
||||
// Note that Countdown internally calls common.mustCall, that's why it's not done here.
|
||||
const countdown = new Countdown(max, () => {});
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
const server = http.createServer((req, res) => {});
|
||||
onGC(server, { ongc: countdown.dec.bind(countdown) });
|
||||
}
|
||||
|
||||
setImmediate(() => {
|
||||
global.gc();
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
// This tests that the http2 server sends data early when it accumulates
|
||||
// enough from ongoing requests to avoid DoS as mitigation for
|
||||
// CVE-2019-9517 and CVE-2019-9511.
|
||||
// Added by https://github.com/nodejs/node/commit/8a4a193
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
|
||||
const content = fixtures.readSync('person-large.jpg');
|
||||
|
||||
const server = http2.createServer({
|
||||
maxSessionMemory: 1000
|
||||
});
|
||||
let streamCount = 0;
|
||||
server.on('stream', (stream, headers) => {
|
||||
stream.respond({
|
||||
'content-type': 'image/jpeg',
|
||||
':status': 200
|
||||
});
|
||||
stream.end(content);
|
||||
console.log('server sends content', ++streamCount);
|
||||
});
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = http2.connect(`http://localhost:${server.address().port}/`);
|
||||
|
||||
let endCount = 0;
|
||||
let finished = 0;
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const req = client.request({ ':path': '/' }).end();
|
||||
const chunks = [];
|
||||
req.on('data', (chunk) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
req.on('end', common.mustCall(() => {
|
||||
console.log('client receives content', ++endCount);
|
||||
assert.deepStrictEqual(Buffer.concat(chunks), content);
|
||||
|
||||
if (++finished === 100) {
|
||||
client.close();
|
||||
server.close();
|
||||
}
|
||||
}));
|
||||
req.on('error', (e) => {
|
||||
console.log('client error', e);
|
||||
});
|
||||
}
|
||||
}));
|
||||
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const Countdown = require('../common/countdown');
|
||||
const http2 = require('http2');
|
||||
|
||||
const server = http2.createServer();
|
||||
|
||||
let session;
|
||||
|
||||
const countdown = new Countdown(2, () => {
|
||||
server.close(common.mustSucceed());
|
||||
session.close();
|
||||
});
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = http2.connect(`http://localhost:${server.address().port}`);
|
||||
client.on('connect', common.mustCall(() => countdown.dec()));
|
||||
}));
|
||||
|
||||
server.on('session', common.mustCall((s) => {
|
||||
session = s;
|
||||
countdown.dec();
|
||||
}));
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
// Flags: --expose-gc
|
||||
|
||||
// Check that creating a server without listening does not leak resources.
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto) {
|
||||
common.skip('missing crypto');
|
||||
}
|
||||
|
||||
const { onGC } = require('../common/gc');
|
||||
const Countdown = require('../common/countdown');
|
||||
|
||||
const https = require('https');
|
||||
const max = 100;
|
||||
|
||||
// Note that Countdown internally calls common.mustCall, that's why it's not done here.
|
||||
const countdown = new Countdown(max, () => {});
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
const server = https.createServer((req, res) => {});
|
||||
onGC(server, { ongc: countdown.dec.bind(countdown) });
|
||||
}
|
||||
|
||||
setImmediate(() => {
|
||||
global.gc();
|
||||
});
|
||||
45
test/js/node/test/parallel/test-net-server-close.js
Normal file
45
test/js/node/test/parallel/test-net-server-close.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
const sockets = [];
|
||||
|
||||
const server = net.createServer(function(c) {
|
||||
c.on('close', common.mustCall());
|
||||
|
||||
sockets.push(c);
|
||||
|
||||
if (sockets.length === 2) {
|
||||
assert.strictEqual(server.close(), server);
|
||||
sockets.forEach((c) => c.destroy());
|
||||
}
|
||||
});
|
||||
|
||||
server.on('close', common.mustCall());
|
||||
|
||||
assert.strictEqual(server, server.listen(0, () => {
|
||||
net.createConnection(server.address().port);
|
||||
net.createConnection(server.address().port);
|
||||
}));
|
||||
33
test/js/node/test/parallel/test-net-sync-cork.js
Normal file
33
test/js/node/test/parallel/test-net-sync-cork.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
const server = net.createServer(handle);
|
||||
|
||||
const N = 100;
|
||||
const buf = Buffer.alloc(2, 'a');
|
||||
|
||||
server.listen(0, function() {
|
||||
const conn = net.connect(this.address().port);
|
||||
|
||||
conn.on('connect', () => {
|
||||
let res = true;
|
||||
let i = 0;
|
||||
for (; i < N && res; i++) {
|
||||
conn.cork();
|
||||
conn.write(buf);
|
||||
res = conn.write(buf);
|
||||
conn.uncork();
|
||||
}
|
||||
assert.strictEqual(i, N);
|
||||
conn.end();
|
||||
});
|
||||
});
|
||||
|
||||
function handle(socket) {
|
||||
socket.resume();
|
||||
socket.on('error', common.mustNotCall())
|
||||
.on('close', common.mustCall(() => server.close()));
|
||||
}
|
||||
23
test/js/node/test/parallel/test-primitive-timer-leak.js
Normal file
23
test/js/node/test/parallel/test-primitive-timer-leak.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
// Flags: --expose-gc
|
||||
require('../common');
|
||||
const { onGC } = require('../common/gc');
|
||||
|
||||
// See https://github.com/nodejs/node/issues/53335
|
||||
const poller = setInterval(() => {
|
||||
global.gc();
|
||||
}, 100);
|
||||
|
||||
let count = 0;
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const timer = setTimeout(() => {}, 0);
|
||||
onGC(timer, {
|
||||
ongc: () => {
|
||||
if (++count === 10) {
|
||||
clearInterval(poller);
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log(+timer);
|
||||
}
|
||||
38
test/js/node/test/parallel/test-stdio-pipe-access.js
Normal file
38
test/js/node/test/parallel/test-stdio-pipe-access.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.isMainThread)
|
||||
common.skip("Workers don't have process-like stdio");
|
||||
|
||||
// Test if Node handles accessing process.stdin if it is a redirected
|
||||
// pipe without deadlocking
|
||||
const { spawn, spawnSync } = require('child_process');
|
||||
|
||||
const numTries = 5;
|
||||
const who = process.argv.length <= 2 ? 'runner' : process.argv[2];
|
||||
|
||||
switch (who) {
|
||||
case 'runner':
|
||||
for (let num = 0; num < numTries; ++num) {
|
||||
spawnSync(process.argv0,
|
||||
[process.argv[1], 'parent'],
|
||||
{ 'stdio': 'inherit' });
|
||||
}
|
||||
break;
|
||||
case 'parent': {
|
||||
const middle = spawn(process.argv0,
|
||||
[process.argv[1], 'middle'],
|
||||
{ 'stdio': 'pipe' });
|
||||
middle.stdout.on('data', () => {});
|
||||
break;
|
||||
}
|
||||
case 'middle':
|
||||
spawn(process.argv0,
|
||||
[process.argv[1], 'bottom'],
|
||||
{ 'stdio': [ process.stdin,
|
||||
process.stdout,
|
||||
process.stderr ] });
|
||||
break;
|
||||
case 'bottom':
|
||||
process.stdin; // eslint-disable-line no-unused-expressions
|
||||
break;
|
||||
}
|
||||
56
test/js/node/test/parallel/test-timers-immediate-queue.js
Normal file
56
test/js/node/test/parallel/test-timers-immediate-queue.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// setImmediate should run clear its queued cbs once per event loop turn
|
||||
// but immediates queued while processing the current queue should happen
|
||||
// on the next turn of the event loop.
|
||||
|
||||
// hit should be the exact same size of QUEUE, if we're letting things
|
||||
// recursively add to the immediate QUEUE hit will be > QUEUE
|
||||
|
||||
let ticked = false;
|
||||
|
||||
let hit = 0;
|
||||
const QUEUE = 10;
|
||||
|
||||
function run() {
|
||||
if (hit === 0) {
|
||||
setTimeout(() => { ticked = true; }, 1);
|
||||
const now = Date.now();
|
||||
while (Date.now() - now < 2);
|
||||
}
|
||||
|
||||
if (ticked) return;
|
||||
|
||||
hit += 1;
|
||||
setImmediate(run);
|
||||
}
|
||||
|
||||
for (let i = 0; i < QUEUE; i++)
|
||||
setImmediate(run);
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.strictEqual(hit, QUEUE);
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
if (!common.hasIPv6)
|
||||
common.skip('no IPv6 support');
|
||||
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
const dns = require('dns');
|
||||
|
||||
function runTest() {
|
||||
tls.createServer({
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
}).on('connection', common.mustCall(function() {
|
||||
this.close();
|
||||
})).listen(0, '::1', common.mustCall(function() {
|
||||
const options = {
|
||||
host: 'localhost',
|
||||
port: this.address().port,
|
||||
family: 6,
|
||||
rejectUnauthorized: false,
|
||||
};
|
||||
// Will fail with ECONNREFUSED if the address family is not honored.
|
||||
tls.connect(options).once('secureConnect', common.mustCall(function() {
|
||||
assert.strictEqual(this.remoteAddress, '::1');
|
||||
this.destroy();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
dns.lookup('localhost', {
|
||||
family: 6, all: true
|
||||
}, common.mustCall((err, addresses) => {
|
||||
if (err) {
|
||||
if (err.code === 'ENOTFOUND' || err.code === 'EAI_AGAIN')
|
||||
common.skip('localhost does not resolve to ::1');
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (addresses.some((val) => val.address === '::1'))
|
||||
runTest();
|
||||
else
|
||||
common.skip('localhost does not resolve to ::1');
|
||||
}));
|
||||
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
|
||||
const server = net.createServer((c) => {
|
||||
c.end();
|
||||
}).listen(common.mustCall(() => {
|
||||
const port = server.address().port;
|
||||
|
||||
const socket = new net.Socket();
|
||||
|
||||
let errored = false;
|
||||
tls.connect({ socket })
|
||||
.once('error', common.mustCall((e) => {
|
||||
assert.strictEqual(e.code, 'ECONNRESET');
|
||||
assert.strictEqual(e.path, undefined);
|
||||
assert.strictEqual(e.host, undefined);
|
||||
assert.strictEqual(e.port, undefined);
|
||||
assert.strictEqual(e.localAddress, undefined);
|
||||
errored = true;
|
||||
server.close();
|
||||
}))
|
||||
.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(errored, true);
|
||||
}));
|
||||
|
||||
socket.connect(port);
|
||||
}));
|
||||
20
test/js/node/test/parallel/test-ttywrap-stack.js
Normal file
20
test/js/node/test/parallel/test-ttywrap-stack.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
// This test ensures that console.log
|
||||
// will not crash the process if there
|
||||
// is not enough space on the V8 stack
|
||||
|
||||
const done = common.mustCall();
|
||||
|
||||
async function test() {
|
||||
await test();
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
await test();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
})().then(done, done);
|
||||
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const { MessageChannel, Worker } = require('worker_threads');
|
||||
|
||||
// Test that SharedArrayBuffer instances created from WASM are transferable
|
||||
// through MessageChannels (without crashing).
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
const wasmSource = fixtures.readSync('shared-memory.wasm');
|
||||
const wasmModule = new WebAssembly.Module(wasmSource);
|
||||
const instance = new WebAssembly.Instance(wasmModule);
|
||||
|
||||
const { buffer } = instance.exports.memory;
|
||||
assert(buffer instanceof SharedArrayBuffer);
|
||||
|
||||
{
|
||||
const { port1, port2 } = new MessageChannel();
|
||||
port1.postMessage(buffer);
|
||||
port2.once('message', common.mustCall((buffer2) => {
|
||||
// Make sure serialized + deserialized buffer refer to the same memory.
|
||||
const expected = 'Hello, world!';
|
||||
const bytes = Buffer.from(buffer).write(expected);
|
||||
const deserialized = Buffer.from(buffer2).toString('utf8', 0, bytes);
|
||||
assert.deepStrictEqual(deserialized, expected);
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure we can free WASM memory originating from a thread that already
|
||||
// stopped when we exit.
|
||||
const worker = new Worker(`
|
||||
const { parentPort } = require('worker_threads');
|
||||
|
||||
// Compile the same WASM module from its source bytes.
|
||||
const wasmSource = new Uint8Array([${wasmSource.join(',')}]);
|
||||
const wasmModule = new WebAssembly.Module(wasmSource);
|
||||
const instance = new WebAssembly.Instance(wasmModule);
|
||||
parentPort.postMessage(instance.exports.memory);
|
||||
|
||||
// Do the same thing, except we receive the WASM module via transfer.
|
||||
parentPort.once('message', ({ wasmModule }) => {
|
||||
const instance = new WebAssembly.Instance(wasmModule);
|
||||
parentPort.postMessage(instance.exports.memory);
|
||||
});
|
||||
`, { eval: true });
|
||||
worker.on('message', common.mustCall(({ buffer }) => {
|
||||
assert(buffer instanceof SharedArrayBuffer);
|
||||
worker.buf = buffer; // Basically just keep the reference to buffer alive.
|
||||
}, 2));
|
||||
worker.once('exit', common.mustCall());
|
||||
worker.postMessage({ wasmModule });
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const { Worker } = require('worker_threads');
|
||||
|
||||
// Regression for https://github.com/nodejs/node/issues/43182.
|
||||
const w = new Worker(new URL('data:text/javascript,process.exit(1);await new Promise(()=>{ process.exit(2); })'));
|
||||
w.on('exit', common.mustCall((code) => {
|
||||
assert.strictEqual(code, 1);
|
||||
}));
|
||||
Reference in New Issue
Block a user