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: move hijackstdio out of require('common') #22462

Closed
wants to merge 1 commit into from
Closed
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
78 changes: 48 additions & 30 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,24 +173,6 @@ Indicates whether `IPv6` is supported on this platform.

Indicates if there are multiple localhosts available.

### hijackStderr(listener)
* `listener` [<Function>]: a listener with a single parameter
called `data`.

Eavesdrop to `process.stderr.write` calls. Once `process.stderr.write` is
called, `listener` will also be called and the `data` of `write` function will
be passed to `listener`. What's more, `process.stderr.writeTimes` is a count of
the number of calls.

### hijackStdout(listener)
* `listener` [<Function>]: a listener with a single parameter
called `data`.

Eavesdrop to `process.stdout.write` calls. Once `process.stdout.write` is
called, `listener` will also be called and the `data` of `write` function will
be passed to `listener`. What's more, `process.stdout.writeTimes` is a count of
the number of calls.

### inFreeBSDJail
* [<boolean>]

Expand Down Expand Up @@ -355,16 +337,6 @@ A port number for tests to use if one is needed.

Logs '1..0 # Skipped: ' + `msg`

### restoreStderr()

Restore the original `process.stderr.write`. Used to restore `stderr` to its
original state after calling [`common.hijackStdErr()`][].

### restoreStdout()

Restore the original `process.stdout.write`. Used to restore `stdout` to its
original state after calling [`common.hijackStdOut()`][].

### rootDir
* [<string>]

Expand Down Expand Up @@ -596,6 +568,52 @@ validateSnapshotNodes('TLSWRAP', [
]);
```

## hijackstdio Module

The `hijackstdio` module provides utility functions for temporarily redirecting
`stdout` and `stderr` output.

<!-- eslint-disable no-undef, node-core/required-modules -->
```js
const { hijackStdout, restoreStdout } = require('../common/hijackstdio');

hijackStdout((data) => {
/* Do something with data */
restoreStdout();
});

