1// Test for "overlapped" stdio option. This test uses the "overlapped-checker"
2// helper program which basically a specialized echo program.
3//
4// The test has two goals:
5//
6// - Verify that overlapped I/O works on windows. The test program will deadlock
7//   if stdin doesn't have the FILE_FLAG_OVERLAPPED flag set on startup (see
8//   test/overlapped-checker/main_win.c for more details).
9// - Verify that "overlapped" stdio option works transparently as a pipe (on
10//   unix/windows)
11//
12// This is how the test works:
13//
14// - This script assumes only numeric strings are written to the test program
15//   stdout.
16// - The test program will be spawned with "overlapped" set on stdin and "pipe"
17//   set on stdout/stderr and at startup writes a number to its stdout
18// - When this script receives some data, it will parse the number, add 50 and
19//   write to the test program's stdin.
20// - The test program will then echo the number back to us which will repeat the
21//   cycle until the number reaches 200, at which point we send the "exit"
22//   string, which causes the test program to exit.
23// - Extra assertion: Every time the test program writes a string to its stdout,
24//   it will write the number of bytes written to stderr.
25// - If overlapped I/O is not setup correctly, this test is going to hang.
26'use strict';
27const common = require('../common');
28const assert = require('assert');
29const path = require('path');
30const child_process = require('child_process');
31
32const exeExtension = process.platform === 'win32' ? '.exe' : '';
33const exe = 'overlapped-checker' + exeExtension;
34const exePath = path.join(path.dirname(process.execPath), exe);
35
36if (!require('fs').existsSync(exePath)) {
37  common.skip(exe + ' binary is not available');
38}
39
40const child = child_process.spawn(exePath, [], {
41  stdio: ['overlapped', 'pipe', 'pipe']
42});
43
44child.stdin.setEncoding('utf8');
45child.stdout.setEncoding('utf8');
46child.stderr.setEncoding('utf8');
47
48function writeNext(n) {
49  child.stdin.write((n + 50).toString());
50}
51
52child.stdout.on('data', (s) => {
53  const n = Number(s);
54  if (n >= 200) {
55    child.stdin.write('exit');
56    return;
57  }
58  writeNext(n);
59});
60
61let stderr = '';
62child.stderr.on('data', (s) => {
63  stderr += s;
64});
65
66child.stderr.on('end', common.mustCall(() => {
67  // This is the sequence of numbers sent to us:
68  // - 0 (1 byte written)
69  // - 50 (2 bytes written)
70  // - 100 (3 bytes written)
71  // - 150 (3 bytes written)
72  // - 200 (3 bytes written)
73  assert.strictEqual(stderr, '12333');
74}));
75
76child.on('exit', common.mustCall((status) => {
77  // The test program will return the number of writes as status code.
78  assert.strictEqual(status, 0);
79}));
80