Skip to content

Commit

Permalink
test: kill subprocess only after last ACK
Browse files Browse the repository at this point in the history
* Add multiple comments.
* Switch to a persistent fixture for subprocess.
* Assert that `send` queue is drained.

PR-URL: #15186
Fixes: #15176
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
refack authored and jasnell committed Sep 20, 2017
1 parent 2e421ff commit f0a741d
Showing 1 changed file with 47 additions and 17 deletions.
64 changes: 47 additions & 17 deletions test/parallel/test-child-process-send-returns-boolean.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,58 @@
'use strict';
const common = require('../common');

// subprocess.send() will return false if the channel has closed or when the
// backlog of unsent messages exceeds a threshold that makes it unwise to send
// more. Otherwise, the method returns true.

const assert = require('assert');
const net = require('net');
const { fork, spawn } = require('child_process');
const fixtures = require('../common/fixtures');

const emptyFile = fixtures.path('empty.js');
// Just a script that stays alive (does not listen to `process.on('message')`).
const subScript = fixtures.path('child-process-persistent.js');

{
// Test `send` return value on `fork` that opens and IPC by deafult.
const n = fork(subScript);
// `subprocess.send` should always return `true` for the first send.
const rv = n.send({ h: 'w' }, (err) => { if (err) assert.fail(err); });
assert.strictEqual(rv, true);
n.kill();
}

const n = fork(emptyFile);
{
// Test `send` return value on `spawn` and saturate backlog with handles.
// Call `spawn` with options that open an IPC channel.
const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
const s = spawn(process.execPath, [subScript], spawnOptions);

const rv = n.send({ hello: 'world' });
assert.strictEqual(rv, true);
const server = net.createServer(common.mustNotCall()).listen(0, () => {
const handle = server._handle;

const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
const s = spawn(process.execPath, [emptyFile], spawnOptions);
let handle = null;
s.on('exit', function() {
handle.close();
});
// Sending a handle and not giving the tickQueue time to acknoladge should
// create the internal backlog, but leave it empty.
const rv1 = s.send('one', handle, (err) => { if (err) assert.fail(err); });
assert.strictEqual(rv1, true);
// Since the first `send` included a handle (should be unackoladged),
// we can safly queue up only one more message.
const rv2 = s.send('two', (err) => { if (err) assert.fail(err); });
assert.strictEqual(rv2, true);
// The backlog should now be indicate to backoff.
const rv3 = s.send('three', (err) => { if (err) assert.fail(err); });
assert.strictEqual(rv3, false);
const rv4 = s.send('four', (err) => {
if (err) assert.fail(err);
// `send` queue should have been drained.
const rv5 = s.send('5', handle, (err) => { if (err) assert.fail(err); });
assert.strictEqual(rv5, true);

net.createServer(common.mustNotCall()).listen(0, function() {
handle = this._handle;
assert.strictEqual(s.send('one', handle), true);
assert.strictEqual(s.send('two', handle), true);
assert.strictEqual(s.send('three'), false);
assert.strictEqual(s.send('four'), false);
});
// End test and cleanup.
s.kill();
handle.close();
server.close();
});
assert.strictEqual(rv4, false);
});
}

0 comments on commit f0a741d

Please sign in to comment.