diff --git a/test/parallel/test-child-process-send-returns-boolean.js b/test/parallel/test-child-process-send-returns-boolean.js index e273d1c205..2fbba1a454 100644 --- a/test/parallel/test-child-process-send-returns-boolean.js +++ b/test/parallel/test-child-process-send-returns-boolean.js @@ -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); + }); +}