-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
child_process: spawn ignores options in case args is undefined #24913
child_process: spawn ignores options in case args is undefined #24913
Conversation
Can you add a test for this? |
lib/child_process.js
Outdated
@@ -403,8 +403,9 @@ function normalizeSpawnArguments(file, args, options) { | |||
|
|||
if (Array.isArray(args)) { | |||
args = args.slice(0); | |||
} else if (args !== undefined && | |||
(args === null || typeof args !== 'object')) { | |||
} else if (args === undefined) { |
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.
Any reason not to be generous and permit null
here? I believe our linter permits == null
which evaluates to true
for both null
and undefined
. In fact, there are two other places in this file already that use that.
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.
Adjusted that case.
Here's what the test file could look like. 'use strict';
const common = require('../common');
const assert = require('assert');
const { spawn } = require('child_process');
const tmpdir = require('../common/tmpdir');
const command = common.isWindows ? 'cd' : 'pwd';
const subprocess = spawn(command, undefined, { cwd: tmpdir.path });
subprocess.stdout.on('data', common.mustCall((data) => {
const actual = data.toString().trim().toLowerCase();
const expected = tmpdir.path.trim().toLowerCase();
assert.strictEqual(actual, expected);
})); |
1b28329
to
f52d957
Compare
Updated PR. |
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
// USE OR OTHER DEALINGS IN THE SOFTWARE. |
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.
New tests should not include the copyright boilerplate.
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.
+
const subprocess = spawn(command, testCase, { cwd: tmpdir.path }); | ||
|
||
subprocess.stdout.on('data', common.mustCall((data) => { | ||
resolve(data.toString().trim().toLowerCase()); |
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.
Use subprocess.stdout.setEncoding('utf8')
so you get strings instead of buffers and accumulate the strings.
toString-ing a buffer is unsound because the output may be split over multiple buffers (i.e., you can get multiple 'data' events and multi-byte sequences may be split across buffers.)
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.
Good catch, overlooked that
f52d957
to
2f8a34c
Compare
PR has been updated according to comments. |
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.
LGTM as-is or with the comment I suggested adding.
2f8a34c
to
f57a30b
Compare
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.
See comment.
@@ -0,0 +1,46 @@ | |||
'use strict'; |
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 is already a test for this behaviour, could you expand it instead of adding another test file? See test-child-process-spawn-typeerror.js
(and yes, it's name doesn't well reflect is purpose anymore). I assume this change effects, or SHOULD effect, every child_process API that accepts an argv
argument, showing that they have identical handling of the argv
option, which is what the test I mentioned is set up for.
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.
@sam-github Nit or requirement to land?
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 it lands with these changes. Particularly with API consistency.
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.
That's a little bit controversial.
This file contains lots of unrelated checks, like https://github.com/nodejs/node/blob/master/test/parallel/test-child-process-spawn-typeerror.js#L115. Why do we test execFile
function within spawn
test file, shouldn't it be placed in test-child-process-exec-file.js or something like that ?
And we have already separate test file test-child-process-spawn-argv0.js for testing argv0 param, so what the problem with args
?
In my opinion, *-spawn-typeerror.js should contain tests just about incorrect types, and just for spawn method.
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 addition, that fix effects only spawn
and spawnSync
methods.
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 also favor smaller, more-focused test files, especially for child_process
tests in parallel
.
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 consider that tests that are intended to ensure multiple APIs have behave identically, when they should, are best contained within a single file.
At this time, I can't tell from the tests whether all the child_process APIs do, in fact, have identical arg handling. Also, I can't tell if this PR makes them more (or less) consistent. Its possible that it fixes an inconsistency. Its possible it makes them inconsistent. I don't know. Ideally, the test structure would make that very clear. Every PR doesn't have to be ideal. I'm removing my review.
89d8237
to
982fc17
Compare
@@ -0,0 +1,38 @@ | |||
'use strict'; |
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.
Added same test for spawnSync
method.
982fc17
to
18d4a95
Compare
Looks like there are relevant test failures on Windows: 15:40:38 not ok 64 parallel/test-child-process-spawn-args
15:40:38 ---
15:40:38 duration_ms: 0.251
15:40:38 severity: fail
15:40:38 exitcode: 1
15:40:38 stack: |-
15:40:38 events.js:174
15:40:38 throw er; // Unhandled 'error' event
15:40:38 ^
15:40:38
15:40:38 Error: spawn cd ENOENT
15:40:38 at Process.ChildProcess._handle.onexit (internal/child_process.js:246:19)
15:40:38 at onErrorNT (internal/child_process.js:422:16)
15:40:38 at internalTickCallback (internal/process/next_tick.js:72:19)
15:40:38 at process._tickCallback (internal/process/next_tick.js:47:5)
15:40:38 at Function.Module.runMain (internal/modules/cjs/loader.js:774:11)
15:40:38 at executeUserCode (internal/bootstrap/node.js:317:15)
15:40:38 at startExecution (internal/bootstrap/node.js:251:3)
15:40:38 at startup (internal/bootstrap/node.js:202:3)
15:40:38 at internal/bootstrap/node.js:682:1
15:40:38 Emitted 'error' event at:
15:40:38 at Process.ChildProcess._handle.onexit (internal/child_process.js:252:12)
15:40:38 at onErrorNT (internal/child_process.js:422:16)
15:40:38 [... lines matching original stack trace ...]
15:40:38 at internal/bootstrap/node.js:682:1
15:40:38 ... 15:45:14 ok 65 parallel/test-child-process-spawn-argv0
15:45:14 ---
15:45:14 duration_ms: 0.596
15:45:14 ...
15:45:15 not ok 66 parallel/test-child-process-spawnsync-args
15:45:15 ---
15:45:15 duration_ms: 0.201
15:45:15 severity: fail
15:45:15 exitcode: 1
15:45:15 stack: |-
15:45:15 assert.js:86
15:45:15 throw new AssertionError(obj);
15:45:15 ^
15:45:15
15:45:15 AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
15:45:15 + actual - expected
15:45:15
15:45:15 + null
15:45:15 - Buffer [Uint8Array] []
15:45:15 at testCases.map (c:\workspace\node-test-binary-windows\test\parallel\test-child-process-spawnsync-args.js:33:10)
15:45:15 at Array.map (<anonymous>)
15:45:15 at Object.<anonymous> (c:\workspace\node-test-binary-windows\test\parallel\test-child-process-spawnsync-args.js:26:27)
15:45:15 at Module._compile (internal/modules/cjs/loader.js:718:30)
15:45:15 at Object.Module._extensions..js (internal/modules/cjs/loader.js:729:10)
15:45:15 at Module.load (internal/modules/cjs/loader.js:617:32)
15:45:15 at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
15:45:15 at Function.Module._load (internal/modules/cjs/loader.js:552:3)
15:45:15 at Function.Module.runMain (internal/modules/cjs/loader.js:771:12)
15:45:15 at executeUserCode (internal/bootstrap/node.js:317:15)
15:45:15 ... |
18d4a95
to
5c90c83
Compare
Fixed tests for Windows based systems |
5c90c83
to
9db8495
Compare
Still seems to be failing in relevant ways on Windows: 14:32:33 not ok 64 parallel/test-child-process-spawn-args
14:32:33 ---
14:32:33 duration_ms: 0.250
14:32:33 severity: fail
14:32:33 exitcode: 1
14:32:33 stack: |-
14:32:33 events.js:174
14:32:33 throw er; // Unhandled 'error' event
14:32:33 ^
14:32:33
14:32:33 Error: spawn cd ENOENT
14:32:33 at Process.ChildProcess._handle.onexit (internal/child_process.js:246:19)
14:32:33 at onErrorNT (internal/child_process.js:422:16)
14:32:33 at internalTickCallback (internal/process/next_tick.js:72:19)
14:32:33 at process._tickCallback (internal/process/next_tick.js:47:5)
14:32:33 at Function.Module.runMain (internal/modules/cjs/loader.js:774:11)
14:32:33 at executeUserCode (internal/bootstrap/node.js:318:15)
14:32:33 at startExecution (internal/bootstrap/node.js:252:3)
14:32:33 at startup (internal/bootstrap/node.js:203:3)
14:32:33 at internal/bootstrap/node.js:693:1
14:32:33 Emitted 'error' event at:
14:32:33 at Process.ChildProcess._handle.onexit (internal/child_process.js:252:12)
14:32:33 at onErrorNT (internal/child_process.js:422:16)
14:32:33 [... lines matching original stack trace ...]
14:32:33 at internal/bootstrap/node.js:693:1
14:32:33 ... Do you have access to a Windows machine? If not, maybe someone from @nodejs/platform-windows can help. |
spawn method ignores 3-d argument 'options' in case the second one 'args' equals to 'undefined'. Fixes: nodejs#24912
9db8495
to
f4e8e66
Compare
@Trott no, I don't but that typo could be the case, let's check one more time |
spawn method ignores 3-d argument 'options' in case the second one 'args' equals to 'undefined'. Fixes: nodejs#24912 PR-URL: nodejs#24913 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Landed in 2077007 |
The tests added in this PR fail for me locally:
Am I missing something? |
python tools/test.py -J --mode=release test/parallel/test-child-process-spawn-args.js Details: https://github.com/nodejs/node/blob/master/BUILDING.md#running-tests |
@targos The test is missing a I'll open a PR to fix. |
Without `tmpdir.refresh()`, the test fails in some situations. This was missed because using `test.py` will almost always result in a leftover tmpdir lying around that makes the `refresh()` not needed. Refs: nodejs#24913 (comment)
FWIW I initially saw the tests fail with |
Without `tmpdir.refresh()`, the test fails in some situations. This was missed because using `test.py` will almost always result in a leftover tmpdir lying around that makes the `refresh()` not needed. Refs: nodejs#24913 (comment) PR-URL: nodejs#25098 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
Without `tmpdir.refresh()`, the test fails in some situations. This was missed because using `test.py` will almost always result in a leftover tmpdir lying around that makes the `refresh()` not needed. Refs: #24913 (comment) PR-URL: #25098 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
spawn method ignores 3-d argument 'options' in case the second one 'args' equals to 'undefined'. Fixes: nodejs#24912 PR-URL: nodejs#24913 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Without `tmpdir.refresh()`, the test fails in some situations. This was missed because using `test.py` will almost always result in a leftover tmpdir lying around that makes the `refresh()` not needed. Refs: nodejs#24913 (comment) PR-URL: nodejs#25098 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
Without `tmpdir.refresh()`, the test fails in some situations. This was missed because using `test.py` will almost always result in a leftover tmpdir lying around that makes the `refresh()` not needed. Refs: #24913 (comment) PR-URL: #25098 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Signed-off-by: Beth Griggs <Bethany.Griggs@uk.ibm.com>
spawn method ignores 3-d argument 'options' in case
the second one 'args' equals to 'undefined'.
Fixes: #24912
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes