Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: migrate tests to use node:test module for better test structure for worker test #56029

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
49 changes: 28 additions & 21 deletions test/parallel/test-worker-heapdump-failure.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const { Worker } = require('worker_threads');
const { once } = require('events');

(async function() {
const w = new Worker('', { eval: true });
const { test } = require('node:test');
const { Worker } = require('node:worker_threads');
const { once } = require('node:events');
const assert = require('node:assert');

// Test for ERR_WORKER_NOT_RUNNING when calling getHeapSnapshot on a worker that's not running
test('Worker heap snapshot tests', async (t) => {
await t.test('should throw ERR_WORKER_NOT_RUNNING when worker is not running', async () => {
const w = new Worker('', { eval: true });

await once(w, 'exit');
await assert.rejects(() => w.getHeapSnapshot(), {
name: 'Error',
code: 'ERR_WORKER_NOT_RUNNING'
await once(w, 'exit');
await assert.rejects(() => w.getHeapSnapshot(), {
name: 'Error',
code: 'ERR_WORKER_NOT_RUNNING',
});
});
})().then(common.mustCall());

(async function() {
const worker = new Worker('setInterval(() => {}, 1000);', { eval: true });
await once(worker, 'online');
await t.test('should throw ERR_INVALID_ARG_TYPE for invalid options argument in getHeapSnapshot', async () => {
const worker = new Worker('setInterval(() => {}, 1000);', { eval: true });
await once(worker, 'online');

[1, true, [], null, Infinity, NaN].forEach((i) => {
assert.throws(() => worker.getHeapSnapshot(i), {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "options" argument must be of type object.' +
common.invalidArgTypeHelper(i)
// Test various invalid types for the `options` argument
[1, true, [], null, Infinity, NaN].forEach((i) => {
assert.throws(() => worker.getHeapSnapshot(i), {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: `The "options" argument must be of type object.${common.invalidArgTypeHelper(i)}`,
});
});

await worker.terminate();
});
await worker.terminate();
})().then(common.mustCall());
});
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const fs = require('fs').promises;
const { MessageChannel } = require('worker_threads');
const { once } = require('events');

// Test that overriding the internal kTransfer method of a JSTransferable does
// not enable loading arbitrary code from internal Node.js core modules.

(async function() {
const fh = await fs.open(__filename);
assert.strictEqual(fh.constructor.name, 'FileHandle');

const kTransfer = Object.getOwnPropertySymbols(Object.getPrototypeOf(fh))
.filter((symbol) => symbol.description === 'messaging_transfer_symbol')[0];
assert.strictEqual(typeof kTransfer, 'symbol');
fh[kTransfer] = () => {
return {
data: '✨',
deserializeInfo: 'net:Socket'
};
};

const { port1, port2 } = new MessageChannel();
port1.postMessage(fh, [ fh ]);
port2.on('message', common.mustNotCall());

const [ exception ] = await once(port2, 'messageerror');

assert.strictEqual(exception.message, 'Unknown deserialize spec net:Socket');
port2.close();
})().then(common.mustCall());
const fs = require('node:fs').promises;
const assert = require('node:assert');

const { test } = require('node:test');
const { MessageChannel } = require('node:worker_threads');
const { once } = require('node:events');

// Test: Overriding kTransfer method should not enable loading arbitrary code from Node.js core modules.
test('Security test for overriding kTransfer method', async (t) => {
await t.test(
'should throw an error for invalid deserializeInfo from core module',
async () => {
const fh = await fs.open(__filename);
assert.strictEqual(fh.constructor.name, 'FileHandle');

const kTransfer = Object.getOwnPropertySymbols(
Object.getPrototypeOf(fh),
).find((symbol) => symbol.description === 'messaging_transfer_symbol');
assert.strictEqual(typeof kTransfer, 'symbol');

// Override the kTransfer method
fh[kTransfer] = () => ({
data: '✨',
deserializeInfo: 'net:Socket', // Attempt to load an internal module
});

const { port1, port2 } = new MessageChannel();
port1.postMessage(fh, [fh]);

// Verify that no valid message is processed
port2.on('message', common.mustNotCall());

// Capture the 'messageerror' event and validate the error
const [exception] = await once(port2, 'messageerror');
const errorMessage =
'Unexpected error message for invalid deserializeInfo';

assert.strictEqual(
exception.message,
'Unknown deserialize spec net:Socket',
errorMessage,
);

port2.close();
},
);
});
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const fs = require('fs').promises;
const { MessageChannel } = require('worker_threads');
const { once } = require('events');

// Test that overriding the internal kTransfer method of a JSTransferable does
// not enable loading arbitrary code from the disk.

module.exports = {
NotARealClass: common.mustNotCall()
};

(async function() {
const fh = await fs.open(__filename);
assert.strictEqual(fh.constructor.name, 'FileHandle');

const kTransfer = Object.getOwnPropertySymbols(Object.getPrototypeOf(fh))
.filter((symbol) => symbol.description === 'messaging_transfer_symbol')[0];
assert.strictEqual(typeof kTransfer, 'symbol');
fh[kTransfer] = () => {
return {
const assert = require('node:assert');
const fs = require('node:fs').promises;

const { test } = require('node:test');
const { MessageChannel } = require('node:worker_threads');
const { once } = require('node:events');

// Test: Overriding the internal kTransfer method should not enable arbitrary code loading.
test('Overriding kTransfer method security test', async (t) => {
await t.test('should throw an error for invalid deserializeInfo', async () => {
const fh = await fs.open(__filename);
assert.strictEqual(fh.constructor.name, 'FileHandle');

const kTransfer = Object.getOwnPropertySymbols(Object.getPrototypeOf(fh))
.find((symbol) => symbol.description === 'messaging_transfer_symbol');
assert.strictEqual(typeof kTransfer, 'symbol');

// Override the kTransfer method
fh[kTransfer] = () => ({
data: '✨',
deserializeInfo: `${__filename}:NotARealClass`
};
};
deserializeInfo: `${__filename}:NotARealClass`,
});

const { port1, port2 } = new MessageChannel();
port1.postMessage(fh, [fh]);

const { port1, port2 } = new MessageChannel();
port1.postMessage(fh, [ fh ]);
port2.on('message', common.mustNotCall());
// Verify that no valid message is processed
port2.on('message', common.mustNotCall());

const [ exception ] = await once(port2, 'messageerror');
// Capture the 'messageerror' event and validate the error
const [exception] = await once(port2, 'messageerror');
assert.match(exception.message, /Missing internal module/, 'Unexpected error message');

assert.match(exception.message, /Missing internal module/);
port2.close();
})().then(common.mustCall());
port2.close();
});
});
Loading
Loading