mirror of
https://github.com/nodejs/node.git
synced 2025-05-02 18:44:40 +00:00

Adds a new `../common/fixtures' module to begin normalizing `test/fixtures` use. Our test code is a bit inconsistent with regards to use of the fixtures directory. Some code uses `path.join()`, some code uses string concats, some other code uses template strings, etc. In mnay cases, significant duplication of code is seen when accessing fixture files, etc. This updates many (but by no means all) of the tests in the test suite to use the new consistent API. There are still many more to update, which would make an excelent Code-n-Learn exercise. PR-URL: https://github.com/nodejs/node/pull/14332 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Michaël Zasso <targos@protonmail.com>
262 lines
6.7 KiB
JavaScript
262 lines
6.7 KiB
JavaScript
'use strict';
|
|
const common = require('../common');
|
|
|
|
// This test checks that the semantics of `util.callbackify` are as described in
|
|
// the API docs
|
|
|
|
const assert = require('assert');
|
|
const { callbackify } = require('util');
|
|
const { execFile } = require('child_process');
|
|
const fixtures = require('../common/fixtures');
|
|
|
|
const values = [
|
|
'hello world',
|
|
null,
|
|
undefined,
|
|
false,
|
|
0,
|
|
{},
|
|
{ key: 'value' },
|
|
Symbol('I am a symbol'),
|
|
function ok() {},
|
|
['array', 'with', 4, 'values'],
|
|
new Error('boo')
|
|
];
|
|
|
|
{
|
|
// Test that the resolution value is passed as second argument to callback
|
|
for (const value of values) {
|
|
// Test and `async function`
|
|
async function asyncFn() {
|
|
return await Promise.resolve(value);
|
|
}
|
|
|
|
const cbAsyncFn = callbackify(asyncFn);
|
|
cbAsyncFn(common.mustCall((err, ret) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
}));
|
|
|
|
// Test Promise factory
|
|
function promiseFn() {
|
|
return Promise.resolve(value);
|
|
}
|
|
|
|
const cbPromiseFn = callbackify(promiseFn);
|
|
cbPromiseFn(common.mustCall((err, ret) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
}));
|
|
|
|
// Test Thenable
|
|
function thenableFn() {
|
|
return {
|
|
then(onRes, onRej) {
|
|
onRes(value);
|
|
}
|
|
};
|
|
}
|
|
|
|
const cbThenableFn = callbackify(thenableFn);
|
|
cbThenableFn(common.mustCall((err, ret) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
}));
|
|
}
|
|
}
|
|
|
|
{
|
|
// Test that rejection reason is passed as first argument to callback
|
|
for (const value of values) {
|
|
// Test an `async function`
|
|
async function asyncFn() {
|
|
return await Promise.reject(value);
|
|
}
|
|
|
|
const cbAsyncFn = callbackify(asyncFn);
|
|
cbAsyncFn(common.mustCall((err, ret) => {
|
|
assert.strictEqual(ret, undefined);
|
|
if (err instanceof Error) {
|
|
if ('reason' in err) {
|
|
assert(!value);
|
|
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
|
|
assert.strictEqual(err.reason, value);
|
|
} else {
|
|
assert.strictEqual(String(value).endsWith(err.message), true);
|
|
}
|
|
} else {
|
|
assert.strictEqual(err, value);
|
|
}
|
|
}));
|
|
|
|
// test a Promise factory
|
|
function promiseFn() {
|
|
return Promise.reject(value);
|
|
}
|
|
|
|
const cbPromiseFn = callbackify(promiseFn);
|
|
cbPromiseFn(common.mustCall((err, ret) => {
|
|
assert.strictEqual(ret, undefined);
|
|
if (err instanceof Error) {
|
|
if ('reason' in err) {
|
|
assert(!value);
|
|
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
|
|
assert.strictEqual(err.reason, value);
|
|
} else {
|
|
assert.strictEqual(String(value).endsWith(err.message), true);
|
|
}
|
|
} else {
|
|
assert.strictEqual(err, value);
|
|
}
|
|
}));
|
|
|
|
// Test Thenable
|
|
function thenableFn() {
|
|
return {
|
|
then(onRes, onRej) {
|
|
onRej(value);
|
|
}
|
|
};
|
|
}
|
|
|
|
const cbThenableFn = callbackify(thenableFn);
|
|
cbThenableFn(common.mustCall((err, ret) => {
|
|
assert.strictEqual(ret, undefined);
|
|
if (err instanceof Error) {
|
|
if ('reason' in err) {
|
|
assert(!value);
|
|
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
|
|
assert.strictEqual(err.reason, value);
|
|
} else {
|
|
assert.strictEqual(String(value).endsWith(err.message), true);
|
|
}
|
|
} else {
|
|
assert.strictEqual(err, value);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
{
|
|
// Test that arguments passed to callbackified function are passed to original
|
|
for (const value of values) {
|
|
async function asyncFn(arg) {
|
|
assert.strictEqual(arg, value);
|
|
return await Promise.resolve(arg);
|
|
}
|
|
|
|
const cbAsyncFn = callbackify(asyncFn);
|
|
cbAsyncFn(value, common.mustCall((err, ret) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
}));
|
|
|
|
function promiseFn(arg) {
|
|
assert.strictEqual(arg, value);
|
|
return Promise.resolve(arg);
|
|
}
|
|
|
|
const cbPromiseFn = callbackify(promiseFn);
|
|
cbPromiseFn(value, common.mustCall((err, ret) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
}));
|
|
}
|
|
}
|
|
|
|
{
|
|
// Test that `this` binding is the same for callbackified and original
|
|
for (const value of values) {
|
|
const iAmThis = {
|
|
fn(arg) {
|
|
assert.strictEqual(this, iAmThis);
|
|
return Promise.resolve(arg);
|
|
},
|
|
};
|
|
iAmThis.cbFn = callbackify(iAmThis.fn);
|
|
iAmThis.cbFn(value, common.mustCall(function(err, ret) {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
assert.strictEqual(this, iAmThis);
|
|
}));
|
|
|
|
const iAmThat = {
|
|
async fn(arg) {
|
|
assert.strictEqual(this, iAmThat);
|
|
return await Promise.resolve(arg);
|
|
},
|
|
};
|
|
iAmThat.cbFn = callbackify(iAmThat.fn);
|
|
iAmThat.cbFn(value, common.mustCall(function(err, ret) {
|
|
assert.ifError(err);
|
|
assert.strictEqual(ret, value);
|
|
assert.strictEqual(this, iAmThat);
|
|
}));
|
|
}
|
|
}
|
|
|
|
{
|
|
// Test that callback that throws emits an `uncaughtException` event
|
|
const fixture = fixtures.path('uncaught-exceptions', 'callbackify1.js');
|
|
execFile(
|
|
process.execPath,
|
|
[fixture],
|
|
common.mustCall((err, stdout, stderr) => {
|
|
assert.strictEqual(err.code, 1);
|
|
assert.strictEqual(Object.getPrototypeOf(err).name, 'Error');
|
|
assert.strictEqual(stdout, '');
|
|
const errLines = stderr.trim().split(/[\r\n]+/);
|
|
const errLine = errLines.find((l) => /^Error/.exec(l));
|
|
assert.strictEqual(errLine, `Error: ${fixture}`);
|
|
})
|
|
);
|
|
}
|
|
|
|
{
|
|
// Test that handled `uncaughtException` works and passes rejection reason
|
|
const fixture = fixtures.path('uncaught-exceptions', 'callbackify2.js');
|
|
execFile(
|
|
process.execPath,
|
|
[fixture],
|
|
common.mustCall((err, stdout, stderr) => {
|
|
assert.ifError(err);
|
|
assert.strictEqual(stdout.trim(), fixture);
|
|
assert.strictEqual(stderr, '');
|
|
})
|
|
);
|
|
}
|
|
|
|
{
|
|
// Verify that non-function inputs throw.
|
|
['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
|
|
assert.throws(() => {
|
|
callbackify(value);
|
|
}, common.expectsError({
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
type: TypeError,
|
|
message: 'The "original" argument must be of type function'
|
|
}));
|
|
});
|
|
}
|
|
|
|
{
|
|
async function asyncFn() {
|
|
return await Promise.resolve(42);
|
|
}
|
|
|
|
const cb = callbackify(asyncFn);
|
|
const args = [];
|
|
|
|
// Verify that the last argument to the callbackified function is a function.
|
|
['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
|
|
args.push(value);
|
|
assert.throws(() => {
|
|
cb(...args);
|
|
}, common.expectsError({
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
type: TypeError,
|
|
message: 'The last argument must be of type function'
|
|
}));
|
|
});
|
|
}
|