Skip to content

Commit

Permalink
doc: fix default maxBuffer size
Browse files Browse the repository at this point in the history
Correctly document the default maxBuffer size for execSync,
execFileSync, and spawnSync. It is 200 * 1024, not Infinity.
Add tests to verify behaviour is as documented.

PR-URL: #22894
Reviewed-By: Sam Roberts <[email protected]>
  • Loading branch information
koh110 authored and sam-github committed Apr 4, 2019
1 parent b180a15 commit ceb80f4
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 3 deletions.
6 changes: 3 additions & 3 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ changes:
process will be killed. **Default:** `'SIGTERM'`.
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
stderr. If exceeded, the child process is terminated. See caveat at
[`maxBuffer` and Unicode][]. **Default:** `200 * 1024`.
[`maxBuffer` and Unicode][]. **Default:** `Infinity`.
* `encoding` {string} The encoding used for all stdio inputs and outputs.
**Default:** `'buffer'`.
* `windowsHide` {boolean} Hide the subprocess console window that would
Expand Down Expand Up @@ -788,7 +788,7 @@ changes:
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
stderr. If exceeded, the child process is terminated and any output is
truncated. See caveat at [`maxBuffer` and Unicode][].
**Default:** `200 * 1024`.
**Default:** `Infinity`.
* `encoding` {string} The encoding used for all stdio inputs and outputs.
**Default:** `'buffer'`.
* `windowsHide` {boolean} Hide the subprocess console window that would
Expand Down Expand Up @@ -852,7 +852,7 @@ changes:
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
stderr. If exceeded, the child process is terminated and any output is
truncated. See caveat at [`maxBuffer` and Unicode][].
**Default:** `200 * 1024`.
**Default:** `Infinity`.
* `encoding` {string} The encoding used for all stdio inputs and outputs.
**Default:** `'buffer'`.
* `shell` {boolean|string} If `true`, runs `command` inside of a shell. Uses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ function runChecks(err, stdio, streamName, expected) {
assert.deepStrictEqual(stdio[streamName], expected);
}

