Imported Upstream version 1.7.1
[platform/upstream/ninja.git] / src / subprocess_test.cc
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.
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
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
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
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
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
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
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
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
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
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
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     "whoami",
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 // 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;
224
225   // Make sure [ulimit -n] isn't going to stop us from working.
226   rlimit rlim;
227   ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
228   if (rlim.rlim_cur < kNumProcs) {
229     printf("Raise [ulimit -n] above %u (currently %lu) to make this test go\n",
230            kNumProcs, rlim.rlim_cur);
231     return;
232   }
233
234   vector<Subprocess*> procs;
235   for (size_t i = 0; i < kNumProcs; ++i) {
236     Subprocess* subproc = subprocs_.Add("/bin/echo");
237     ASSERT_NE((Subprocess *) 0, subproc);
238     procs.push_back(subproc);
239   }
240   while (!subprocs_.running_.empty())
241     subprocs_.DoWork();
242   for (size_t i = 0; i < procs.size(); ++i) {
243     ASSERT_EQ(ExitSuccess, procs[i]->Finish());
244     ASSERT_NE("", procs[i]->GetOutput());
245   }
246   ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
247 }
248 #endif  // !__APPLE__ && !_WIN32
249
250 // TODO: this test could work on Windows, just not sure how to simply
251 // read stdin.
252 #ifndef _WIN32
253 // Verify that a command that attempts to read stdin correctly thinks
254 // that stdin is closed.
255 TEST_F(SubprocessTest, ReadStdin) {
256   Subprocess* subproc = subprocs_.Add("cat -");
257   while (!subproc->Done()) {
258     subprocs_.DoWork();
259   }
260   ASSERT_EQ(ExitSuccess, subproc->Finish());
261   ASSERT_EQ(1u, subprocs_.finished_.size());
262 }
263 #endif  // _WIN32