Skip to content

Commit

Permalink
test: move hijackstdio out of require('common')
Browse files Browse the repository at this point in the history
Move the hijackstdio functions out of common so that they are
imported only into the tests that actually need them

PR-URL: #22462
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
  • Loading branch information
jasnell authored and addaleax committed Aug 27, 2018
1 parent 29a5efa commit dc0b7e7
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 96 deletions.
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` [&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.

### inFreeBSDJail
* [&lt;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
* [&lt;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 @@ -787,30 +787,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 @@ -824,10 +800,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 @@ -60,11 +67,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 @@ -163,8 +170,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 @@ -234,8 +241,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 @@ -246,22 +249,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

0 comments on commit dc0b7e7

Please sign in to comment.