1'use strict';
2const common = require('../common');
3
4// subprocess.send() will return false if the channel has closed or when the
5// backlog of unsent messages exceeds a threshold that makes it unwise to send
6// more. Otherwise, the method returns true.
7
8const assert = require('assert');
9const net = require('net');
10const { fork, spawn } = require('child_process');
11const fixtures = require('../common/fixtures');
12
13// Just a script that stays alive (does not listen to `process.on('message')`).
14const subScript = fixtures.path('child-process-persistent.js');
15
16{
17  // Test `send` return value on `fork` that opens and IPC by default.
18  const n = fork(subScript);
19  // `subprocess.send` should always return `true` for the first send.
20  const rv = n.send({ h: 'w' }, assert.ifError);
21  assert.strictEqual(rv, true);
22  n.kill('SIGKILL');
23}
24
25{
26  // Test `send` return value on `spawn` and saturate backlog with handles.
27  // Call `spawn` with options that open an IPC channel.
28  const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
29  const s = spawn(process.execPath, [subScript], spawnOptions);
30
31  const server = net.createServer(common.mustNotCall()).listen(0, () => {
32    const handle = server._handle;
33
34    // Sending a handle and not giving the tickQueue time to acknowledge should
35    // create the internal backlog, but leave it empty.
36    const rv1 = s.send('one', handle, (err) => { if (err) assert.fail(err); });
37    assert.strictEqual(rv1, true);
38    // Since the first `send` included a handle (should be unacknowledged),
39    // we can safely queue up only one more message.
40    const rv2 = s.send('two', (err) => { if (err) assert.fail(err); });
41    assert.strictEqual(rv2, true);
42    // The backlog should now be indicate to backoff.
43    const rv3 = s.send('three', (err) => { if (err) assert.fail(err); });
44    assert.strictEqual(rv3, false);
45    const rv4 = s.send('four', (err) => {
46      if (err) assert.fail(err);
47      // `send` queue should have been drained.
48      const rv5 = s.send('5', handle, (err) => { if (err) assert.fail(err); });
49      assert.strictEqual(rv5, true);
50
51      // End test and cleanup.
52      s.kill();
53      handle.close();
54      server.close();
55    });
56    assert.strictEqual(rv4, false);
57  });
58}
59