2019-05-05 05:27:57 +00:00
|
|
|
/+ dub.sdl:
|
|
|
|
name "test"
|
|
|
|
description "Subprocesses"
|
|
|
|
dependency "vibe-core" path="../"
|
|
|
|
+/
|
|
|
|
module test;
|
|
|
|
|
2019-06-02 04:42:41 +00:00
|
|
|
static if (__VERSION__ >= 2080) {
|
|
|
|
|
2019-05-05 05:27:57 +00:00
|
|
|
import core.thread;
|
|
|
|
import vibe.core.log;
|
|
|
|
import vibe.core.core;
|
|
|
|
import vibe.core.process;
|
|
|
|
import std.array;
|
|
|
|
import std.range;
|
|
|
|
import std.algorithm;
|
|
|
|
|
|
|
|
void testEcho()
|
|
|
|
{
|
|
|
|
foreach (i; 0..100) {
|
|
|
|
auto procPipes = pipeProcess(["echo", "foo bar"], Redirect.stdout);
|
|
|
|
|
|
|
|
assert(!procPipes.process.exited);
|
|
|
|
|
|
|
|
auto output = procPipes.stdout.collectOutput();
|
|
|
|
|
|
|
|
assert(procPipes.process.wait() == 0);
|
|
|
|
assert(procPipes.process.exited);
|
|
|
|
|
|
|
|
assert(output == "foo bar\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void testCat()
|
|
|
|
{
|
|
|
|
auto procPipes = pipeProcess(["cat"]);
|
|
|
|
|
|
|
|
string output;
|
|
|
|
auto outputTask = runTask({
|
|
|
|
output = procPipes.stdout.collectOutput();
|
|
|
|
});
|
|
|
|
|
|
|
|
auto inputs = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
|
|
|
|
.map!(s => s ~ "\n")
|
|
|
|
.repeat(4000).join.array;
|
|
|
|
foreach (input; inputs) {
|
|
|
|
procPipes.stdin.write(input);
|
|
|
|
}
|
|
|
|
|
|
|
|
procPipes.stdin.close();
|
|
|
|
assert(procPipes.process.wait() == 0);
|
|
|
|
|
|
|
|
outputTask.join();
|
|
|
|
|
|
|
|
assert(output == inputs.join());
|
|
|
|
}
|
|
|
|
|
|
|
|
void testStderr()
|
|
|
|
{
|
|
|
|
auto program = q{
|
|
|
|
foreach (line; stdin.byLine())
|
|
|
|
stderr.writeln(line);
|
|
|
|
};
|
|
|
|
auto procPipes = pipeProcess(["rdmd", "--eval", program], Redirect.stdin | Redirect.stderr);
|
|
|
|
|
2019-05-05 08:02:26 +00:00
|
|
|
// Wait for rdmd to compile
|
2019-05-07 00:30:11 +00:00
|
|
|
sleep(3.seconds);
|
2019-05-05 08:02:26 +00:00
|
|
|
|
2019-05-05 05:27:57 +00:00
|
|
|
string output;
|
|
|
|
auto outputTask = runTask({
|
|
|
|
output = procPipes.stderr.collectOutput();
|
|
|
|
});
|
|
|
|
|
|
|
|
auto inputs = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
|
|
|
|
.map!(s => s ~ "\n")
|
|
|
|
.repeat(4000).join.array;
|
|
|
|
foreach (input; inputs) {
|
|
|
|
procPipes.stdin.write(input);
|
|
|
|
}
|
|
|
|
|
|
|
|
procPipes.stdin.close();
|
|
|
|
assert(procPipes.process.wait() == 0);
|
|
|
|
|
|
|
|
outputTask.join();
|
|
|
|
|
|
|
|
assert(output == inputs.join);
|
|
|
|
}
|
|
|
|
|
|
|
|
void testRandomDeath()
|
|
|
|
{
|
2019-05-05 08:02:26 +00:00
|
|
|
auto program = q{
|
|
|
|
import core.thread;
|
|
|
|
import std.random;
|
|
|
|
Thread.sleep(dur!"msecs"(uniform(0, 1000)));
|
|
|
|
};
|
|
|
|
// Prime rdmd
|
|
|
|
execute(["rdmd", "--eval", program]);
|
|
|
|
|
2019-05-05 05:27:57 +00:00
|
|
|
foreach (i; 0..20) {
|
|
|
|
auto process = spawnProcess(["rdmd", "--eval", program]);
|
|
|
|
|
|
|
|
assert(!process.exited);
|
|
|
|
|
|
|
|
sleep(800.msecs);
|
|
|
|
try {
|
|
|
|
process.kill();
|
|
|
|
} catch (Exception e) {}
|
|
|
|
process.wait();
|
|
|
|
|
|
|
|
assert(process.exited);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void testIgnoreSigterm()
|
|
|
|
{
|
|
|
|
auto program = q{
|
|
|
|
import core.thread;
|
|
|
|
import core.sys.posix.signal;
|
|
|
|
|
|
|
|
signal(SIGINT, SIG_IGN);
|
|
|
|
signal(SIGTERM, SIG_IGN);
|
|
|
|
|
|
|
|
foreach (line; stdin.byLine()) {
|
|
|
|
writeln(line);
|
|
|
|
stdout.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zombie
|
|
|
|
while (true) Thread.sleep(100.dur!"msecs");
|
|
|
|
};
|
|
|
|
auto procPipes = pipeProcess(
|
|
|
|
["rdmd", "--eval", program],
|
|
|
|
Redirect.stdin | Redirect.stdout | Redirect.stderrToStdout);
|
|
|
|
|
|
|
|
string output;
|
|
|
|
auto outputTask = runTask({
|
|
|
|
output = procPipes.stdout.collectOutput();
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(!procPipes.process.exited);
|
|
|
|
|
2019-05-05 08:02:26 +00:00
|
|
|
// Give the program some time to compile and install the signal handler
|
2019-05-07 00:30:11 +00:00
|
|
|
sleep(4.seconds);
|
2019-05-05 05:27:57 +00:00
|
|
|
|
|
|
|
procPipes.process.kill();
|
|
|
|
procPipes.stdin.write("foo\n");
|
|
|
|
|
|
|
|
assert(!procPipes.process.exited);
|
|
|
|
|
|
|
|
assert(procPipes.process.waitOrForceKill(2.seconds) == 9);
|
|
|
|
|
|
|
|
assert(procPipes.process.exited);
|
|
|
|
|
|
|
|
outputTask.join();
|
|
|
|
|
|
|
|
assert(output == "foo\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void testSimpleShell()
|
|
|
|
{
|
|
|
|
auto res = executeShell("echo foo");
|
|
|
|
|
|
|
|
assert(res.status == 0);
|
|
|
|
assert(res.output == "foo\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void testLineEndings()
|
|
|
|
{
|
|
|
|
auto program = q{
|
|
|
|
write("linux\n");
|
|
|
|
write("os9\r");
|
|
|
|
write("win\r\n");
|
|
|
|
};
|
|
|
|
auto res = execute(["rdmd", "--eval", program]);
|
|
|
|
|
|
|
|
assert(res.status == 0);
|
|
|
|
assert(res.output == "linux\nos9\rwin\r\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
runTask({
|
|
|
|
auto tasks = [
|
|
|
|
&testEcho,
|
|
|
|
&testCat,
|
|
|
|
&testStderr,
|
|
|
|
&testRandomDeath,
|
|
|
|
&testIgnoreSigterm,
|
|
|
|
&testSimpleShell,
|
|
|
|
&testLineEndings,
|
|
|
|
].map!(fn => runTask({
|
|
|
|
try {
|
|
|
|
fn();
|
|
|
|
} catch (Exception e) {
|
|
|
|
logError("%s", e);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
|
|
|
foreach (task; tasks) {
|
|
|
|
task.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
exitEventLoop();
|
|
|
|
});
|
|
|
|
|
|
|
|
runEventLoop();
|
|
|
|
}
|
2019-06-02 04:42:41 +00:00
|
|
|
|
|
|
|
}
|