console.log('this is sent to the hijacked listener');
```

### hijackStderr(listener)
* `listener` [&lt;Function>]: a listener with a single parameter
called `data`.

Eavesdrop to `process.stderr.write()` calls. Once `process.stderr.write()` is
called, `listener` will also be called and the `data` of `write` function will
be passed to `listener`. What's more, `process.stderr.writeTimes` is a count of
the number of calls.

### hijackStdout(listener)
* `listener` [&lt;Function>]: a listener with a single parameter
called `data`.

Eavesdrop to `process.stdout.write()` calls. Once `process.stdout.write()` is
called, `listener` will also be called and the `data` of `write` function will
be passed to `listener`. What's more, `process.stdout.writeTimes` is a count of
the number of calls.

### restoreStderr()

Restore the original `process.stderr.write()`. Used to restore `stderr` to its
original state after calling [`hijackstdio.hijackStdErr()`][].

### restoreStdout()

Restore the original `process.stdout.write()`. Used to restore `stdout` to its
original state after calling [`hijackstdio.hijackStdOut()`][].


## HTTP/2 Module

The http2.js module provides a handful of utilities for creating mock HTTP/2
Expand Down Expand Up @@ -773,6 +791,6 @@ implementation with tests from
[&lt;boolean>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
[&lt;number>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
[&lt;string>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type
[`common.hijackStdErr()`]: #hijackstderrlistener
[`common.hijackStdOut()`]: #hijackstdoutlistener
[`hijackstdio.hijackStdErr()`]: #hijackstderrlistener
[`hijackstdio.hijackStdOut()`]: #hijackstdoutlistener
[internationalization]: https://github.com/nodejs/node/wiki/Intl
33 changes: 33 additions & 0 deletions test/common/hijackstdio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable node-core/required-modules */
'use strict';

// Hijack stdout and stderr
const stdWrite = {};
function hijackStdWritable(name, listener) {
const stream = process[name];
const _write = stdWrite[name] = stream.write;

stream.writeTimes = 0;
stream.write = function(data, callback) {
try {
listener(data);
} catch (e) {
process.nextTick(() => { throw e; });
}

_write.call(stream, data, callback);
stream.writeTimes++;
};
}

function restoreWritable(name) {
process[name].write = stdWrite[name];
delete process[name].writeTimes;
}

module.exports = {
hijackStdout: hijackStdWritable.bind(null, 'stdout'),
hijackStderr: hijackStdWritable.bind(null, 'stderr'),
restoreStdout: restoreWritable.bind(null, 'stdout'),
restoreStderr: restoreWritable.bind(null, 'stderr')
};
28 changes: 0 additions & 28 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,30 +786,6 @@ exports.getTTYfd = function getTTYfd() {
return ttyFd;
};

// Hijack stdout and stderr
const stdWrite = {};
function hijackStdWritable(name, listener) {
const stream = process[name];
const _write = stdWrite[name] = stream.write;

stream.writeTimes = 0;
stream.write = function(data, callback) {
try {
listener(data);
} catch (e) {
process.nextTick(() => { throw e; });
}

_write.call(stream, data, callback);
stream.writeTimes++;
};
}

function restoreWritable(name) {
process[name].write = stdWrite[name];
delete process[name].writeTimes;
}

exports.runWithInvalidFD = function(func) {
let fd = 1 << 30;
// Get first known bad file descriptor. 1 << 30 is usually unlikely to
Expand All @@ -823,10 +799,6 @@ exports.runWithInvalidFD = function(func) {
exports.printSkipMessage('Could not generate an invalid fd');
};

exports.hijackStdout = hijackStdWritable.bind(null, 'stdout');
exports.hijackStderr = hijackStdWritable.bind(null, 'stderr');
exports.restoreStdout = restoreWritable.bind(null, 'stdout');
exports.restoreStderr = restoreWritable.bind(null, 'stderr');
exports.isCPPSymbolsNotMapped = exports.isWindows ||
exports.isSunOS ||
exports.isAIX ||
Expand Down
8 changes: 0 additions & 8 deletions test/common/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ const {
disableCrashOnUnhandledRejection,
getTTYfd,
runWithInvalidFD,
hijackStdout,
hijackStderr,
restoreStdout,
restoreStderr,
isCPPSymbolsNotMapped
} = common;

Expand Down Expand Up @@ -109,9 +105,5 @@ export {
disableCrashOnUnhandledRejection,
getTTYfd,
runWithInvalidFD,
hijackStdout,
hijackStderr,
restoreStdout,
restoreStderr,
isCPPSymbolsNotMapped
};
9 changes: 5 additions & 4 deletions test/parallel/test-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

'use strict';
const common = require('../common');
const hijackstdio = require('../common/hijackstdio');
const fixtures = require('../common/fixtures');
const assert = require('assert');
const { execFile } = require('child_process');
Expand Down Expand Up @@ -95,7 +96,7 @@ const HIJACK_TEST_ARRAY = [ 'foo\n', 'bar\n', 'baz\n' ];
const stream = process[`std${txt}`];
const originalWrite = stream.write;

common[`hijackStd${txt}`](common.mustCall(function(data) {
hijackstdio[`hijackStd${txt}`](common.mustCall(function(data) {
assert.strictEqual(data, HIJACK_TEST_ARRAY[stream.writeTimes]);
}, HIJACK_TEST_ARRAY.length));
assert.notStrictEqual(originalWrite, stream.write);
Expand All @@ -105,22 +106,22 @@ const HIJACK_TEST_ARRAY = [ 'foo\n', 'bar\n', 'baz\n' ];
});

assert.strictEqual(HIJACK_TEST_ARRAY.length, stream.writeTimes);
common[`restoreStd${txt}`]();
hijackstdio[`restoreStd${txt}`]();
assert.strictEqual(originalWrite, stream.write);
});

// hijackStderr and hijackStdout again
// for console
[[ 'err', 'error' ], [ 'out', 'log' ]].forEach(([ type, method ]) => {
common[`hijackStd${type}`](common.mustCall(function(data) {
hijackstdio[`hijackStd${type}`](common.mustCall(function(data) {
assert.strictEqual(data, 'test\n');

// throw an error
throw new Error(`console ${type} error`);
}));

console[method]('test');
common[`restoreStd${type}`]();
hijackstdio[`restoreStd${type}`]();
});

let uncaughtTimes = 0;
Expand Down
16 changes: 11 additions & 5 deletions test/parallel/test-console-group.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
'use strict';
const common = require('../common');
require('../common');
const {
hijackStdout,
hijackStderr,
restoreStdout,
restoreStderr
} = require('../common/hijackstdio');

const assert = require('assert');
const Console = require('console').Console;
Expand All @@ -8,21 +14,21 @@ let c, stdout, stderr;

function setup() {
stdout = '';
common.hijackStdout(function(data) {
hijackStdout(function(data) {
stdout += data;
});

stderr = '';
common.hijackStderr(function(data) {
hijackStderr(function(data) {
stderr += data;
});

c = new Console(process.stdout, process.stderr);
}

function teardown() {
common.restoreStdout();
common.restoreStderr();
restoreStdout();
restoreStderr();
}

// Basic group() functionality
Expand Down
19 changes: 13 additions & 6 deletions test/parallel/test-console.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ const common = require('../common');
const assert = require('assert');
const util = require('util');

const {
hijackStdout,
hijackStderr,
restoreStdout,
restoreStderr
} = require('../common/hijackstdio');

assert.ok(process.stdout.writable);
assert.ok(process.stderr.writable);
// Support legacy API
Expand Down Expand Up @@ -63,11 +70,11 @@ const custom_inspect = { foo: 'bar', [util.inspect.custom]: () => 'inspect' };
const strings = [];
const errStrings = [];
process.stdout.isTTY = false;
common.hijackStdout(function(data) {
hijackStdout(function(data) {
strings.push(data);
});
process.stderr.isTTY = false;
common.hijackStderr(function(data) {
hijackStderr(function(data) {
errStrings.push(data);
});

Expand Down Expand Up @@ -175,8 +182,8 @@ console.assert(true, 'this should not throw');

assert.strictEqual(strings.length, process.stdout.writeTimes);
assert.strictEqual(errStrings.length, process.stderr.writeTimes);
common.restoreStdout();
common.restoreStderr();
restoreStdout();
restoreStderr();

// verify that console.timeEnd() doesn't leave dead links
const timesMapSize = console._times.size;
Expand Down Expand Up @@ -246,8 +253,8 @@ assert.strictEqual(errStrings.shift().split('\n').shift(),

// hijack stderr to catch `process.emitWarning` which is using
// `process.nextTick`
common.hijackStderr(common.mustCall(function(data) {
common.restoreStderr();
hijackStderr(common.mustCall(function(data) {
restoreStderr();

// stderr.write will catch sync error, so use `process.nextTick` here
process.nextTick(function() {
Expand Down
13 changes: 8 additions & 5 deletions test/parallel/test-internal-errors.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');

const {
hijackStdout,
restoreStdout,
} = require('../common/hijackstdio');
const assert = require('assert');
const errors = require('internal/errors');

Expand Down Expand Up @@ -241,22 +244,22 @@ assert.strictEqual(
// browser. Note that `message` remains non-enumerable after being assigned.
{
let initialConsoleLog = '';
common.hijackStdout((data) => { initialConsoleLog += data; });
hijackStdout((data) => { initialConsoleLog += data; });
const myError = new errors.codes.ERR_TLS_HANDSHAKE_TIMEOUT();
assert.deepStrictEqual(Object.keys(myError), []);
const initialToString = myError.toString();
console.log(myError);
assert.notStrictEqual(initialConsoleLog, '');

common.restoreStdout();
restoreStdout();

let subsequentConsoleLog = '';
common.hijackStdout((data) => { subsequentConsoleLog += data; });
hijackStdout((data) => { subsequentConsoleLog += data; });
myError.message = 'Fhqwhgads';
assert.deepStrictEqual(Object.keys(myError), []);
assert.notStrictEqual(myError.toString(), initialToString);
console.log(myError);
assert.strictEqual(subsequentConsoleLog, initialConsoleLog);

common.restoreStdout();
restoreStdout();
}
3 changes: 2 additions & 1 deletion test/parallel/test-process-raw-debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

'use strict';
const common = require('../common');
const { hijackStderr } = require('../common/hijackstdio');
const assert = require('assert');
const os = require('os');

Expand Down Expand Up @@ -63,7 +64,7 @@ function child() {
throw new Error('No ticking!');
};

common.hijackStderr(common.mustNotCall('stderr.write must not be called.'));
hijackStderr(common.mustNotCall('stderr.write must not be called.'));

process._rawDebug('I can still %s!', 'debug');
}
Loading