#include "subprocess.h"
#include "test.h"
#ifndef _WIN32
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#endif
using namespace std;
namespace {
#ifdef _WIN32
const char* kSimpleCommand = "cmd /c dir \\";
#else
const char* kSimpleCommand = "ls /";
#endif
struct SubprocessTest : public testing::Test {
SubprocessSet subprocs_;
};
}
TEST_F(SubprocessTest, BadCommandStderr) {
Subprocess* subproc = subprocs_.Add("cmd /c ninja_no_such_command");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitFailure, subproc->Finish());
EXPECT_NE("", subproc->GetOutput());
}
TEST_F(SubprocessTest, NoSuchCommand) {
Subprocess* subproc = subprocs_.Add("ninja_no_such_command");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitFailure, subproc->Finish());
EXPECT_NE("", subproc->GetOutput());
#ifdef _WIN32
ASSERT_EQ("CreateProcess failed: The system cannot find the file "
"specified.\n", subproc->GetOutput());
#endif
}
#ifndef _WIN32
TEST_F(SubprocessTest, InterruptChild) {
Subprocess* subproc = subprocs_.Add("kill -INT $$");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitInterrupted, subproc->Finish());
}
TEST_F(SubprocessTest, InterruptParent) {
Subprocess* subproc = subprocs_.Add("kill -INT $PPID ; sleep 1");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
return;
}
ASSERT_FALSE("We should have been interrupted");
}
TEST_F(SubprocessTest, InterruptChildWithSigTerm) {
Subprocess* subproc = subprocs_.Add("kill -TERM $$");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitInterrupted, subproc->Finish());
}
TEST_F(SubprocessTest, InterruptParentWithSigTerm) {
Subprocess* subproc = subprocs_.Add("kill -TERM $PPID ; sleep 1");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
return;
}
ASSERT_FALSE("We should have been interrupted");
}
TEST_F(SubprocessTest, InterruptChildWithSigHup) {
Subprocess* subproc = subprocs_.Add("kill -HUP $$");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitInterrupted, subproc->Finish());
}
TEST_F(SubprocessTest, InterruptParentWithSigHup) {
Subprocess* subproc = subprocs_.Add("kill -HUP $PPID ; sleep 1");
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
return;
}
ASSERT_FALSE("We should have been interrupted");
}
TEST_F(SubprocessTest, Console) {
if (isatty(0) && isatty(1) && isatty(2)) {
Subprocess* subproc =
subprocs_.Add("test -t 0 -a -t 1 -a -t 2", true);
ASSERT_NE((Subprocess*)0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
EXPECT_EQ(ExitSuccess, subproc->Finish());
}
}
#endif
TEST_F(SubprocessTest, SetWithSingle) {
Subprocess* subproc = subprocs_.Add(kSimpleCommand);
ASSERT_NE((Subprocess *) 0, subproc);
while (!subproc->Done()) {
subprocs_.DoWork();
}
ASSERT_EQ(ExitSuccess, subproc->Finish());
ASSERT_NE("", subproc->GetOutput());
ASSERT_EQ(1u, subprocs_.finished_.size());
}
TEST_F(SubprocessTest, SetWithMulti) {
Subprocess* processes[3];
const char* kCommands[3] = {
kSimpleCommand,
#ifdef _WIN32
"cmd /c echo hi",
"cmd /c time /t",
#else
"id -u",
"pwd",
#endif
};
for (int i = 0; i < 3; ++i) {
processes[i] = subprocs_.Add(kCommands[i]);
ASSERT_NE((Subprocess *) 0, processes[i]);
}
ASSERT_EQ(3u, subprocs_.running_.size());
for (int i = 0; i < 3; ++i) {
ASSERT_FALSE(processes[i]->Done());
ASSERT_EQ("", processes[i]->GetOutput());
}
while (!processes[0]->Done() || !processes[1]->Done() ||
!processes[2]->Done()) {
ASSERT_GT(subprocs_.running_.size(), 0u);
subprocs_.DoWork();
}
ASSERT_EQ(0u, subprocs_.running_.size());
ASSERT_EQ(3u, subprocs_.finished_.size());
for (int i = 0; i < 3; ++i) {
ASSERT_EQ(ExitSuccess, processes[i]->Finish());
ASSERT_NE("", processes[i]->GetOutput());
delete processes[i];
}
}
#if defined(USE_PPOLL)
TEST_F(SubprocessTest, SetWithLots) {
const unsigned kNumProcs = 1025;
rlimit rlim;
ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
if (rlim.rlim_cur < kNumProcs) {
printf("Raise [ulimit -n] above %u (currently %lu) to make this test go\n",
kNumProcs, rlim.rlim_cur);
return;
}
vector<Subprocess*> procs;
for (size_t i = 0; i < kNumProcs; ++i) {
Subprocess* subproc = subprocs_.Add("/bin/echo");
ASSERT_NE((Subprocess *) 0, subproc);
procs.push_back(subproc);
}
while (!subprocs_.running_.empty())
subprocs_.DoWork();
for (size_t i = 0; i < procs.size(); ++i) {
ASSERT_EQ(ExitSuccess, procs[i]->Finish());
ASSERT_NE("", procs[i]->GetOutput());
}
ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
}
#endif
#ifndef _WIN32
TEST_F(SubprocessTest, ReadStdin) {
Subprocess* subproc = subprocs_.Add("cat -");
while (!subproc->Done()) {
subprocs_.DoWork();
}
ASSERT_EQ(ExitSuccess, subproc->Finish());
ASSERT_EQ(1u, subprocs_.finished_.size());
}
#endif