• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
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
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14 
15 #include "subprocess.h"
16 
17 #include "test.h"
18 
19 #ifndef _WIN32
20 // SetWithLots need setrlimit.
21 #include <stdio.h>
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 #include <unistd.h>
25 #endif
26 
27 namespace {
28 
29 #ifdef _WIN32
30 const char* kSimpleCommand = "cmd /c dir \\";
31 #else
32 const char* kSimpleCommand = "ls /";
33 #endif
34 
35 struct SubprocessTest : public testing::Test {
36   SubprocessSet subprocs_;
37 };
38 
39 }  // anonymous namespace
40 
41 // Run a command that fails and emits to stderr.
TEST_F(SubprocessTest,BadCommandStderr)42 TEST_F(SubprocessTest, BadCommandStderr) {
43   Subprocess* subproc = subprocs_.Add("cmd /c ninja_no_such_command");
44   ASSERT_NE((Subprocess *) 0, subproc);
45 
46   while (!subproc->Done()) {
47     // Pretend we discovered that stderr was ready for writing.
48     subprocs_.DoWork();
49   }
50 
51   EXPECT_EQ(ExitFailure, subproc->Finish());
52   EXPECT_NE("", subproc->GetOutput());
53 }
54 
55 // Run a command that does not exist
TEST_F(SubprocessTest,NoSuchCommand)56 TEST_F(SubprocessTest, NoSuchCommand) {
57   Subprocess* subproc = subprocs_.Add("ninja_no_such_command");
58   ASSERT_NE((Subprocess *) 0, subproc);
59 
60   while (!subproc->Done()) {
61     // Pretend we discovered that stderr was ready for writing.
62     subprocs_.DoWork();
63   }
64 
65   EXPECT_EQ(ExitFailure, subproc->Finish());
66   EXPECT_NE("", subproc->GetOutput());
67 #ifdef _WIN32
68   ASSERT_EQ("CreateProcess failed: The system cannot find the file "
69             "specified.\n", subproc->GetOutput());
70 #endif
71 }
72 
73 #ifndef _WIN32
74 
TEST_F(SubprocessTest,InterruptChild)75 TEST_F(SubprocessTest, InterruptChild) {
76   Subprocess* subproc = subprocs_.Add("kill -INT $$");
77   ASSERT_NE((Subprocess *) 0, subproc);
78 
79   while (!subproc->Done()) {
80     subprocs_.DoWork();
81   }
82 
83   EXPECT_EQ(ExitInterrupted, subproc->Finish());
84 }
85 
TEST_F(SubprocessTest,InterruptParent)86 TEST_F(SubprocessTest, InterruptParent) {
87   Subprocess* subproc = subprocs_.Add("kill -INT $PPID ; sleep 1");
88   ASSERT_NE((Subprocess *) 0, subproc);
89 
90   while (!subproc->Done()) {
91     bool interrupted = subprocs_.DoWork();
92     if (interrupted)
93       return;
94   }
95 
96   ASSERT_FALSE("We should have been interrupted");
97 }
98 
TEST_F(SubprocessTest,InterruptChildWithSigTerm)99 TEST_F(SubprocessTest, InterruptChildWithSigTerm) {
100   Subprocess* subproc = subprocs_.Add("kill -TERM $$");
101   ASSERT_NE((Subprocess *) 0, subproc);
102 
103   while (!subproc->Done()) {
104     subprocs_.DoWork();
105   }
106 
107   EXPECT_EQ(ExitInterrupted, subproc->Finish());
108 }
109 
TEST_F(SubprocessTest,InterruptParentWithSigTerm)110 TEST_F(SubprocessTest, InterruptParentWithSigTerm) {
111   Subprocess* subproc = subprocs_.Add("kill -TERM $PPID ; sleep 1");
112   ASSERT_NE((Subprocess *) 0, subproc);
113 
114   while (!subproc->Done()) {
115     bool interrupted = subprocs_.DoWork();
116     if (interrupted)
117       return;
118   }
119 
120   ASSERT_FALSE("We should have been interrupted");
121 }
122 
TEST_F(SubprocessTest,InterruptChildWithSigHup)123 TEST_F(SubprocessTest, InterruptChildWithSigHup) {
124   Subprocess* subproc = subprocs_.Add("kill -HUP $$");
125   ASSERT_NE((Subprocess *) 0, subproc);
126 
127   while (!subproc->Done()) {
128     subprocs_.DoWork();
129   }
130 
131   EXPECT_EQ(ExitInterrupted, subproc->Finish());
132 }
133 
TEST_F(SubprocessTest,InterruptParentWithSigHup)134 TEST_F(SubprocessTest, InterruptParentWithSigHup) {
135   Subprocess* subproc = subprocs_.Add("kill -HUP $PPID ; sleep 1");
136   ASSERT_NE((Subprocess *) 0, subproc);
137 
138   while (!subproc->Done()) {
139     bool interrupted = subprocs_.DoWork();
140     if (interrupted)
141       return;
142   }
143 
144   ASSERT_FALSE("We should have been interrupted");
145 }
146 
TEST_F(SubprocessTest,Console)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);
153 
154     while (!subproc->Done()) {
155       subprocs_.DoWork();
156     }
157 
158     EXPECT_EQ(ExitSuccess, subproc->Finish());
159   }
160 }
161 
162 #endif
163 
TEST_F(SubprocessTest,SetWithSingle)164 TEST_F(SubprocessTest, SetWithSingle) {
165   Subprocess* subproc = subprocs_.Add(kSimpleCommand);
166   ASSERT_NE((Subprocess *) 0, subproc);
167 
168   while (!subproc->Done()) {
169     subprocs_.DoWork();
170   }
171   ASSERT_EQ(ExitSuccess, subproc->Finish());
172   ASSERT_NE("", subproc->GetOutput());
173 
174   ASSERT_EQ(1u, subprocs_.finished_.size());
175 }
176 
TEST_F(SubprocessTest,SetWithMulti)177 TEST_F(SubprocessTest, SetWithMulti) {
178   Subprocess* processes[3];
179   const char* kCommands[3] = {
180     kSimpleCommand,
181 #ifdef _WIN32
182     "cmd /c echo hi",
183     "cmd /c time /t",
184 #else
185     "id -u",
186     "pwd",
187 #endif
188   };
189 
190   for (int i = 0; i < 3; ++i) {
191     processes[i] = subprocs_.Add(kCommands[i]);
192     ASSERT_NE((Subprocess *) 0, processes[i]);
193   }
194 
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());
199   }
200 
201   while (!processes[0]->Done() || !processes[1]->Done() ||
202          !processes[2]->Done()) {
203     ASSERT_GT(subprocs_.running_.size(), 0u);
204     subprocs_.DoWork();
205   }
206 
207   ASSERT_EQ(0u, subprocs_.running_.size());
208   ASSERT_EQ(3u, subprocs_.finished_.size());
209 
210   for (int i = 0; i < 3; ++i) {
211     ASSERT_EQ(ExitSuccess, processes[i]->Finish());
212     ASSERT_NE("", processes[i]->GetOutput());
213     delete processes[i];
214   }
215 }
216 
217 #if defined(USE_PPOLL)
TEST_F(SubprocessTest,SetWithLots)218 TEST_F(SubprocessTest, SetWithLots) {
219   // Arbitrary big number; needs to be over 1024 to confirm we're no longer
220   // hostage to pselect.
221   const unsigned kNumProcs = 1025;
222 
223   // Make sure [ulimit -n] isn't going to stop us from working.
224   rlimit rlim;
225   ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
226   if (rlim.rlim_cur < kNumProcs) {
227     printf("Raise [ulimit -n] above %u (currently %lu) to make this test go\n",
228            kNumProcs, rlim.rlim_cur);
229     return;
230   }
231 
232   vector<Subprocess*> procs;
233   for (size_t i = 0; i < kNumProcs; ++i) {
234     Subprocess* subproc = subprocs_.Add("/bin/echo");
235     ASSERT_NE((Subprocess *) 0, subproc);
236     procs.push_back(subproc);
237   }
238   while (!subprocs_.running_.empty())
239     subprocs_.DoWork();
240   for (size_t i = 0; i < procs.size(); ++i) {
241     ASSERT_EQ(ExitSuccess, procs[i]->Finish());
242     ASSERT_NE("", procs[i]->GetOutput());
243   }
244   ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
245 }
246 #endif  // !__APPLE__ && !_WIN32
247 
248 // TODO: this test could work on Windows, just not sure how to simply
249 // read stdin.
250 #ifndef _WIN32
251 // Verify that a command that attempts to read stdin correctly thinks
252 // that stdin is closed.
TEST_F(SubprocessTest,ReadStdin)253 TEST_F(SubprocessTest, ReadStdin) {
254   Subprocess* subproc = subprocs_.Add("cat -");
255   while (!subproc->Done()) {
256     subprocs_.DoWork();
257   }
258   ASSERT_EQ(ExitSuccess, subproc->Finish());
259   ASSERT_EQ(1u, subprocs_.finished_.size());
260 }
261 #endif  // _WIN32
262