-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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: add hijackStdout and hijackStderr #13439
Conversation
Add `common.hijackStdout` and `common.hijackStderr` to provide monitor for console output. Refs: https://github.com/nodejs/node/blob/917f86ea353e087af3bc4553219ffabaa2193d20/test/parallel/test-global-console-exists.js#L41-L43
/cc @nodejs/testing |
cc/ @nodejs/testing |
Why is this being added to the test/common.js for a single test? It seems like this is very test-specific and should belong in the test file itself? |
I'm with @mscdex. |
Better yet, hoist them to common if it turns out there's a need for them in several tests. |
test/common/index.js
Outdated
stream.write = function(data) { | ||
listener(data); | ||
_write(data); | ||
stream.writeTimes++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic seem not go well with the writable.write specification:
callback (Function) :Callback for when this chunk of data is flushed
Your logic will cause:
- Issue the completion handler before the actual write (_write)
- Listener will be called in the same loop tick, making it a direct call, not a callback.
I propose:
_wite(data, listener)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, listener
is something like .emit('write')
but not .emit('written')
, so it's sync.
And I've added the callback
in _write
now.
stderr.write = function() { | ||
throw new Error('No writing to stderr!'); | ||
}; | ||
common.hijackStderr(common.mustNotCall('stderr.write mustn\'t be called.')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd avoid the contraction or use template strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I don't quite understand what's your meaning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace 'stderr.write mustn\'t be called.'
with either:
'stderr.write must not be called.'
or
`stderr.write mustn't be called.`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/common/README.md
Outdated
@@ -116,6 +116,16 @@ Checks whether `IPv6` is supported on this platform. | |||
|
|||
Checks if there are multiple localhosts available. | |||
|
|||
### hijackStderr(listener) | |||
* `listener` [<Function>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions): An listener with a single parameter called `data`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"A listener"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please break the lines at 80 chars if possible.
test/fixtures/echo-close-check.js
Outdated
|
||
let current; | ||
common.hijackStdout(function(data) { | ||
assert.equal(data, current); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use strict equal.
test/fixtures/echo-close-check.js
Outdated
const stdin = process.openStdin(); | ||
|
||
let current; | ||
common.hijackStdout(function(data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there is an assertion in the listener function, it is better to have it wrapped in common.mustCall
test/parallel/test-console.js
Outdated
@@ -159,3 +156,13 @@ assert.throws(() => { | |||
assert.doesNotThrow(() => { | |||
console.assert(true, 'this should not throw'); | |||
}); | |||
|
|||
// hijack stderr to catch `process.emitWarning` which using `process.nextTick` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which is using
|
||
let write_calls = 0; | ||
common.hijackStderr(function(data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
common.mustCall
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits
Some comments about synchronization
I'm +1 for this feature
test/parallel/test-console.js
Outdated
|
||
// stderr.write will catch sync error, so use `process.nextTick` here | ||
process.nextTick(function() { | ||
assert(/no such label/.test(data)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like assert.strictEqual(data.includes('no such label'), true)
better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/common/README.md
Outdated
@@ -116,6 +116,26 @@ Checks whether `IPv6` is supported on this platform. | |||
|
|||
Checks if there are multiple localhosts available. | |||
|
|||
### hijackStderr(listener) | |||
* `listener` | |||
[<Function>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I know everywhere else uses it this way but) if you are using this link more than one you could use [MDN-Function][]
, and put
[MDN-Function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions
the the bottom of the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/common/README.md
Outdated
[<Function>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions): | ||
a listener with a single parameter called `data`. | ||
|
||
Hijack `process.stderr` to listen `write` action. Once `process.stderr.write` is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hijack `process.stderr` to listen `write` action
=> Eavesdrop to `process.stderr.write` calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/common/README.md
Outdated
|
||
Hijack `process.stderr` to listen `write` action. 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` will plus one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... `process.stderr.writeTimes` is a count of the number of calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/common/README.md
Outdated
[<Function>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions): | ||
a listener with a single parameter called `data`. | ||
|
||
Hijack `process.stdout` to listen `write` action. Once `process.stdout.write` is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
IMHO since this is an "internal" guide you could merge then into
### hijackStdout/Stderr(listener)
test/fixtures/echo-close-check.js
Outdated
const stdin = process.openStdin(); | ||
|
||
let current; | ||
common.hijackStdout(common.mustCall(function(data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't this this is an interesting use of hijackStdout
, it just tests the mechanics of hijackStdout
.
BTW: you should do that in explicitly in test/parallel/test-common.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/fixtures/echo.js
Outdated
process.stdout.write(data.toString()); | ||
}); | ||
|
||
common.hijackStdout(function(data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
@@ -105,8 +103,10 @@ console.timeEnd('constructor'); | |||
console.time('hasOwnProperty'); | |||
console.timeEnd('hasOwnProperty'); | |||
|
|||
global.process.stdout.write = stdout_write; | |||
global.process.stderr.write = stderr_write; | |||
assert.strictEqual(strings.length, process.stdout.writeTimes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't this fail after you implemented @gireeshpunathil's async comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, listener
is sync which means a write
action is emitted but not finished.
I just added the callback
to the original _write
function to make it may receivecallback
.
@@ -146,9 +146,6 @@ assert.ok(/^hasOwnProperty: \d+\.\d{3}ms$/.test(strings.shift().trim())); | |||
assert.strictEqual('Trace: This is a {"formatted":"trace"} 10 foo', | |||
errStrings.shift().split('\n').shift()); | |||
|
|||
assert.strictEqual(strings.length, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep this.
But I assume you'll need to solve async issues with this whole block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same which mentioned before.
And assert.strictEqual(strings.length, 0)
equals above assert.strictEqual(strings.length, process.stdout.writeTimes);
.
Quick CI (linuxone): https://ci.nodejs.org/job/node-test-commit-linuxone/6370/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks ✔️
@refack Thanks |
test/common/README.md
Outdated
@@ -116,6 +116,14 @@ Checks whether `IPv6` is supported on this platform. | |||
|
|||
Checks if there are multiple localhosts available. | |||
|
|||
### hijackStderr/Stdout(listener) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be listed as separate functions (even if it means duplicating the text)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasnell I suggested the the merge (since it's an internal guide) #13439 (comment)
Please 👍 / 👎 again, just so we don't ask @XadillaX to do unnecessary work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather keep the style consistent throughout, so would really prefer them separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack.
Sorry @XadillaX
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
test/common/README.md
Outdated
@@ -250,6 +258,14 @@ Port tests are running on. | |||
|
|||
Deletes the 'tmp' dir and recreates it | |||
|
|||
### restoreStderr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are functions, then please include the ()
@Trott you ok with this? |
I'm neutral on this change, so I guess that means I'm ok with it. |
I think I've done all of the work after reviewing. @jasnell |
/cc @nodejs/testing anyone else have an 👍 / 👎 opinion? |
so could it be landed now? |
If CI failures are unrelated (I haven't looked), then, yes, this can be landed. Probable lander would be @refack since he's the sole approval right now. @mscdex @gibfahn If you're questions/skepticism should be interpreted as being opposed to this landing, please say so and maybe use the |
@XadillaX technically it's ready, AFAICT CI is clean, but hust in case: |
Add `common.hijackStdout` and `common.hijackStderr` to provide monitor for console output. PR-URL: nodejs#13439 Reviewed-By: Refael Ackermann <[email protected]>
Landed in d00e5f1 |
Extra quick sanity of |
Add `common.hijackStdout` and `common.hijackStderr` to provide monitor for console output. PR-URL: #13439 Reviewed-By: Refael Ackermann <[email protected]>
is this something we want to add to lts? |
if we want to land this on 6.x it will require a manual backport |
Add
common.hijackStdout
andcommon.hijackStderr
to provide monitorfor console output.
Refs:
node/test/parallel/test-global-console-exists.js
Lines 41 to 43 in 917f86e
Checklist
make -j4 test
(UNIX)