From ed2d7cd365616b8c1beca853a20bb5a071a2744d Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Wed, 7 Feb 2018 10:33:51 +0100 Subject: [PATCH] test: stdio pipe behavior tests Add two regression tests for stdio over pipes. test-stdio-pipe-access tests if accessing stdio pipe that is being read by another process does not deadlocks Node.js. This was reported in https://github.com/nodejs/node/issues/10836 and was fixed in v8.3.0. The deadlock would happen intermittently, so we run the test 5 times. test-stdio-pipe-redirect tests if redirecting one child process stdin to another process stdout does not crash Node as reported in https://github.com/nodejs/node/issues/17493. It was fixed in https://github.com/nodejs/node/pull/18019. PR-URL: https://github.com/nodejs/node/pull/18614 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- test/parallel/test-stdio-pipe-access.js | 35 +++++++++++++++++++++ test/parallel/test-stdio-pipe-redirect.js | 38 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 test/parallel/test-stdio-pipe-access.js create mode 100644 test/parallel/test-stdio-pipe-redirect.js diff --git a/test/parallel/test-stdio-pipe-access.js b/test/parallel/test-stdio-pipe-access.js new file mode 100644 index 00000000000000..ef84bb83803b26 --- /dev/null +++ b/test/parallel/test-stdio-pipe-access.js @@ -0,0 +1,35 @@ +'use strict'; +require('../common'); + +// Test if Node handles acessing process.stdin if it is a redirected +// pipe without deadlocking +const { spawn, spawnSync } = require('child_process'); + +const numTries = 5; +const who = process.argv.length <= 2 ? 'runner' : process.argv[2]; + +switch (who) { + case 'runner': + for (let num = 0; num < numTries; ++num) { + spawnSync(process.argv0, + [process.argv[1], 'parent'], + { 'stdio': 'inherit' }); + } + break; + case 'parent': + const middle = spawn(process.argv0, + [process.argv[1], 'middle'], + { 'stdio': 'pipe' }); + middle.stdout.on('data', () => {}); + break; + case 'middle': + spawn(process.argv0, + [process.argv[1], 'bottom'], + { 'stdio': [ process.stdin, + process.stdout, + process.stderr ] }); + break; + case 'bottom': + process.stdin; + break; +} diff --git a/test/parallel/test-stdio-pipe-redirect.js b/test/parallel/test-stdio-pipe-redirect.js new file mode 100644 index 00000000000000..b47f5b9cf44af5 --- /dev/null +++ b/test/parallel/test-stdio-pipe-redirect.js @@ -0,0 +1,38 @@ +'use strict'; +require('../common'); + +// Test if Node handles redirecting one child process stdout to another +// process stdin without crashing. +const spawn = require('child_process').spawn; + +const writeSize = 100; +const totalDots = 10000; + +const who = process.argv.length <= 2 ? 'parent' : process.argv[2]; + +switch (who) { + case 'parent': + const consumer = spawn(process.argv0, [process.argv[1], 'consumer'], { + stdio: ['pipe', 'ignore', 'inherit'], + }); + const producer = spawn(process.argv0, [process.argv[1], 'producer'], { + stdio: ['pipe', consumer.stdin, 'inherit'], + }); + process.stdin.on('data', () => {}); + producer.on('exit', process.exit); + break; + case 'producer': + const buffer = Buffer.alloc(writeSize, '.'); + let written = 0; + const write = () => { + if (written < totalDots) { + written += writeSize; + process.stdout.write(buffer, write); + } + }; + write(); + break; + case 'consumer': + process.stdin.on('data', () => {}); + break; +}