From 07ceb545bdd6c19cad7e8799889392836758fdc6 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Aug 2018 09:17:19 -0700 Subject: [PATCH] test: move hijackstdio out of require('common') Move the hijackstdio functions out of common so that they are imported only into the tests that actually need them PR-URL: https://github.com/nodejs/node/pull/22462 Reviewed-By: Ruben Bridgewater Reviewed-By: Refael Ackermann Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca --- test/common/README.md | 78 +++++++++++++-------- test/common/hijackstdio.js | 33 +++++++++ test/common/index.js | 28 -------- test/common/index.mjs | 8 --- test/parallel/test-common.js | 9 +-- test/parallel/test-console-group.js | 16 +++-- test/parallel/test-console.js | 19 +++-- test/parallel/test-internal-errors.js | 13 ++-- test/parallel/test-process-raw-debug.js | 3 +- test/parallel/test-process-warning.js | 8 ++- test/parallel/test-repl-tab-complete.js | 8 ++- test/parallel/test-tls-parse-cert-string.js | 8 ++- test/parallel/test-util-log.js | 11 ++- 13 files changed, 146 insertions(+), 96 deletions(-) create mode 100644 test/common/hijackstdio.js diff --git a/test/common/README.md b/test/common/README.md index e44dcd299c4caa..487c252af39779 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -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>] @@ -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>] @@ -596,6 +568,52 @@ validateSnapshotNodes('TLSWRAP', [ ]); ``` +## hijackstdio Module + +The `hijackstdio` module provides utility functions for temporarily redirecting +`stdout` and `stderr` output. + + +```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` [<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. + +### 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 @@ -773,6 +791,6 @@ implementation with tests from [<boolean>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type [<number>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type [<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 diff --git a/test/common/hijackstdio.js b/test/common/hijackstdio.js new file mode 100644 index 00000000000000..fcc98208f0ec8c --- /dev/null +++ b/test/common/hijackstdio.js @@ -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') +}; diff --git a/test/common/index.js b/test/common/index.js index 696d9201226ed9..78590a3330cd2a 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -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 @@ -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 || diff --git a/test/common/index.mjs b/test/common/index.mjs index 3ad51d4cae7e0e..5a0d547d595b6d 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -52,10 +52,6 @@ const { disableCrashOnUnhandledRejection, getTTYfd, runWithInvalidFD, - hijackStdout, - hijackStderr, - restoreStdout, - restoreStderr, isCPPSymbolsNotMapped } = common; @@ -109,9 +105,5 @@ export { disableCrashOnUnhandledRejection, getTTYfd, runWithInvalidFD, - hijackStdout, - hijackStderr, - restoreStdout, - restoreStderr, isCPPSymbolsNotMapped }; diff --git a/test/parallel/test-common.js b/test/parallel/test-common.js index 7a89b37660d5f6..eafe4dd830bcb2 100644 --- a/test/parallel/test-common.js +++ b/test/parallel/test-common.js @@ -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'); @@ -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); @@ -105,14 +106,14 @@ 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 @@ -120,7 +121,7 @@ const HIJACK_TEST_ARRAY = [ 'foo\n', 'bar\n', 'baz\n' ]; })); console[method]('test'); - common[`restoreStd${type}`](); + hijackstdio[`restoreStd${type}`](); }); let uncaughtTimes = 0; diff --git a/test/parallel/test-console-group.js b/test/parallel/test-console-group.js index 8486d1a7ace367..9ab6c9db7e8c16 100644 --- a/test/parallel/test-console-group.js +++ b/test/parallel/test-console-group.js @@ -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; @@ -8,12 +14,12 @@ 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; }); @@ -21,8 +27,8 @@ function setup() { } function teardown() { - common.restoreStdout(); - common.restoreStderr(); + restoreStdout(); + restoreStderr(); } // Basic group() functionality diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index a0e6e322a5e42a..1a041c7f90ef72 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -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 @@ -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); }); @@ -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; @@ -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() { diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index 8fda4b25f2f5e2..be93598e068464 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -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'); @@ -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(); } diff --git a/test/parallel/test-process-raw-debug.js b/test/parallel/test-process-raw-debug.js index 1f1ec4c3803e2e..090525e18c5d3e 100644 --- a/test/parallel/test-process-raw-debug.js +++ b/test/parallel/test-process-raw-debug.js @@ -21,6 +21,7 @@ 'use strict'; const common = require('../common'); +const { hijackStderr } = require('../common/hijackstdio'); const assert = require('assert'); const os = require('os'); @@ -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'); } diff --git a/test/parallel/test-process-warning.js b/test/parallel/test-process-warning.js index da4521da790650..e4538ddc084722 100644 --- a/test/parallel/test-process-warning.js +++ b/test/parallel/test-process-warning.js @@ -1,12 +1,16 @@ 'use strict'; const common = require('../common'); +const { + hijackStderr, + restoreStderr +} = require('../common/hijackstdio'); const assert = require('assert'); function test1() { // Output is skipped if the argument to the 'warning' event is // not an Error object. - common.hijackStderr(common.mustNotCall('stderr.write must not be called')); + hijackStderr(common.mustNotCall('stderr.write must not be called')); process.emit('warning', 'test'); setImmediate(test2); } @@ -21,7 +25,7 @@ function test2() { } function test3() { - common.restoreStderr(); + restoreStderr(); // Type defaults to warning when the second argument is an object process.emitWarning('test', {}); process.once('warning', common.mustCall((warning) => { diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index a336058fa16d01..784bcade77e6fa 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -23,6 +23,10 @@ const common = require('../common'); const ArrayStream = require('../common/arraystream'); +const { + hijackStderr, + restoreStderr +} = require('../common/hijackstdio'); const assert = require('assert'); const fixtures = require('../common/fixtures'); const hasInspector = process.config.variables.v8_enable_inspector === 1; @@ -423,9 +427,9 @@ testMe.complete('obj.', common.mustCall((error, data) => { putIn.run([`var ele = new ${type.name}(1e6 + 1); ele.biu = 1;`]); } - common.hijackStderr(common.mustNotCall()); + hijackStderr(common.mustNotCall()); testMe.complete('ele.', common.mustCall((err, data) => { - common.restoreStderr(); + restoreStderr(); assert.ifError(err); const ele = (type === Array) ? diff --git a/test/parallel/test-tls-parse-cert-string.js b/test/parallel/test-tls-parse-cert-string.js index a0bafe9c528774..a3062c227e6fd1 100644 --- a/test/parallel/test-tls-parse-cert-string.js +++ b/test/parallel/test-tls-parse-cert-string.js @@ -5,13 +5,17 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +const { + hijackStderr, + restoreStderr +} = require('../common/hijackstdio'); const assert = require('assert'); // Flags: --expose_internals const internalTLS = require('internal/tls'); const tls = require('tls'); const noOutput = common.mustNotCall(); -common.hijackStderr(noOutput); +hijackStderr(noOutput); { const singles = 'C=US\nST=CA\nL=SF\nO=Node.js Foundation\nOU=Node.js\n' + @@ -54,7 +58,7 @@ common.hijackStderr(noOutput); assert.deepStrictEqual(internalTLS.parseCertString(input), expected); } -common.restoreStderr(); +restoreStderr(); { common.expectWarning('DeprecationWarning', diff --git a/test/parallel/test-util-log.js b/test/parallel/test-util-log.js index 907a361e97ecb8..4d81fc8f7a4255 100644 --- a/test/parallel/test-util-log.js +++ b/test/parallel/test-util-log.js @@ -21,6 +21,11 @@ 'use strict'; const common = require('../common'); +const { + hijackStdout, + hijackStderr, + restoreStdout, +} = require('../common/hijackstdio'); const assert = require('assert'); const util = require('util'); @@ -28,10 +33,10 @@ assert.ok(process.stdout.writable); assert.ok(process.stderr.writable); const strings = []; -common.hijackStdout(function(data) { +hijackStdout(function(data) { strings.push(data); }); -common.hijackStderr(common.mustNotCall('stderr.write must not be called')); +hijackStderr(common.mustNotCall('stderr.write must not be called')); const tests = [ { input: 'foo', output: 'foo' }, @@ -57,4 +62,4 @@ tests.forEach(function(test) { assert.strictEqual(process.stdout.writeTimes, tests.length); -common.restoreStdout(); +restoreStdout();