1 // Copyright 2012 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "subprocess.h"
20 // SetWithLots need setrlimit.
23 #include <sys/resource.h>
30 const char* kSimpleCommand = "cmd /c dir \\";
32 const char* kSimpleCommand = "ls /";
35 struct SubprocessTest : public testing::Test {
36 SubprocessSet subprocs_;
39 } // anonymous namespace
41 // Run a command that fails and emits to stderr.
42 TEST_F(SubprocessTest, BadCommandStderr) {
43 Subprocess* subproc = subprocs_.Add("cmd /c ninja_no_such_command");
44 ASSERT_NE((Subprocess *) 0, subproc);
46 while (!subproc->Done()) {
47 // Pretend we discovered that stderr was ready for writing.
51 EXPECT_EQ(ExitFailure, subproc->Finish());
52 EXPECT_NE("", subproc->GetOutput());
55 // Run a command that does not exist
56 TEST_F(SubprocessTest, NoSuchCommand) {
57 Subprocess* subproc = subprocs_.Add("ninja_no_such_command");
58 ASSERT_NE((Subprocess *) 0, subproc);
60 while (!subproc->Done()) {
61 // Pretend we discovered that stderr was ready for writing.
65 EXPECT_EQ(ExitFailure, subproc->Finish());
66 EXPECT_NE("", subproc->GetOutput());
68 ASSERT_EQ("CreateProcess failed: The system cannot find the file "
69 "specified.\n", subproc->GetOutput());
75 TEST_F(SubprocessTest, InterruptChild) {
76 Subprocess* subproc = subprocs_.Add("kill -INT $$");
77 ASSERT_NE((Subprocess *) 0, subproc);
79 while (!subproc->Done()) {
83 EXPECT_EQ(ExitInterrupted, subproc->Finish());
86 TEST_F(SubprocessTest, InterruptParent) {
87 Subprocess* subproc = subprocs_.Add("kill -INT $PPID ; sleep 1");
88 ASSERT_NE((Subprocess *) 0, subproc);
90 while (!subproc->Done()) {
91 bool interrupted = subprocs_.DoWork();
96 ASSERT_FALSE("We should have been interrupted");
99 TEST_F(SubprocessTest, InterruptChildWithSigTerm) {
100 Subprocess* subproc = subprocs_.Add("kill -TERM $$");
101 ASSERT_NE((Subprocess *) 0, subproc);
103 while (!subproc->Done()) {
107 EXPECT_EQ(ExitInterrupted, subproc->Finish());
110 TEST_F(SubprocessTest, InterruptParentWithSigTerm) {
111 Subprocess* subproc = subprocs_.Add("kill -TERM $PPID ; sleep 1");
112 ASSERT_NE((Subprocess *) 0, subproc);
114 while (!subproc->Done()) {
115 bool interrupted = subprocs_.DoWork();
120 ASSERT_FALSE("We should have been interrupted");
123 TEST_F(SubprocessTest, InterruptChildWithSigHup) {
124 Subprocess* subproc = subprocs_.Add("kill -HUP $$");
125 ASSERT_NE((Subprocess *) 0, subproc);
127 while (!subproc->Done()) {
131 EXPECT_EQ(ExitInterrupted, subproc->Finish());
134 TEST_F(SubprocessTest, InterruptParentWithSigHup) {
135 Subprocess* subproc = subprocs_.Add("kill -HUP $PPID ; sleep 1");
136 ASSERT_NE((Subprocess *) 0, subproc);
138 while (!subproc->Done()) {
139 bool interrupted = subprocs_.DoWork();
144 ASSERT_FALSE("We should have been interrupted");
147 TEST_F(SubprocessTest, Console) {
148 // Skip test if we don't have the console ourselves.
149 if (isatty(0) && isatty(1) && isatty(2)) {
150 Subprocess* subproc =
151 subprocs_.Add("test -t 0 -a -t 1 -a -t 2", /*use_console=*/true);
152 ASSERT_NE((Subprocess*)0, subproc);
154 while (!subproc->Done()) {
158 EXPECT_EQ(ExitSuccess, subproc->Finish());
164 TEST_F(SubprocessTest, SetWithSingle) {
165 Subprocess* subproc = subprocs_.Add(kSimpleCommand);
166 ASSERT_NE((Subprocess *) 0, subproc);
168 while (!subproc->Done()) {
171 ASSERT_EQ(ExitSuccess, subproc->Finish());
172 ASSERT_NE("", subproc->GetOutput());
174 ASSERT_EQ(1u, subprocs_.finished_.size());
177 TEST_F(SubprocessTest, SetWithMulti) {
178 Subprocess* processes[3];
179 const char* kCommands[3] = {
190 for (int i = 0; i < 3; ++i) {
191 processes[i] = subprocs_.Add(kCommands[i]);
192 ASSERT_NE((Subprocess *) 0, processes[i]);
195 ASSERT_EQ(3u, subprocs_.running_.size());
196 for (int i = 0; i < 3; ++i) {
197 ASSERT_FALSE(processes[i]->Done());
198 ASSERT_EQ("", processes[i]->GetOutput());
201 while (!processes[0]->Done() || !processes[1]->Done() ||
202 !processes[2]->Done()) {
203 ASSERT_GT(subprocs_.running_.size(), 0u);
207 ASSERT_EQ(0u, subprocs_.running_.size());
208 ASSERT_EQ(3u, subprocs_.finished_.size());
210 for (int i = 0; i < 3; ++i) {
211 ASSERT_EQ(ExitSuccess, processes[i]->Finish());
212 ASSERT_NE("", processes[i]->GetOutput());
217 // OS X's process limit is less than 1025 by default
218 // (|sysctl kern.maxprocperuid| is 709 on 10.7 and 10.8 and less prior to that).
219 #if !defined(__APPLE__) && !defined(_WIN32)
220 TEST_F(SubprocessTest, SetWithLots) {
221 // Arbitrary big number; needs to be over 1024 to confirm we're no longer
222 // hostage to pselect.
223 const unsigned kNumProcs = 1025;
225 // Make sure [ulimit -n] isn't going to stop us from working.
227 ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
228 if (rlim.rlim_cur < kNumProcs) {
229 printf("Raise [ulimit -n] well above %u (currently %lu) to make this test go\n", kNumProcs, rlim.rlim_cur);
233 vector<Subprocess*> procs;
234 for (size_t i = 0; i < kNumProcs; ++i) {
235 Subprocess* subproc = subprocs_.Add("/bin/echo");
236 ASSERT_NE((Subprocess *) 0, subproc);
237 procs.push_back(subproc);
239 while (!subprocs_.running_.empty())
241 for (size_t i = 0; i < procs.size(); ++i) {
242 ASSERT_EQ(ExitSuccess, procs[i]->Finish());
243 ASSERT_NE("", procs[i]->GetOutput());
245 ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
247 #endif // !__APPLE__ && !_WIN32
249 // TODO: this test could work on Windows, just not sure how to simply
252 // Verify that a command that attempts to read stdin correctly thinks
253 // that stdin is closed.
254 TEST_F(SubprocessTest, ReadStdin) {
255 Subprocess* subproc = subprocs_.Add("cat -");
256 while (!subproc->Done()) {
259 ASSERT_EQ(ExitSuccess, subproc->Finish());
260 ASSERT_EQ(1u, subprocs_.finished_.size());