// default value
{
const cmd = `"${process.execPath}" -e "console.log('a'.repeat(200 * 1024))"`;

cp.exec(cmd, common.mustCall((err) => {
assert(err instanceof RangeError);
assert.strictEqual(err.message, 'stdout maxBuffer length exceeded');
assert.strictEqual(err.code, 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER');
}));
}

// default value
{
const cmd =
`${process.execPath} -e "console.log('a'.repeat(200 * 1024 - 1))"`;

cp.exec(cmd, common.mustCall((err, stdout, stderr) => {
assert.ifError(err);
assert.strictEqual(stdout.trim(), 'a'.repeat(200 * 1024 - 1));
assert.strictEqual(stderr, '');
}));
}

{
const cmd = `"${process.execPath}" -e "console.log('hello world');"`;
const options = { maxBuffer: Infinity };
Expand Down
94 changes: 94 additions & 0 deletions test/parallel/test-child-process-execfile-maxbuf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const { execFile } = require('child_process');

function checkFactory(streamName) {
return common.mustCall((err) => {
assert(err instanceof RangeError);
assert.strictEqual(err.message, `${streamName} maxBuffer length exceeded`);
assert.strictEqual(err.code, 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER');
});
}

// default value
{
execFile(
process.execPath,
['-e', 'console.log("a".repeat(200 * 1024))'],
checkFactory('stdout')
);
}

// default value
{
execFile(
process.execPath,
['-e', 'console.log("a".repeat(200 * 1024 - 1))'],
common.mustCall((err, stdout, stderr) => {
assert.ifError(err);
assert.strictEqual(stdout.trim(), 'a'.repeat(200 * 1024 - 1));
assert.strictEqual(stderr, '');
})
);
}

{
const options = { maxBuffer: Infinity };

execFile(
process.execPath,
['-e', 'console.log("hello world");'],
options,
common.mustCall((err, stdout, stderr) => {
assert.ifError(err);
assert.strictEqual(stdout.trim(), 'hello world');
assert.strictEqual(stderr, '');
})
);
}

{
execFile('echo', ['hello world'], { maxBuffer: 5 }, checkFactory('stdout'));
}

const unicode = '中文测试'; // length = 4, byte length = 12

{
execFile(
process.execPath,
['-e', `console.log('${unicode}');`],
{ maxBuffer: 10 },
checkFactory('stdout'));
}

{
execFile(
process.execPath,
['-e', `console.error('${unicode}');`],
{ maxBuffer: 10 },
checkFactory('stderr')
);
}

{
const child = execFile(
process.execPath,
['-e', `console.log('${unicode}');`],
{ encoding: null, maxBuffer: 10 },
checkFactory('stdout')
);

child.stdout.setEncoding('utf-8');
}

{
const child = execFile(
process.execPath,
['-e', `console.error('${unicode}');`],
{ encoding: null, maxBuffer: 10 },
checkFactory('stderr')
);

child.stderr.setEncoding('utf-8');
}
46 changes: 46 additions & 0 deletions test/parallel/test-child-process-execfilesync-maxbuf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';
require('../common');

// This test checks that the maxBuffer option for child_process.spawnSync()
// works as expected.

const assert = require('assert');
const execFileSync = require('child_process').execFileSync;
const msgOut = 'this is stdout';
const msgOutBuf = Buffer.from(`${msgOut}\n`);

const args = [
'-e',
`console.log("${msgOut}");`
];

// Verify that an error is returned if maxBuffer is surpassed.
{
assert.throws(
() => execFileSync(process.execPath, args, { maxBuffer: 1 }),
(e) => {
assert.ok(e, 'maxBuffer should error');
assert.strictEqual(e.errno, 'ENOBUFS');
assert.deepStrictEqual(e.stdout, msgOutBuf);
return true;
}
);
}

// Verify that a maxBuffer size of Infinity works.
{
const ret = execFileSync(process.execPath, args, { maxBuffer: Infinity });

assert.deepStrictEqual(ret, msgOutBuf);
}

// maxBuffer size is Infinity at default.
{
const ret = execFileSync(
process.execPath,
['-e', "console.log('a'.repeat(200 * 1024))"],
{ encoding: 'utf-8' }
);

assert.ifError(ret.error);
}
37 changes: 37 additions & 0 deletions test/parallel/test-child-process-execsync-maxbuf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';
require('../common');

// This test checks that the maxBuffer option for child_process.spawnSync()
// works as expected.

const assert = require('assert');
const { execSync } = require('child_process');
const msgOut = 'this is stdout';
const msgOutBuf = Buffer.from(`${msgOut}\n`);

const args = [
'-e',
`"console.log('${msgOut}')";`
];

// Verify that an error is returned if maxBuffer is surpassed.
{
assert.throws(() => {
execSync(`"${process.execPath}" ${args.join(' ')}`, { maxBuffer: 1 });
}, (e) => {
assert.ok(e, 'maxBuffer should error');
assert.strictEqual(e.errno, 'ENOBUFS');
assert.deepStrictEqual(e.stdout, msgOutBuf);
return true;
});
}

// Verify that a maxBuffer size of Infinity works.
{
const ret = execSync(
`"${process.execPath}" ${args.join(' ')}`,
{ maxBuffer: Infinity }
);

assert.deepStrictEqual(ret, msgOutBuf);
}
8 changes: 8 additions & 0 deletions test/parallel/test-child-process-spawnsync-maxbuf.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ const args = [
assert.ifError(ret.error);
assert.deepStrictEqual(ret.stdout, msgOutBuf);
}

// maxBuffer size is Infinity at default.
{
const args = ['-e', "console.log('a'.repeat(200 * 1024))"];
const ret = spawnSync(process.execPath, args, { encoding: 'utf-8' });

assert.ifError(ret.error);
}

0 comments on commit ceb80f4

Please sign in to comment.