1 // Copyright 2011 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 "build.h"
16
17 #include <assert.h>
18
19 #include "build_log.h"
20 #include "deps_log.h"
21 #include "graph.h"
22 #include "status.h"
23 #include "test.h"
24
25 using namespace std;
26
27 struct CompareEdgesByOutput {
cmpCompareEdgesByOutput28 static bool cmp(const Edge* a, const Edge* b) {
29 return a->outputs_[0]->path() < b->outputs_[0]->path();
30 }
31 };
32
33 /// Fixture for tests involving Plan.
34 // Though Plan doesn't use State, it's useful to have one around
35 // to create Nodes and Edges.
36 struct PlanTest : public StateTestWithBuiltinRules {
37 Plan plan_;
38
39 /// Because FindWork does not return Edges in any sort of predictable order,
40 // provide a means to get available Edges in order and in a format which is
41 // easy to write tests around.
FindWorkSortedPlanTest42 void FindWorkSorted(deque<Edge*>* ret, int count) {
43 for (int i = 0; i < count; ++i) {
44 ASSERT_TRUE(plan_.more_to_do());
45 Edge* edge = plan_.FindWork();
46 ASSERT_TRUE(edge);
47 ret->push_back(edge);
48 }
49 ASSERT_FALSE(plan_.FindWork());
50 sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp);
51 }
52
53 void TestPoolWithDepthOne(const char *test_case);
54 };
55
TEST_F(PlanTest,Basic)56 TEST_F(PlanTest, Basic) {
57 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
58 "build out: cat mid\n"
59 "build mid: cat in\n"));
60 GetNode("mid")->MarkDirty();
61 GetNode("out")->MarkDirty();
62 string err;
63 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
64 ASSERT_EQ("", err);
65 ASSERT_TRUE(plan_.more_to_do());
66
67 Edge* edge = plan_.FindWork();
68 ASSERT_TRUE(edge);
69 ASSERT_EQ("in", edge->inputs_[0]->path());
70 ASSERT_EQ("mid", edge->outputs_[0]->path());
71
72 ASSERT_FALSE(plan_.FindWork());
73
74 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
75 ASSERT_EQ("", err);
76
77 edge = plan_.FindWork();
78 ASSERT_TRUE(edge);
79 ASSERT_EQ("mid", edge->inputs_[0]->path());
80 ASSERT_EQ("out", edge->outputs_[0]->path());
81
82 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
83 ASSERT_EQ("", err);
84
85 ASSERT_FALSE(plan_.more_to_do());
86 edge = plan_.FindWork();
87 ASSERT_EQ(0, edge);
88 }
89
90 // Test that two outputs from one rule can be handled as inputs to the next.
TEST_F(PlanTest,DoubleOutputDirect)91 TEST_F(PlanTest, DoubleOutputDirect) {
92 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
93 "build out: cat mid1 mid2\n"
94 "build mid1 mid2: cat in\n"));
95 GetNode("mid1")->MarkDirty();
96 GetNode("mid2")->MarkDirty();
97 GetNode("out")->MarkDirty();
98
99 string err;
100 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
101 ASSERT_EQ("", err);
102 ASSERT_TRUE(plan_.more_to_do());
103
104 Edge* edge;
105 edge = plan_.FindWork();
106 ASSERT_TRUE(edge); // cat in
107 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
108 ASSERT_EQ("", err);
109
110 edge = plan_.FindWork();
111 ASSERT_TRUE(edge); // cat mid1 mid2
112 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
113 ASSERT_EQ("", err);
114
115 edge = plan_.FindWork();
116 ASSERT_FALSE(edge); // done
117 }
118
119 // Test that two outputs from one rule can eventually be routed to another.
TEST_F(PlanTest,DoubleOutputIndirect)120 TEST_F(PlanTest, DoubleOutputIndirect) {
121 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
122 "build out: cat b1 b2\n"
123 "build b1: cat a1\n"
124 "build b2: cat a2\n"
125 "build a1 a2: cat in\n"));
126 GetNode("a1")->MarkDirty();
127 GetNode("a2")->MarkDirty();
128 GetNode("b1")->MarkDirty();
129 GetNode("b2")->MarkDirty();
130 GetNode("out")->MarkDirty();
131 string err;
132 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
133 ASSERT_EQ("", err);
134 ASSERT_TRUE(plan_.more_to_do());
135
136 Edge* edge;
137 edge = plan_.FindWork();
138 ASSERT_TRUE(edge); // cat in
139 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
140 ASSERT_EQ("", err);
141
142 edge = plan_.FindWork();
143 ASSERT_TRUE(edge); // cat a1
144 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
145 ASSERT_EQ("", err);
146
147 edge = plan_.FindWork();
148 ASSERT_TRUE(edge); // cat a2
149 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
150 ASSERT_EQ("", err);
151
152 edge = plan_.FindWork();
153 ASSERT_TRUE(edge); // cat b1 b2
154 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
155 ASSERT_EQ("", err);
156
157 edge = plan_.FindWork();
158 ASSERT_FALSE(edge); // done
159 }
160
161 // Test that two edges from one output can both execute.
TEST_F(PlanTest,DoubleDependent)162 TEST_F(PlanTest, DoubleDependent) {
163 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
164 "build out: cat a1 a2\n"
165 "build a1: cat mid\n"
166 "build a2: cat mid\n"
167 "build mid: cat in\n"));
168 GetNode("mid")->MarkDirty();
169 GetNode("a1")->MarkDirty();
170 GetNode("a2")->MarkDirty();
171 GetNode("out")->MarkDirty();
172
173 string err;
174 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
175 ASSERT_EQ("", err);
176 ASSERT_TRUE(plan_.more_to_do());
177
178 Edge* edge;
179 edge = plan_.FindWork();
180 ASSERT_TRUE(edge); // cat in
181 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
182 ASSERT_EQ("", err);
183
184 edge = plan_.FindWork();
185 ASSERT_TRUE(edge); // cat mid
186 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
187 ASSERT_EQ("", err);
188
189 edge = plan_.FindWork();
190 ASSERT_TRUE(edge); // cat mid
191 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
192 ASSERT_EQ("", err);
193
194 edge = plan_.FindWork();
195 ASSERT_TRUE(edge); // cat a1 a2
196 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
197 ASSERT_EQ("", err);
198
199 edge = plan_.FindWork();
200 ASSERT_FALSE(edge); // done
201 }
202
TestPoolWithDepthOne(const char * test_case)203 void PlanTest::TestPoolWithDepthOne(const char* test_case) {
204 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, test_case));
205 GetNode("out1")->MarkDirty();
206 GetNode("out2")->MarkDirty();
207 string err;
208 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
209 ASSERT_EQ("", err);
210 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
211 ASSERT_EQ("", err);
212 ASSERT_TRUE(plan_.more_to_do());
213
214 Edge* edge = plan_.FindWork();
215 ASSERT_TRUE(edge);
216 ASSERT_EQ("in", edge->inputs_[0]->path());
217 ASSERT_EQ("out1", edge->outputs_[0]->path());
218
219 // This will be false since poolcat is serialized
220 ASSERT_FALSE(plan_.FindWork());
221
222 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
223 ASSERT_EQ("", err);
224
225 edge = plan_.FindWork();
226 ASSERT_TRUE(edge);
227 ASSERT_EQ("in", edge->inputs_[0]->path());
228 ASSERT_EQ("out2", edge->outputs_[0]->path());
229
230 ASSERT_FALSE(plan_.FindWork());
231
232 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
233 ASSERT_EQ("", err);
234
235 ASSERT_FALSE(plan_.more_to_do());
236 edge = plan_.FindWork();
237 ASSERT_EQ(0, edge);
238 }
239
TEST_F(PlanTest,PoolWithDepthOne)240 TEST_F(PlanTest, PoolWithDepthOne) {
241 TestPoolWithDepthOne(
242 "pool foobar\n"
243 " depth = 1\n"
244 "rule poolcat\n"
245 " command = cat $in > $out\n"
246 " pool = foobar\n"
247 "build out1: poolcat in\n"
248 "build out2: poolcat in\n");
249 }
250
TEST_F(PlanTest,ConsolePool)251 TEST_F(PlanTest, ConsolePool) {
252 TestPoolWithDepthOne(
253 "rule poolcat\n"
254 " command = cat $in > $out\n"
255 " pool = console\n"
256 "build out1: poolcat in\n"
257 "build out2: poolcat in\n");
258 }
259
TEST_F(PlanTest,PoolsWithDepthTwo)260 TEST_F(PlanTest, PoolsWithDepthTwo) {
261 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
262 "pool foobar\n"
263 " depth = 2\n"
264 "pool bazbin\n"
265 " depth = 2\n"
266 "rule foocat\n"
267 " command = cat $in > $out\n"
268 " pool = foobar\n"
269 "rule bazcat\n"
270 " command = cat $in > $out\n"
271 " pool = bazbin\n"
272 "build out1: foocat in\n"
273 "build out2: foocat in\n"
274 "build out3: foocat in\n"
275 "build outb1: bazcat in\n"
276 "build outb2: bazcat in\n"
277 "build outb3: bazcat in\n"
278 " pool =\n"
279 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
280 ));
281 // Mark all the out* nodes dirty
282 for (int i = 0; i < 3; ++i) {
283 GetNode("out" + string(1, '1' + static_cast<char>(i)))->MarkDirty();
284 GetNode("outb" + string(1, '1' + static_cast<char>(i)))->MarkDirty();
285 }
286 GetNode("allTheThings")->MarkDirty();
287
288 string err;
289 EXPECT_TRUE(plan_.AddTarget(GetNode("allTheThings"), &err));
290 ASSERT_EQ("", err);
291
292 deque<Edge*> edges;
293 FindWorkSorted(&edges, 5);
294
295 for (int i = 0; i < 4; ++i) {
296 Edge *edge = edges[i];
297 ASSERT_EQ("in", edge->inputs_[0]->path());
298 string base_name(i < 2 ? "out" : "outb");
299 ASSERT_EQ(base_name + string(1, '1' + (i % 2)), edge->outputs_[0]->path());
300 }
301
302 // outb3 is exempt because it has an empty pool
303 Edge* edge = edges[4];
304 ASSERT_TRUE(edge);
305 ASSERT_EQ("in", edge->inputs_[0]->path());
306 ASSERT_EQ("outb3", edge->outputs_[0]->path());
307
308 // finish out1
309 plan_.EdgeFinished(edges.front(), Plan::kEdgeSucceeded, &err);
310 ASSERT_EQ("", err);
311 edges.pop_front();
312
313 // out3 should be available
314 Edge* out3 = plan_.FindWork();
315 ASSERT_TRUE(out3);
316 ASSERT_EQ("in", out3->inputs_[0]->path());
317 ASSERT_EQ("out3", out3->outputs_[0]->path());
318
319 ASSERT_FALSE(plan_.FindWork());
320
321 plan_.EdgeFinished(out3, Plan::kEdgeSucceeded, &err);
322 ASSERT_EQ("", err);
323
324 ASSERT_FALSE(plan_.FindWork());
325
326 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
327 plan_.EdgeFinished(*it, Plan::kEdgeSucceeded, &err);
328 ASSERT_EQ("", err);
329 }
330
331 Edge* last = plan_.FindWork();
332 ASSERT_TRUE(last);
333 ASSERT_EQ("allTheThings", last->outputs_[0]->path());
334
335 plan_.EdgeFinished(last, Plan::kEdgeSucceeded, &err);
336 ASSERT_EQ("", err);
337
338 ASSERT_FALSE(plan_.more_to_do());
339 ASSERT_FALSE(plan_.FindWork());
340 }
341
TEST_F(PlanTest,PoolWithRedundantEdges)342 TEST_F(PlanTest, PoolWithRedundantEdges) {
343 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
344 "pool compile\n"
345 " depth = 1\n"
346 "rule gen_foo\n"
347 " command = touch foo.cpp\n"
348 "rule gen_bar\n"
349 " command = touch bar.cpp\n"
350 "rule echo\n"
351 " command = echo $out > $out\n"
352 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
353 " pool = compile\n"
354 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
355 " pool = compile\n"
356 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
357 "build foo.cpp: gen_foo\n"
358 "build bar.cpp: gen_bar\n"
359 "build all: phony libfoo.a\n"));
360 GetNode("foo.cpp")->MarkDirty();
361 GetNode("foo.cpp.obj")->MarkDirty();
362 GetNode("bar.cpp")->MarkDirty();
363 GetNode("bar.cpp.obj")->MarkDirty();
364 GetNode("libfoo.a")->MarkDirty();
365 GetNode("all")->MarkDirty();
366 string err;
367 EXPECT_TRUE(plan_.AddTarget(GetNode("all"), &err));
368 ASSERT_EQ("", err);
369 ASSERT_TRUE(plan_.more_to_do());
370
371 Edge* edge = NULL;
372
373 deque<Edge*> initial_edges;
374 FindWorkSorted(&initial_edges, 2);
375
376 edge = initial_edges[1]; // Foo first
377 ASSERT_EQ("foo.cpp", edge->outputs_[0]->path());
378 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
379 ASSERT_EQ("", err);
380
381 edge = plan_.FindWork();
382 ASSERT_TRUE(edge);
383 ASSERT_FALSE(plan_.FindWork());
384 ASSERT_EQ("foo.cpp", edge->inputs_[0]->path());
385 ASSERT_EQ("foo.cpp", edge->inputs_[1]->path());
386 ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path());
387 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
388 ASSERT_EQ("", err);
389
390 edge = initial_edges[0]; // Now for bar
391 ASSERT_EQ("bar.cpp", edge->outputs_[0]->path());
392 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
393 ASSERT_EQ("", err);
394
395 edge = plan_.FindWork();
396 ASSERT_TRUE(edge);
397 ASSERT_FALSE(plan_.FindWork());
398 ASSERT_EQ("bar.cpp", edge->inputs_[0]->path());
399 ASSERT_EQ("bar.cpp", edge->inputs_[1]->path());
400 ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path());
401 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
402 ASSERT_EQ("", err);
403
404 edge = plan_.FindWork();
405 ASSERT_TRUE(edge);
406 ASSERT_FALSE(plan_.FindWork());
407 ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path());
408 ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path());
409 ASSERT_EQ("libfoo.a", edge->outputs_[0]->path());
410 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
411 ASSERT_EQ("", err);
412
413 edge = plan_.FindWork();
414 ASSERT_TRUE(edge);
415 ASSERT_FALSE(plan_.FindWork());
416 ASSERT_EQ("libfoo.a", edge->inputs_[0]->path());
417 ASSERT_EQ("all", edge->outputs_[0]->path());
418 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
419 ASSERT_EQ("", err);
420
421 edge = plan_.FindWork();
422 ASSERT_FALSE(edge);
423 ASSERT_FALSE(plan_.more_to_do());
424 }
425
TEST_F(PlanTest,PoolWithFailingEdge)426 TEST_F(PlanTest, PoolWithFailingEdge) {
427 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
428 "pool foobar\n"
429 " depth = 1\n"
430 "rule poolcat\n"
431 " command = cat $in > $out\n"
432 " pool = foobar\n"
433 "build out1: poolcat in\n"
434 "build out2: poolcat in\n"));
435 GetNode("out1")->MarkDirty();
436 GetNode("out2")->MarkDirty();
437 string err;
438 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
439 ASSERT_EQ("", err);
440 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
441 ASSERT_EQ("", err);
442 ASSERT_TRUE(plan_.more_to_do());
443
444 Edge* edge = plan_.FindWork();
445 ASSERT_TRUE(edge);
446 ASSERT_EQ("in", edge->inputs_[0]->path());
447 ASSERT_EQ("out1", edge->outputs_[0]->path());
448
449 // This will be false since poolcat is serialized
450 ASSERT_FALSE(plan_.FindWork());
451
452 plan_.EdgeFinished(edge, Plan::kEdgeFailed, &err);
453 ASSERT_EQ("", err);
454
455 edge = plan_.FindWork();
456 ASSERT_TRUE(edge);
457 ASSERT_EQ("in", edge->inputs_[0]->path());
458 ASSERT_EQ("out2", edge->outputs_[0]->path());
459
460 ASSERT_FALSE(plan_.FindWork());
461
462 plan_.EdgeFinished(edge, Plan::kEdgeFailed, &err);
463 ASSERT_EQ("", err);
464
465 ASSERT_TRUE(plan_.more_to_do()); // Jobs have failed
466 edge = plan_.FindWork();
467 ASSERT_EQ(0, edge);
468 }
469
470 /// Fake implementation of CommandRunner, useful for tests.
471 struct FakeCommandRunner : public CommandRunner {
FakeCommandRunnerFakeCommandRunner472 explicit FakeCommandRunner(VirtualFileSystem* fs) :
473 max_active_edges_(1), fs_(fs) {}
474
475 // CommandRunner impl
476 virtual bool CanRunMore() const;
477 virtual bool StartCommand(Edge* edge);
478 virtual bool WaitForCommand(Result* result);
479 virtual vector<Edge*> GetActiveEdges();
480 virtual void Abort();
481
482 vector<string> commands_ran_;
483 vector<Edge*> active_edges_;
484 size_t max_active_edges_;
485 VirtualFileSystem* fs_;
486 };
487
488 struct BuildTest : public StateTestWithBuiltinRules, public BuildLogUser {
BuildTestBuildTest489 BuildTest() : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
490 builder_(&state_, config_, NULL, NULL, &fs_, &status_, 0) {
491 }
492
BuildTestBuildTest493 explicit BuildTest(DepsLog* log)
494 : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
495 builder_(&state_, config_, NULL, log, &fs_, &status_, 0) {}
496
SetUpBuildTest497 virtual void SetUp() {
498 StateTestWithBuiltinRules::SetUp();
499
500 builder_.command_runner_.reset(&command_runner_);
501 AssertParse(&state_,
502 "build cat1: cat in1\n"
503 "build cat2: cat in1 in2\n"
504 "build cat12: cat cat1 cat2\n");
505
506 fs_.Create("in1", "");
507 fs_.Create("in2", "");
508 }
509
~BuildTestBuildTest510 ~BuildTest() {
511 builder_.command_runner_.release();
512 }
513
IsPathDeadBuildTest514 virtual bool IsPathDead(StringPiece s) const { return false; }
515
516 /// Rebuild target in the 'working tree' (fs_).
517 /// State of command_runner_ and logs contents (if specified) ARE MODIFIED.
518 /// Handy to check for NOOP builds, and higher-level rebuild tests.
519 void RebuildTarget(const string& target, const char* manifest,
520 const char* log_path = NULL, const char* deps_path = NULL,
521 State* state = NULL);
522
523 // Mark a path dirty.
524 void Dirty(const string& path);
525
MakeConfigBuildTest526 BuildConfig MakeConfig() {
527 BuildConfig config;
528 config.verbosity = BuildConfig::QUIET;
529 return config;
530 }
531
532 BuildConfig config_;
533 FakeCommandRunner command_runner_;
534 VirtualFileSystem fs_;
535 StatusPrinter status_;
536 Builder builder_;
537 };
538
RebuildTarget(const string & target,const char * manifest,const char * log_path,const char * deps_path,State * state)539 void BuildTest::RebuildTarget(const string& target, const char* manifest,
540 const char* log_path, const char* deps_path,
541 State* state) {
542 State local_state, *pstate = &local_state;
543 if (state)
544 pstate = state;
545 ASSERT_NO_FATAL_FAILURE(AddCatRule(pstate));
546 AssertParse(pstate, manifest);
547
548 string err;
549 BuildLog build_log, *pbuild_log = NULL;
550 if (log_path) {
551 ASSERT_TRUE(build_log.Load(log_path, &err));
552 ASSERT_TRUE(build_log.OpenForWrite(log_path, *this, &err));
553 ASSERT_EQ("", err);
554 pbuild_log = &build_log;
555 }
556
557 DepsLog deps_log, *pdeps_log = NULL;
558 if (deps_path) {
559 ASSERT_TRUE(deps_log.Load(deps_path, pstate, &err));
560 ASSERT_TRUE(deps_log.OpenForWrite(deps_path, &err));
561 ASSERT_EQ("", err);
562 pdeps_log = &deps_log;
563 }
564
565 Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_, &status_, 0);
566 EXPECT_TRUE(builder.AddTarget(target, &err));
567
568 command_runner_.commands_ran_.clear();
569 builder.command_runner_.reset(&command_runner_);
570 if (!builder.AlreadyUpToDate()) {
571 bool build_res = builder.Build(&err);
572 EXPECT_TRUE(build_res);
573 }
574 builder.command_runner_.release();
575 }
576
CanRunMore() const577 bool FakeCommandRunner::CanRunMore() const {
578 return active_edges_.size() < max_active_edges_;
579 }
580
StartCommand(Edge * edge)581 bool FakeCommandRunner::StartCommand(Edge* edge) {
582 assert(active_edges_.size() < max_active_edges_);
583 assert(find(active_edges_.begin(), active_edges_.end(), edge)
584 == active_edges_.end());
585 commands_ran_.push_back(edge->EvaluateCommand());
586 if (edge->rule().name() == "cat" ||
587 edge->rule().name() == "cat_rsp" ||
588 edge->rule().name() == "cat_rsp_out" ||
589 edge->rule().name() == "cc" ||
590 edge->rule().name() == "cp_multi_msvc" ||
591 edge->rule().name() == "cp_multi_gcc" ||
592 edge->rule().name() == "touch" ||
593 edge->rule().name() == "touch-interrupt" ||
594 edge->rule().name() == "touch-fail-tick2") {
595 for (vector<Node*>::iterator out = edge->outputs_.begin();
596 out != edge->outputs_.end(); ++out) {
597 fs_->Create((*out)->path(), "");
598 }
599 } else if (edge->rule().name() == "true" ||
600 edge->rule().name() == "fail" ||
601 edge->rule().name() == "interrupt" ||
602 edge->rule().name() == "console") {
603 // Don't do anything.
604 } else if (edge->rule().name() == "cp") {
605 assert(!edge->inputs_.empty());
606 assert(edge->outputs_.size() == 1);
607 string content;
608 string err;
609 if (fs_->ReadFile(edge->inputs_[0]->path(), &content, &err) ==
610 DiskInterface::Okay)
611 fs_->WriteFile(edge->outputs_[0]->path(), content);
612 } else if (edge->rule().name() == "touch-implicit-dep-out") {
613 string dep = edge->GetBinding("test_dependency");
614 fs_->Create(dep, "");
615 fs_->Tick();
616 for (vector<Node*>::iterator out = edge->outputs_.begin();
617 out != edge->outputs_.end(); ++out) {
618 fs_->Create((*out)->path(), "");
619 }
620 } else if (edge->rule().name() == "touch-out-implicit-dep") {
621 string dep = edge->GetBinding("test_dependency");
622 for (vector<Node*>::iterator out = edge->outputs_.begin();
623 out != edge->outputs_.end(); ++out) {
624 fs_->Create((*out)->path(), "");
625 }
626 fs_->Tick();
627 fs_->Create(dep, "");
628 } else if (edge->rule().name() == "generate-depfile") {
629 string dep = edge->GetBinding("test_dependency");
630 string depfile = edge->GetUnescapedDepfile();
631 string contents;
632 for (vector<Node*>::iterator out = edge->outputs_.begin();
633 out != edge->outputs_.end(); ++out) {
634 contents += (*out)->path() + ": " + dep + "\n";
635 fs_->Create((*out)->path(), "");
636 }
637 fs_->Create(depfile, contents);
638 } else {
639 printf("unknown command\n");
640 return false;
641 }
642
643 active_edges_.push_back(edge);
644
645 // Allow tests to control the order by the name of the first output.
646 sort(active_edges_.begin(), active_edges_.end(),
647 CompareEdgesByOutput::cmp);
648
649 return true;
650 }
651
WaitForCommand(Result * result)652 bool FakeCommandRunner::WaitForCommand(Result* result) {
653 if (active_edges_.empty())
654 return false;
655
656 // All active edges were already completed immediately when started,
657 // so we can pick any edge here. Pick the last edge. Tests can
658 // control the order of edges by the name of the first output.
659 vector<Edge*>::iterator edge_iter = active_edges_.end() - 1;
660
661 Edge* edge = *edge_iter;
662 result->edge = edge;
663
664 if (edge->rule().name() == "interrupt" ||
665 edge->rule().name() == "touch-interrupt") {
666 result->status = ExitInterrupted;
667 return true;
668 }
669
670 if (edge->rule().name() == "console") {
671 if (edge->use_console())
672 result->status = ExitSuccess;
673 else
674 result->status = ExitFailure;
675 active_edges_.erase(edge_iter);
676 return true;
677 }
678
679 if (edge->rule().name() == "cp_multi_msvc") {
680 const std::string prefix = edge->GetBinding("msvc_deps_prefix");
681 for (std::vector<Node*>::iterator in = edge->inputs_.begin();
682 in != edge->inputs_.end(); ++in) {
683 result->output += prefix + (*in)->path() + '\n';
684 }
685 }
686
687 if (edge->rule().name() == "fail" ||
688 (edge->rule().name() == "touch-fail-tick2" && fs_->now_ == 2))
689 result->status = ExitFailure;
690 else
691 result->status = ExitSuccess;
692
693 // Provide a way for test cases to verify when an edge finishes that
694 // some other edge is still active. This is useful for test cases
695 // covering behavior involving multiple active edges.
696 const string& verify_active_edge = edge->GetBinding("verify_active_edge");
697 if (!verify_active_edge.empty()) {
698 bool verify_active_edge_found = false;
699 for (vector<Edge*>::iterator i = active_edges_.begin();
700 i != active_edges_.end(); ++i) {
701 if (!(*i)->outputs_.empty() &&
702 (*i)->outputs_[0]->path() == verify_active_edge) {
703 verify_active_edge_found = true;
704 }
705 }
706 EXPECT_TRUE(verify_active_edge_found);
707 }
708
709 active_edges_.erase(edge_iter);
710 return true;
711 }
712
GetActiveEdges()713 vector<Edge*> FakeCommandRunner::GetActiveEdges() {
714 return active_edges_;
715 }
716
Abort()717 void FakeCommandRunner::Abort() {
718 active_edges_.clear();
719 }
720
Dirty(const string & path)721 void BuildTest::Dirty(const string& path) {
722 Node* node = GetNode(path);
723 node->MarkDirty();
724
725 // If it's an input file, mark that we've already stat()ed it and
726 // it's missing.
727 if (!node->in_edge())
728 node->MarkMissing();
729 }
730
TEST_F(BuildTest,NoWork)731 TEST_F(BuildTest, NoWork) {
732 string err;
733 EXPECT_TRUE(builder_.AlreadyUpToDate());
734 }
735
TEST_F(BuildTest,OneStep)736 TEST_F(BuildTest, OneStep) {
737 // Given a dirty target with one ready input,
738 // we should rebuild the target.
739 Dirty("cat1");
740 string err;
741 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
742 ASSERT_EQ("", err);
743 EXPECT_TRUE(builder_.Build(&err));
744 ASSERT_EQ("", err);
745
746 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
747 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
748 }
749
TEST_F(BuildTest,OneStep2)750 TEST_F(BuildTest, OneStep2) {
751 // Given a target with one dirty input,
752 // we should rebuild the target.
753 Dirty("cat1");
754 string err;
755 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
756 ASSERT_EQ("", err);
757 EXPECT_TRUE(builder_.Build(&err));
758 EXPECT_EQ("", err);
759
760 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
761 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
762 }
763
TEST_F(BuildTest,TwoStep)764 TEST_F(BuildTest, TwoStep) {
765 string err;
766 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
767 ASSERT_EQ("", err);
768 EXPECT_TRUE(builder_.Build(&err));
769 EXPECT_EQ("", err);
770 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
771 // Depending on how the pointers work out, we could've ran
772 // the first two commands in either order.
773 EXPECT_TRUE((command_runner_.commands_ran_[0] == "cat in1 > cat1" &&
774 command_runner_.commands_ran_[1] == "cat in1 in2 > cat2") ||
775 (command_runner_.commands_ran_[1] == "cat in1 > cat1" &&
776 command_runner_.commands_ran_[0] == "cat in1 in2 > cat2"));
777
778 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
779
780 fs_.Tick();
781
782 // Modifying in2 requires rebuilding one intermediate file
783 // and the final file.
784 fs_.Create("in2", "");
785 state_.Reset();
786 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
787 ASSERT_EQ("", err);
788 EXPECT_TRUE(builder_.Build(&err));
789 ASSERT_EQ("", err);
790 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
791 EXPECT_EQ("cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
792 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
793 }
794
TEST_F(BuildTest,TwoOutputs)795 TEST_F(BuildTest, TwoOutputs) {
796 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
797 "rule touch\n"
798 " command = touch $out\n"
799 "build out1 out2: touch in.txt\n"));
800
801 fs_.Create("in.txt", "");
802
803 string err;
804 EXPECT_TRUE(builder_.AddTarget("out1", &err));
805 ASSERT_EQ("", err);
806 EXPECT_TRUE(builder_.Build(&err));
807 EXPECT_EQ("", err);
808 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
809 EXPECT_EQ("touch out1 out2", command_runner_.commands_ran_[0]);
810 }
811
TEST_F(BuildTest,ImplicitOutput)812 TEST_F(BuildTest, ImplicitOutput) {
813 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
814 "rule touch\n"
815 " command = touch $out $out.imp\n"
816 "build out | out.imp: touch in.txt\n"));
817 fs_.Create("in.txt", "");
818
819 string err;
820 EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
821 ASSERT_EQ("", err);
822 EXPECT_TRUE(builder_.Build(&err));
823 EXPECT_EQ("", err);
824 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
825 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[0]);
826 }
827
828 // Test case from
829 // https://github.com/ninja-build/ninja/issues/148
TEST_F(BuildTest,MultiOutIn)830 TEST_F(BuildTest, MultiOutIn) {
831 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
832 "rule touch\n"
833 " command = touch $out\n"
834 "build in1 otherfile: touch in\n"
835 "build out: touch in | in1\n"));
836
837 fs_.Create("in", "");
838 fs_.Tick();
839 fs_.Create("in1", "");
840
841 string err;
842 EXPECT_TRUE(builder_.AddTarget("out", &err));
843 ASSERT_EQ("", err);
844 EXPECT_TRUE(builder_.Build(&err));
845 EXPECT_EQ("", err);
846 }
847
TEST_F(BuildTest,Chain)848 TEST_F(BuildTest, Chain) {
849 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
850 "build c2: cat c1\n"
851 "build c3: cat c2\n"
852 "build c4: cat c3\n"
853 "build c5: cat c4\n"));
854
855 fs_.Create("c1", "");
856
857 string err;
858 EXPECT_TRUE(builder_.AddTarget("c5", &err));
859 ASSERT_EQ("", err);
860 EXPECT_TRUE(builder_.Build(&err));
861 EXPECT_EQ("", err);
862 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
863
864 err.clear();
865 command_runner_.commands_ran_.clear();
866 state_.Reset();
867 EXPECT_TRUE(builder_.AddTarget("c5", &err));
868 ASSERT_EQ("", err);
869 EXPECT_TRUE(builder_.AlreadyUpToDate());
870
871 fs_.Tick();
872
873 fs_.Create("c3", "");
874 err.clear();
875 command_runner_.commands_ran_.clear();
876 state_.Reset();
877 EXPECT_TRUE(builder_.AddTarget("c5", &err));
878 ASSERT_EQ("", err);
879 EXPECT_FALSE(builder_.AlreadyUpToDate());
880 EXPECT_TRUE(builder_.Build(&err));
881 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // 3->4, 4->5
882 }
883
TEST_F(BuildTest,MissingInput)884 TEST_F(BuildTest, MissingInput) {
885 // Input is referenced by build file, but no rule for it.
886 string err;
887 Dirty("in1");
888 EXPECT_FALSE(builder_.AddTarget("cat1", &err));
889 EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it",
890 err);
891 }
892
TEST_F(BuildTest,MissingTarget)893 TEST_F(BuildTest, MissingTarget) {
894 // Target is not referenced by build file.
895 string err;
896 EXPECT_FALSE(builder_.AddTarget("meow", &err));
897 EXPECT_EQ("unknown target: 'meow'", err);
898 }
899
TEST_F(BuildTest,MissingInputTarget)900 TEST_F(BuildTest, MissingInputTarget) {
901 // Target is a missing input file
902 string err;
903 Dirty("in1");
904 EXPECT_FALSE(builder_.AddTarget("in1", &err));
905 EXPECT_EQ("'in1' missing and no known rule to make it", err);
906 }
907
TEST_F(BuildTest,MakeDirs)908 TEST_F(BuildTest, MakeDirs) {
909 string err;
910
911 #ifdef _WIN32
912 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
913 "build subdir\\dir2\\file: cat in1\n"));
914 #else
915 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
916 "build subdir/dir2/file: cat in1\n"));
917 #endif
918 EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err));
919
920 EXPECT_EQ("", err);
921 EXPECT_TRUE(builder_.Build(&err));
922 ASSERT_EQ("", err);
923 ASSERT_EQ(2u, fs_.directories_made_.size());
924 EXPECT_EQ("subdir", fs_.directories_made_[0]);
925 EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
926 }
927
TEST_F(BuildTest,DepFileMissing)928 TEST_F(BuildTest, DepFileMissing) {
929 string err;
930 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
931 "rule cc\n command = cc $in\n depfile = $out.d\n"
932 "build fo$ o.o: cc foo.c\n"));
933 fs_.Create("foo.c", "");
934
935 EXPECT_TRUE(builder_.AddTarget("fo o.o", &err));
936 ASSERT_EQ("", err);
937 ASSERT_EQ(1u, fs_.files_read_.size());
938 EXPECT_EQ("fo o.o.d", fs_.files_read_[0]);
939 }
940
TEST_F(BuildTest,DepFileOK)941 TEST_F(BuildTest, DepFileOK) {
942 string err;
943 int orig_edges = state_.edges_.size();
944 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
945 "rule cc\n command = cc $in\n depfile = $out.d\n"
946 "build foo.o: cc foo.c\n"));
947 Edge* edge = state_.edges_.back();
948
949 fs_.Create("foo.c", "");
950 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
951 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
952 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
953 ASSERT_EQ("", err);
954 ASSERT_EQ(1u, fs_.files_read_.size());
955 EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
956
957 // Expect three new edges: one generating foo.o, and two more from
958 // loading the depfile.
959 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
960 // Expect our edge to now have three inputs: foo.c and two headers.
961 ASSERT_EQ(3u, edge->inputs_.size());
962
963 // Expect the command line we generate to only use the original input.
964 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
965 }
966
TEST_F(BuildTest,DepFileParseError)967 TEST_F(BuildTest, DepFileParseError) {
968 string err;
969 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
970 "rule cc\n command = cc $in\n depfile = $out.d\n"
971 "build foo.o: cc foo.c\n"));
972 fs_.Create("foo.c", "");
973 fs_.Create("foo.o.d", "randomtext\n");
974 EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
975 EXPECT_EQ("foo.o.d: expected ':' in depfile", err);
976 }
977
TEST_F(BuildTest,EncounterReadyTwice)978 TEST_F(BuildTest, EncounterReadyTwice) {
979 string err;
980 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
981 "rule touch\n"
982 " command = touch $out\n"
983 "build c: touch\n"
984 "build b: touch || c\n"
985 "build a: touch | b || c\n"));
986
987 vector<Edge*> c_out = GetNode("c")->out_edges();
988 ASSERT_EQ(2u, c_out.size());
989 EXPECT_EQ("b", c_out[0]->outputs_[0]->path());
990 EXPECT_EQ("a", c_out[1]->outputs_[0]->path());
991
992 fs_.Create("b", "");
993 EXPECT_TRUE(builder_.AddTarget("a", &err));
994 ASSERT_EQ("", err);
995
996 EXPECT_TRUE(builder_.Build(&err));
997 ASSERT_EQ("", err);
998 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
999 }
1000
TEST_F(BuildTest,OrderOnlyDeps)1001 TEST_F(BuildTest, OrderOnlyDeps) {
1002 string err;
1003 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1004 "rule cc\n command = cc $in\n depfile = $out.d\n"
1005 "build foo.o: cc foo.c || otherfile\n"));
1006 Edge* edge = state_.edges_.back();
1007
1008 fs_.Create("foo.c", "");
1009 fs_.Create("otherfile", "");
1010 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
1011 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1012 ASSERT_EQ("", err);
1013
1014 // One explicit, two implicit, one order only.
1015 ASSERT_EQ(4u, edge->inputs_.size());
1016 EXPECT_EQ(2, edge->implicit_deps_);
1017 EXPECT_EQ(1, edge->order_only_deps_);
1018 // Verify the inputs are in the order we expect
1019 // (explicit then implicit then orderonly).
1020 EXPECT_EQ("foo.c", edge->inputs_[0]->path());
1021 EXPECT_EQ("blah.h", edge->inputs_[1]->path());
1022 EXPECT_EQ("bar.h", edge->inputs_[2]->path());
1023 EXPECT_EQ("otherfile", edge->inputs_[3]->path());
1024
1025 // Expect the command line we generate to only use the original input.
1026 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
1027
1028 // explicit dep dirty, expect a rebuild.
1029 EXPECT_TRUE(builder_.Build(&err));
1030 ASSERT_EQ("", err);
1031 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1032
1033 fs_.Tick();
1034
1035 // Recreate the depfile, as it should have been deleted by the build.
1036 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
1037
1038 // implicit dep dirty, expect a rebuild.
1039 fs_.Create("blah.h", "");
1040 fs_.Create("bar.h", "");
1041 command_runner_.commands_ran_.clear();
1042 state_.Reset();
1043 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1044 EXPECT_TRUE(builder_.Build(&err));
1045 ASSERT_EQ("", err);
1046 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1047
1048 fs_.Tick();
1049
1050 // Recreate the depfile, as it should have been deleted by the build.
1051 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
1052
1053 // order only dep dirty, no rebuild.
1054 fs_.Create("otherfile", "");
1055 command_runner_.commands_ran_.clear();
1056 state_.Reset();
1057 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1058 EXPECT_EQ("", err);
1059 EXPECT_TRUE(builder_.AlreadyUpToDate());
1060
1061 // implicit dep missing, expect rebuild.
1062 fs_.RemoveFile("bar.h");
1063 command_runner_.commands_ran_.clear();
1064 state_.Reset();
1065 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1066 EXPECT_TRUE(builder_.Build(&err));
1067 ASSERT_EQ("", err);
1068 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1069 }
1070
TEST_F(BuildTest,RebuildOrderOnlyDeps)1071 TEST_F(BuildTest, RebuildOrderOnlyDeps) {
1072 string err;
1073 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1074 "rule cc\n command = cc $in\n"
1075 "rule true\n command = true\n"
1076 "build oo.h: cc oo.h.in\n"
1077 "build foo.o: cc foo.c || oo.h\n"));
1078
1079 fs_.Create("foo.c", "");
1080 fs_.Create("oo.h.in", "");
1081
1082 // foo.o and order-only dep dirty, build both.
1083 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1084 EXPECT_TRUE(builder_.Build(&err));
1085 ASSERT_EQ("", err);
1086 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1087
1088 // all clean, no rebuild.
1089 command_runner_.commands_ran_.clear();
1090 state_.Reset();
1091 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1092 EXPECT_EQ("", err);
1093 EXPECT_TRUE(builder_.AlreadyUpToDate());
1094
1095 // order-only dep missing, build it only.
1096 fs_.RemoveFile("oo.h");
1097 command_runner_.commands_ran_.clear();
1098 state_.Reset();
1099 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1100 EXPECT_TRUE(builder_.Build(&err));
1101 ASSERT_EQ("", err);
1102 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1103 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
1104
1105 fs_.Tick();
1106
1107 // order-only dep dirty, build it only.
1108 fs_.Create("oo.h.in", "");
1109 command_runner_.commands_ran_.clear();
1110 state_.Reset();
1111 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1112 EXPECT_TRUE(builder_.Build(&err));
1113 ASSERT_EQ("", err);
1114 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1115 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
1116 }
1117
1118 #ifdef _WIN32
TEST_F(BuildTest,DepFileCanonicalize)1119 TEST_F(BuildTest, DepFileCanonicalize) {
1120 string err;
1121 int orig_edges = state_.edges_.size();
1122 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1123 "rule cc\n command = cc $in\n depfile = $out.d\n"
1124 "build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
1125 Edge* edge = state_.edges_.back();
1126
1127 fs_.Create("x/y/z/foo.c", "");
1128 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
1129 // Note, different slashes from manifest.
1130 fs_.Create("gen/stuff\\things/foo.o.d",
1131 "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
1132 EXPECT_TRUE(builder_.AddTarget("gen/stuff/things/foo.o", &err));
1133 ASSERT_EQ("", err);
1134 ASSERT_EQ(1u, fs_.files_read_.size());
1135 // The depfile path does not get Canonicalize as it seems unnecessary.
1136 EXPECT_EQ("gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
1137
1138 // Expect three new edges: one generating foo.o, and two more from
1139 // loading the depfile.
1140 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
1141 // Expect our edge to now have three inputs: foo.c and two headers.
1142 ASSERT_EQ(3u, edge->inputs_.size());
1143
1144 // Expect the command line we generate to only use the original input, and
1145 // using the slashes from the manifest.
1146 ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
1147 }
1148 #endif
1149
TEST_F(BuildTest,Phony)1150 TEST_F(BuildTest, Phony) {
1151 string err;
1152 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1153 "build out: cat bar.cc\n"
1154 "build all: phony out\n"));
1155 fs_.Create("bar.cc", "");
1156
1157 EXPECT_TRUE(builder_.AddTarget("all", &err));
1158 ASSERT_EQ("", err);
1159
1160 // Only one command to run, because phony runs no command.
1161 EXPECT_FALSE(builder_.AlreadyUpToDate());
1162 EXPECT_TRUE(builder_.Build(&err));
1163 ASSERT_EQ("", err);
1164 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1165 }
1166
TEST_F(BuildTest,PhonyNoWork)1167 TEST_F(BuildTest, PhonyNoWork) {
1168 string err;
1169 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1170 "build out: cat bar.cc\n"
1171 "build all: phony out\n"));
1172 fs_.Create("bar.cc", "");
1173 fs_.Create("out", "");
1174
1175 EXPECT_TRUE(builder_.AddTarget("all", &err));
1176 ASSERT_EQ("", err);
1177 EXPECT_TRUE(builder_.AlreadyUpToDate());
1178 }
1179
1180 // Test a self-referencing phony. Ideally this should not work, but
1181 // ninja 1.7 and below tolerated and CMake 2.8.12.x and 3.0.x both
1182 // incorrectly produce it. We tolerate it for compatibility.
TEST_F(BuildTest,PhonySelfReference)1183 TEST_F(BuildTest, PhonySelfReference) {
1184 string err;
1185 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1186 "build a: phony a\n"));
1187
1188 EXPECT_TRUE(builder_.AddTarget("a", &err));
1189 ASSERT_EQ("", err);
1190 EXPECT_TRUE(builder_.AlreadyUpToDate());
1191 }
1192
1193 // There are 6 different cases for phony rules:
1194 //
1195 // 1. output edge does not exist, inputs are not real
1196 // 2. output edge does not exist, no inputs
1197 // 3. output edge does not exist, inputs are real, newest mtime is M
1198 // 4. output edge is real, inputs are not real
1199 // 5. output edge is real, no inputs
1200 // 6. output edge is real, inputs are real, newest mtime is M
1201 //
1202 // Expected results :
1203 // 1. Edge is marked as clean, mtime is newest mtime of dependents.
1204 // Touching inputs will cause dependents to rebuild.
1205 // 2. Edge is marked as dirty, causing dependent edges to always rebuild
1206 // 3. Edge is marked as clean, mtime is newest mtime of dependents.
1207 // Touching inputs will cause dependents to rebuild.
1208 // 4. Edge is marked as clean, mtime is newest mtime of dependents.
1209 // Touching inputs will cause dependents to rebuild.
1210 // 5. Edge is marked as dirty, causing dependent edges to always rebuild
1211 // 6. Edge is marked as clean, mtime is newest mtime of dependents.
1212 // Touching inputs will cause dependents to rebuild.
TestPhonyUseCase(BuildTest * t,int i)1213 void TestPhonyUseCase(BuildTest* t, int i) {
1214 State& state_ = t->state_;
1215 Builder& builder_ = t->builder_;
1216 FakeCommandRunner& command_runner_ = t->command_runner_;
1217 VirtualFileSystem& fs_ = t->fs_;
1218
1219 string err;
1220 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1221 "rule touch\n"
1222 " command = touch $out\n"
1223 "build notreal: phony blank\n"
1224 "build phony1: phony notreal\n"
1225 "build phony2: phony\n"
1226 "build phony3: phony blank\n"
1227 "build phony4: phony notreal\n"
1228 "build phony5: phony\n"
1229 "build phony6: phony blank\n"
1230 "\n"
1231 "build test1: touch phony1\n"
1232 "build test2: touch phony2\n"
1233 "build test3: touch phony3\n"
1234 "build test4: touch phony4\n"
1235 "build test5: touch phony5\n"
1236 "build test6: touch phony6\n"
1237 ));
1238
1239 // Set up test.
1240 builder_.command_runner_.release(); // BuildTest owns the CommandRunner
1241 builder_.command_runner_.reset(&command_runner_);
1242
1243 fs_.Create("blank", ""); // a "real" file
1244 EXPECT_TRUE(builder_.AddTarget("test1", &err));
1245 ASSERT_EQ("", err);
1246 EXPECT_TRUE(builder_.AddTarget("test2", &err));
1247 ASSERT_EQ("", err);
1248 EXPECT_TRUE(builder_.AddTarget("test3", &err));
1249 ASSERT_EQ("", err);
1250 EXPECT_TRUE(builder_.AddTarget("test4", &err));
1251 ASSERT_EQ("", err);
1252 EXPECT_TRUE(builder_.AddTarget("test5", &err));
1253 ASSERT_EQ("", err);
1254 EXPECT_TRUE(builder_.AddTarget("test6", &err));
1255 ASSERT_EQ("", err);
1256 EXPECT_TRUE(builder_.Build(&err));
1257 ASSERT_EQ("", err);
1258
1259 string ci;
1260 ci += static_cast<char>('0' + i);
1261
1262 // Tests 1, 3, 4, and 6 should rebuild when the input is updated.
1263 if (i != 2 && i != 5) {
1264 Node* testNode = t->GetNode("test" + ci);
1265 Node* phonyNode = t->GetNode("phony" + ci);
1266 Node* inputNode = t->GetNode("blank");
1267
1268 state_.Reset();
1269 TimeStamp startTime = fs_.now_;
1270
1271 // Build number 1
1272 EXPECT_TRUE(builder_.AddTarget("test" + ci, &err));
1273 ASSERT_EQ("", err);
1274 if (!builder_.AlreadyUpToDate())
1275 EXPECT_TRUE(builder_.Build(&err));
1276 ASSERT_EQ("", err);
1277
1278 // Touch the input file
1279 state_.Reset();
1280 command_runner_.commands_ran_.clear();
1281 fs_.Tick();
1282 fs_.Create("blank", ""); // a "real" file
1283 EXPECT_TRUE(builder_.AddTarget("test" + ci, &err));
1284 ASSERT_EQ("", err);
1285
1286 // Second build, expect testN edge to be rebuilt
1287 // and phonyN node's mtime to be updated.
1288 EXPECT_FALSE(builder_.AlreadyUpToDate());
1289 EXPECT_TRUE(builder_.Build(&err));
1290 ASSERT_EQ("", err);
1291 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1292 EXPECT_EQ(string("touch test") + ci, command_runner_.commands_ran_[0]);
1293 EXPECT_TRUE(builder_.AlreadyUpToDate());
1294
1295 TimeStamp inputTime = inputNode->mtime();
1296
1297 EXPECT_FALSE(phonyNode->exists());
1298 EXPECT_FALSE(phonyNode->dirty());
1299
1300 EXPECT_GT(phonyNode->mtime(), startTime);
1301 EXPECT_EQ(phonyNode->mtime(), inputTime);
1302 ASSERT_TRUE(testNode->Stat(&fs_, &err));
1303 EXPECT_TRUE(testNode->exists());
1304 EXPECT_GT(testNode->mtime(), startTime);
1305 } else {
1306 // Tests 2 and 5: Expect dependents to always rebuild.
1307
1308 state_.Reset();
1309 command_runner_.commands_ran_.clear();
1310 fs_.Tick();
1311 command_runner_.commands_ran_.clear();
1312 EXPECT_TRUE(builder_.AddTarget("test" + ci, &err));
1313 ASSERT_EQ("", err);
1314 EXPECT_FALSE(builder_.AlreadyUpToDate());
1315 EXPECT_TRUE(builder_.Build(&err));
1316 ASSERT_EQ("", err);
1317 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1318 EXPECT_EQ("touch test" + ci, command_runner_.commands_ran_[0]);
1319
1320 state_.Reset();
1321 command_runner_.commands_ran_.clear();
1322 EXPECT_TRUE(builder_.AddTarget("test" + ci, &err));
1323 ASSERT_EQ("", err);
1324 EXPECT_FALSE(builder_.AlreadyUpToDate());
1325 EXPECT_TRUE(builder_.Build(&err));
1326 ASSERT_EQ("", err);
1327 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1328 EXPECT_EQ("touch test" + ci, command_runner_.commands_ran_[0]);
1329 }
1330 }
1331
TEST_F(BuildTest,PhonyUseCase1)1332 TEST_F(BuildTest, PhonyUseCase1) { TestPhonyUseCase(this, 1); }
TEST_F(BuildTest,PhonyUseCase2)1333 TEST_F(BuildTest, PhonyUseCase2) { TestPhonyUseCase(this, 2); }
TEST_F(BuildTest,PhonyUseCase3)1334 TEST_F(BuildTest, PhonyUseCase3) { TestPhonyUseCase(this, 3); }
TEST_F(BuildTest,PhonyUseCase4)1335 TEST_F(BuildTest, PhonyUseCase4) { TestPhonyUseCase(this, 4); }
TEST_F(BuildTest,PhonyUseCase5)1336 TEST_F(BuildTest, PhonyUseCase5) { TestPhonyUseCase(this, 5); }
TEST_F(BuildTest,PhonyUseCase6)1337 TEST_F(BuildTest, PhonyUseCase6) { TestPhonyUseCase(this, 6); }
1338
TEST_F(BuildTest,Fail)1339 TEST_F(BuildTest, Fail) {
1340 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1341 "rule fail\n"
1342 " command = fail\n"
1343 "build out1: fail\n"));
1344
1345 string err;
1346 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1347 ASSERT_EQ("", err);
1348
1349 EXPECT_FALSE(builder_.Build(&err));
1350 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1351 ASSERT_EQ("subcommand failed", err);
1352 }
1353
TEST_F(BuildTest,SwallowFailures)1354 TEST_F(BuildTest, SwallowFailures) {
1355 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1356 "rule fail\n"
1357 " command = fail\n"
1358 "build out1: fail\n"
1359 "build out2: fail\n"
1360 "build out3: fail\n"
1361 "build all: phony out1 out2 out3\n"));
1362
1363 // Swallow two failures, die on the third.
1364 config_.failures_allowed = 3;
1365
1366 string err;
1367 EXPECT_TRUE(builder_.AddTarget("all", &err));
1368 ASSERT_EQ("", err);
1369
1370 EXPECT_FALSE(builder_.Build(&err));
1371 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1372 ASSERT_EQ("subcommands failed", err);
1373 }
1374
TEST_F(BuildTest,SwallowFailuresLimit)1375 TEST_F(BuildTest, SwallowFailuresLimit) {
1376 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1377 "rule fail\n"
1378 " command = fail\n"
1379 "build out1: fail\n"
1380 "build out2: fail\n"
1381 "build out3: fail\n"
1382 "build final: cat out1 out2 out3\n"));
1383
1384 // Swallow ten failures; we should stop before building final.
1385 config_.failures_allowed = 11;
1386
1387 string err;
1388 EXPECT_TRUE(builder_.AddTarget("final", &err));
1389 ASSERT_EQ("", err);
1390
1391 EXPECT_FALSE(builder_.Build(&err));
1392 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1393 ASSERT_EQ("cannot make progress due to previous errors", err);
1394 }
1395
TEST_F(BuildTest,SwallowFailuresPool)1396 TEST_F(BuildTest, SwallowFailuresPool) {
1397 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1398 "pool failpool\n"
1399 " depth = 1\n"
1400 "rule fail\n"
1401 " command = fail\n"
1402 " pool = failpool\n"
1403 "build out1: fail\n"
1404 "build out2: fail\n"
1405 "build out3: fail\n"
1406 "build final: cat out1 out2 out3\n"));
1407
1408 // Swallow ten failures; we should stop before building final.
1409 config_.failures_allowed = 11;
1410
1411 string err;
1412 EXPECT_TRUE(builder_.AddTarget("final", &err));
1413 ASSERT_EQ("", err);
1414
1415 EXPECT_FALSE(builder_.Build(&err));
1416 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1417 ASSERT_EQ("cannot make progress due to previous errors", err);
1418 }
1419
TEST_F(BuildTest,PoolEdgesReadyButNotWanted)1420 TEST_F(BuildTest, PoolEdgesReadyButNotWanted) {
1421 fs_.Create("x", "");
1422
1423 const char* manifest =
1424 "pool some_pool\n"
1425 " depth = 4\n"
1426 "rule touch\n"
1427 " command = touch $out\n"
1428 " pool = some_pool\n"
1429 "rule cc\n"
1430 " command = touch grit\n"
1431 "\n"
1432 "build B.d.stamp: cc | x\n"
1433 "build C.stamp: touch B.d.stamp\n"
1434 "build final.stamp: touch || C.stamp\n";
1435
1436 RebuildTarget("final.stamp", manifest);
1437
1438 fs_.RemoveFile("B.d.stamp");
1439
1440 State save_state;
1441 RebuildTarget("final.stamp", manifest, NULL, NULL, &save_state);
1442 EXPECT_GE(save_state.LookupPool("some_pool")->current_use(), 0);
1443 }
1444
1445 struct BuildWithLogTest : public BuildTest {
BuildWithLogTestBuildWithLogTest1446 BuildWithLogTest() {
1447 builder_.SetBuildLog(&build_log_);
1448 }
1449
1450 BuildLog build_log_;
1451 };
1452
TEST_F(BuildWithLogTest,ImplicitGeneratedOutOfDate)1453 TEST_F(BuildWithLogTest, ImplicitGeneratedOutOfDate) {
1454 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1455 "rule touch\n"
1456 " command = touch $out\n"
1457 " generator = 1\n"
1458 "build out.imp: touch | in\n"));
1459 fs_.Create("out.imp", "");
1460 fs_.Tick();
1461 fs_.Create("in", "");
1462
1463 string err;
1464
1465 EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
1466 EXPECT_FALSE(builder_.AlreadyUpToDate());
1467
1468 EXPECT_TRUE(GetNode("out.imp")->dirty());
1469 }
1470
TEST_F(BuildWithLogTest,ImplicitGeneratedOutOfDate2)1471 TEST_F(BuildWithLogTest, ImplicitGeneratedOutOfDate2) {
1472 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1473 "rule touch-implicit-dep-out\n"
1474 " command = touch $test_dependency ; sleep 1 ; touch $out\n"
1475 " generator = 1\n"
1476 "build out.imp: touch-implicit-dep-out | inimp inimp2\n"
1477 " test_dependency = inimp\n"));
1478 fs_.Create("inimp", "");
1479 fs_.Create("out.imp", "");
1480 fs_.Tick();
1481 fs_.Create("inimp2", "");
1482 fs_.Tick();
1483
1484 string err;
1485
1486 EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
1487 EXPECT_FALSE(builder_.AlreadyUpToDate());
1488
1489 EXPECT_TRUE(builder_.Build(&err));
1490 EXPECT_TRUE(builder_.AlreadyUpToDate());
1491
1492 command_runner_.commands_ran_.clear();
1493 state_.Reset();
1494 builder_.Cleanup();
1495 builder_.plan_.Reset();
1496
1497 EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
1498 EXPECT_TRUE(builder_.AlreadyUpToDate());
1499 EXPECT_FALSE(GetNode("out.imp")->dirty());
1500 }
1501
TEST_F(BuildWithLogTest,NotInLogButOnDisk)1502 TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
1503 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1504 "rule cc\n"
1505 " command = cc\n"
1506 "build out1: cc in\n"));
1507
1508 // Create input/output that would be considered up to date when
1509 // not considering the command line hash.
1510 fs_.Create("in", "");
1511 fs_.Create("out1", "");
1512 string err;
1513
1514 // Because it's not in the log, it should not be up-to-date until
1515 // we build again.
1516 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1517 EXPECT_FALSE(builder_.AlreadyUpToDate());
1518
1519 command_runner_.commands_ran_.clear();
1520 state_.Reset();
1521
1522 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1523 EXPECT_TRUE(builder_.Build(&err));
1524 EXPECT_TRUE(builder_.AlreadyUpToDate());
1525 }
1526
TEST_F(BuildWithLogTest,RebuildAfterFailure)1527 TEST_F(BuildWithLogTest, RebuildAfterFailure) {
1528 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1529 "rule touch-fail-tick2\n"
1530 " command = touch-fail-tick2\n"
1531 "build out1: touch-fail-tick2 in\n"));
1532
1533 string err;
1534
1535 fs_.Create("in", "");
1536
1537 // Run once successfully to get out1 in the log
1538 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1539 EXPECT_TRUE(builder_.Build(&err));
1540 EXPECT_EQ("", err);
1541 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1542
1543 command_runner_.commands_ran_.clear();
1544 state_.Reset();
1545 builder_.Cleanup();
1546 builder_.plan_.Reset();
1547
1548 fs_.Tick();
1549 fs_.Create("in", "");
1550
1551 // Run again with a failure that updates the output file timestamp
1552 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1553 EXPECT_FALSE(builder_.Build(&err));
1554 EXPECT_EQ("subcommand failed", err);
1555 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1556
1557 command_runner_.commands_ran_.clear();
1558 state_.Reset();
1559 builder_.Cleanup();
1560 builder_.plan_.Reset();
1561
1562 fs_.Tick();
1563
1564 // Run again, should rerun even though the output file is up to date on disk
1565 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1566 EXPECT_FALSE(builder_.AlreadyUpToDate());
1567 EXPECT_TRUE(builder_.Build(&err));
1568 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1569 EXPECT_EQ("", err);
1570 }
1571
TEST_F(BuildWithLogTest,RebuildWithNoInputs)1572 TEST_F(BuildWithLogTest, RebuildWithNoInputs) {
1573 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1574 "rule touch\n"
1575 " command = touch\n"
1576 "build out1: touch\n"
1577 "build out2: touch in\n"));
1578
1579 string err;
1580
1581 fs_.Create("in", "");
1582
1583 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1584 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1585 EXPECT_TRUE(builder_.Build(&err));
1586 EXPECT_EQ("", err);
1587 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
1588
1589 command_runner_.commands_ran_.clear();
1590 state_.Reset();
1591
1592 fs_.Tick();
1593
1594 fs_.Create("in", "");
1595
1596 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1597 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1598 EXPECT_TRUE(builder_.Build(&err));
1599 EXPECT_EQ("", err);
1600 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1601 }
1602
TEST_F(BuildWithLogTest,RestatTest)1603 TEST_F(BuildWithLogTest, RestatTest) {
1604 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1605 "rule true\n"
1606 " command = true\n"
1607 " restat = 1\n"
1608 "rule cc\n"
1609 " command = cc\n"
1610 " restat = 1\n"
1611 "build out1: cc in\n"
1612 "build out2: true out1\n"
1613 "build out3: cat out2\n"));
1614
1615 fs_.Create("out1", "");
1616 fs_.Create("out2", "");
1617 fs_.Create("out3", "");
1618
1619 fs_.Tick();
1620
1621 fs_.Create("in", "");
1622
1623 // Do a pre-build so that there's commands in the log for the outputs,
1624 // otherwise, the lack of an entry in the build log will cause out3 to rebuild
1625 // regardless of restat.
1626 string err;
1627 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1628 ASSERT_EQ("", err);
1629 EXPECT_TRUE(builder_.Build(&err));
1630 ASSERT_EQ("", err);
1631 EXPECT_EQ(3u, command_runner_.commands_ran_.size());
1632 EXPECT_EQ(3u, builder_.plan_.command_edge_count());
1633 command_runner_.commands_ran_.clear();
1634 state_.Reset();
1635
1636 fs_.Tick();
1637
1638 fs_.Create("in", "");
1639 // "cc" touches out1, so we should build out2. But because "true" does not
1640 // touch out2, we should cancel the build of out3.
1641 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1642 ASSERT_EQ("", err);
1643 EXPECT_TRUE(builder_.Build(&err));
1644 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1645
1646 // If we run again, it should be a no-op, because the build log has recorded
1647 // that we've already built out2 with an input timestamp of 2 (from out1).
1648 command_runner_.commands_ran_.clear();
1649 state_.Reset();
1650 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1651 ASSERT_EQ("", err);
1652 EXPECT_TRUE(builder_.AlreadyUpToDate());
1653
1654 fs_.Tick();
1655
1656 fs_.Create("in", "");
1657
1658 // The build log entry should not, however, prevent us from rebuilding out2
1659 // if out1 changes.
1660 command_runner_.commands_ran_.clear();
1661 state_.Reset();
1662 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1663 ASSERT_EQ("", err);
1664 EXPECT_TRUE(builder_.Build(&err));
1665 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1666 }
1667
TEST_F(BuildWithLogTest,RestatMissingFile)1668 TEST_F(BuildWithLogTest, RestatMissingFile) {
1669 // If a restat rule doesn't create its output, and the output didn't
1670 // exist before the rule was run, consider that behavior equivalent
1671 // to a rule that doesn't modify its existent output file.
1672
1673 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1674 "rule true\n"
1675 " command = true\n"
1676 " restat = 1\n"
1677 "rule cc\n"
1678 " command = cc\n"
1679 "build out1: true in\n"
1680 "build out2: cc out1\n"));
1681
1682 fs_.Create("in", "");
1683 fs_.Create("out2", "");
1684
1685 // Do a pre-build so that there's commands in the log for the outputs,
1686 // otherwise, the lack of an entry in the build log will cause out2 to rebuild
1687 // regardless of restat.
1688 string err;
1689 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1690 ASSERT_EQ("", err);
1691 EXPECT_TRUE(builder_.Build(&err));
1692 ASSERT_EQ("", err);
1693 command_runner_.commands_ran_.clear();
1694 state_.Reset();
1695
1696 fs_.Tick();
1697 fs_.Create("in", "");
1698 fs_.Create("out2", "");
1699
1700 // Run a build, expect only the first command to run.
1701 // It doesn't touch its output (due to being the "true" command), so
1702 // we shouldn't run the dependent build.
1703 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1704 ASSERT_EQ("", err);
1705 EXPECT_TRUE(builder_.Build(&err));
1706 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1707 }
1708
TEST_F(BuildWithLogTest,RestatSingleDependentOutputDirty)1709 TEST_F(BuildWithLogTest, RestatSingleDependentOutputDirty) {
1710 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1711 "rule true\n"
1712 " command = true\n"
1713 " restat = 1\n"
1714 "rule touch\n"
1715 " command = touch\n"
1716 "build out1: true in\n"
1717 "build out2 out3: touch out1\n"
1718 "build out4: touch out2\n"
1719 ));
1720
1721 // Create the necessary files
1722 fs_.Create("in", "");
1723
1724 string err;
1725 EXPECT_TRUE(builder_.AddTarget("out4", &err));
1726 ASSERT_EQ("", err);
1727 EXPECT_TRUE(builder_.Build(&err));
1728 ASSERT_EQ("", err);
1729 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1730
1731 fs_.Tick();
1732 fs_.Create("in", "");
1733 fs_.RemoveFile("out3");
1734
1735 // Since "in" is missing, out1 will be built. Since "out3" is missing,
1736 // out2 and out3 will be built even though "in" is not touched when built.
1737 // Then, since out2 is rebuilt, out4 should be rebuilt -- the restat on the
1738 // "true" rule should not lead to the "touch" edge writing out2 and out3 being
1739 // cleard.
1740 command_runner_.commands_ran_.clear();
1741 state_.Reset();
1742 EXPECT_TRUE(builder_.AddTarget("out4", &err));
1743 ASSERT_EQ("", err);
1744 EXPECT_TRUE(builder_.Build(&err));
1745 ASSERT_EQ("", err);
1746 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1747 }
1748
1749 // Test scenario, in which an input file is removed, but output isn't changed
1750 // https://github.com/ninja-build/ninja/issues/295
TEST_F(BuildWithLogTest,RestatMissingInput)1751 TEST_F(BuildWithLogTest, RestatMissingInput) {
1752 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1753 "rule true\n"
1754 " command = true\n"
1755 " depfile = $out.d\n"
1756 " restat = 1\n"
1757 "rule cc\n"
1758 " command = cc\n"
1759 "build out1: true in\n"
1760 "build out2: cc out1\n"));
1761
1762 // Create all necessary files
1763 fs_.Create("in", "");
1764
1765 // The implicit dependencies and the depfile itself
1766 // are newer than the output
1767 TimeStamp restat_mtime = fs_.Tick();
1768 fs_.Create("out1.d", "out1: will.be.deleted restat.file\n");
1769 fs_.Create("will.be.deleted", "");
1770 fs_.Create("restat.file", "");
1771
1772 // Run the build, out1 and out2 get built
1773 string err;
1774 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1775 ASSERT_EQ("", err);
1776 EXPECT_TRUE(builder_.Build(&err));
1777 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1778
1779 // See that an entry in the logfile is created, capturing
1780 // the right mtime
1781 BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out1");
1782 ASSERT_TRUE(NULL != log_entry);
1783 ASSERT_EQ(restat_mtime, log_entry->mtime);
1784
1785 // Now remove a file, referenced from depfile, so that target becomes
1786 // dirty, but the output does not change
1787 fs_.RemoveFile("will.be.deleted");
1788
1789 // Trigger the build again - only out1 gets built
1790 command_runner_.commands_ran_.clear();
1791 state_.Reset();
1792 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1793 ASSERT_EQ("", err);
1794 EXPECT_TRUE(builder_.Build(&err));
1795 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1796
1797 // Check that the logfile entry remains correctly set
1798 log_entry = build_log_.LookupByOutput("out1");
1799 ASSERT_TRUE(NULL != log_entry);
1800 ASSERT_EQ(restat_mtime, log_entry->mtime);
1801 }
1802
TEST_F(BuildWithLogTest,GeneratedPlainDepfileMtime)1803 TEST_F(BuildWithLogTest, GeneratedPlainDepfileMtime) {
1804 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1805 "rule generate-depfile\n"
1806 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n"
1807 "build out: generate-depfile\n"
1808 " test_dependency = inimp\n"
1809 " depfile = out.d\n"));
1810 fs_.Create("inimp", "");
1811 fs_.Tick();
1812
1813 string err;
1814
1815 EXPECT_TRUE(builder_.AddTarget("out", &err));
1816 EXPECT_FALSE(builder_.AlreadyUpToDate());
1817
1818 EXPECT_TRUE(builder_.Build(&err));
1819 EXPECT_TRUE(builder_.AlreadyUpToDate());
1820
1821 command_runner_.commands_ran_.clear();
1822 state_.Reset();
1823 builder_.Cleanup();
1824 builder_.plan_.Reset();
1825
1826 EXPECT_TRUE(builder_.AddTarget("out", &err));
1827 EXPECT_TRUE(builder_.AlreadyUpToDate());
1828 }
1829
1830 struct BuildDryRun : public BuildWithLogTest {
BuildDryRunBuildDryRun1831 BuildDryRun() {
1832 config_.dry_run = true;
1833 }
1834 };
1835
TEST_F(BuildDryRun,AllCommandsShown)1836 TEST_F(BuildDryRun, AllCommandsShown) {
1837 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1838 "rule true\n"
1839 " command = true\n"
1840 " restat = 1\n"
1841 "rule cc\n"
1842 " command = cc\n"
1843 " restat = 1\n"
1844 "build out1: cc in\n"
1845 "build out2: true out1\n"
1846 "build out3: cat out2\n"));
1847
1848 fs_.Create("out1", "");
1849 fs_.Create("out2", "");
1850 fs_.Create("out3", "");
1851
1852 fs_.Tick();
1853
1854 fs_.Create("in", "");
1855
1856 // "cc" touches out1, so we should build out2. But because "true" does not
1857 // touch out2, we should cancel the build of out3.
1858 string err;
1859 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1860 ASSERT_EQ("", err);
1861 EXPECT_TRUE(builder_.Build(&err));
1862 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1863 }
1864
1865 // Test that RSP files are created when & where appropriate and deleted after
1866 // successful execution.
TEST_F(BuildTest,RspFileSuccess)1867 TEST_F(BuildTest, RspFileSuccess)
1868 {
1869 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1870 "rule cat_rsp\n"
1871 " command = cat $rspfile > $out\n"
1872 " rspfile = $rspfile\n"
1873 " rspfile_content = $long_command\n"
1874 "rule cat_rsp_out\n"
1875 " command = cat $rspfile > $out\n"
1876 " rspfile = $out.rsp\n"
1877 " rspfile_content = $long_command\n"
1878 "build out1: cat in\n"
1879 "build out2: cat_rsp in\n"
1880 " rspfile = out 2.rsp\n"
1881 " long_command = Some very long command\n"
1882 "build out$ 3: cat_rsp_out in\n"
1883 " long_command = Some very long command\n"));
1884
1885 fs_.Create("out1", "");
1886 fs_.Create("out2", "");
1887 fs_.Create("out 3", "");
1888
1889 fs_.Tick();
1890
1891 fs_.Create("in", "");
1892
1893 string err;
1894 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1895 ASSERT_EQ("", err);
1896 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1897 ASSERT_EQ("", err);
1898 EXPECT_TRUE(builder_.AddTarget("out 3", &err));
1899 ASSERT_EQ("", err);
1900
1901 size_t files_created = fs_.files_created_.size();
1902 size_t files_removed = fs_.files_removed_.size();
1903
1904 EXPECT_TRUE(builder_.Build(&err));
1905 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1906
1907 // The RSP files were created
1908 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1909 ASSERT_EQ(1u, fs_.files_created_.count("out 2.rsp"));
1910 ASSERT_EQ(1u, fs_.files_created_.count("out 3.rsp"));
1911
1912 // The RSP files were removed
1913 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1914 ASSERT_EQ(1u, fs_.files_removed_.count("out 2.rsp"));
1915 ASSERT_EQ(1u, fs_.files_removed_.count("out 3.rsp"));
1916 }
1917
1918 // Test that RSP file is created but not removed for commands, which fail
TEST_F(BuildTest,RspFileFailure)1919 TEST_F(BuildTest, RspFileFailure) {
1920 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1921 "rule fail\n"
1922 " command = fail\n"
1923 " rspfile = $rspfile\n"
1924 " rspfile_content = $long_command\n"
1925 "build out: fail in\n"
1926 " rspfile = out.rsp\n"
1927 " long_command = Another very long command\n"));
1928
1929 fs_.Create("out", "");
1930 fs_.Tick();
1931 fs_.Create("in", "");
1932
1933 string err;
1934 EXPECT_TRUE(builder_.AddTarget("out", &err));
1935 ASSERT_EQ("", err);
1936
1937 size_t files_created = fs_.files_created_.size();
1938 size_t files_removed = fs_.files_removed_.size();
1939
1940 EXPECT_FALSE(builder_.Build(&err));
1941 ASSERT_EQ("subcommand failed", err);
1942 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1943
1944 // The RSP file was created
1945 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1946 ASSERT_EQ(1u, fs_.files_created_.count("out.rsp"));
1947
1948 // The RSP file was NOT removed
1949 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1950 ASSERT_EQ(0u, fs_.files_removed_.count("out.rsp"));
1951
1952 // The RSP file contains what it should
1953 ASSERT_EQ("Another very long command", fs_.files_["out.rsp"].contents);
1954 }
1955
1956 // Test that contents of the RSP file behaves like a regular part of
1957 // command line, i.e. triggers a rebuild if changed
TEST_F(BuildWithLogTest,RspFileCmdLineChange)1958 TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
1959 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1960 "rule cat_rsp\n"
1961 " command = cat $rspfile > $out\n"
1962 " rspfile = $rspfile\n"
1963 " rspfile_content = $long_command\n"
1964 "build out: cat_rsp in\n"
1965 " rspfile = out.rsp\n"
1966 " long_command = Original very long command\n"));
1967
1968 fs_.Create("out", "");
1969 fs_.Tick();
1970 fs_.Create("in", "");
1971
1972 string err;
1973 EXPECT_TRUE(builder_.AddTarget("out", &err));
1974 ASSERT_EQ("", err);
1975
1976 // 1. Build for the 1st time (-> populate log)
1977 EXPECT_TRUE(builder_.Build(&err));
1978 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1979
1980 // 2. Build again (no change)
1981 command_runner_.commands_ran_.clear();
1982 state_.Reset();
1983 EXPECT_TRUE(builder_.AddTarget("out", &err));
1984 EXPECT_EQ("", err);
1985 ASSERT_TRUE(builder_.AlreadyUpToDate());
1986
1987 // 3. Alter the entry in the logfile
1988 // (to simulate a change in the command line between 2 builds)
1989 BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out");
1990 ASSERT_TRUE(NULL != log_entry);
1991 ASSERT_NO_FATAL_FAILURE(AssertHash(
1992 "cat out.rsp > out;rspfile=Original very long command",
1993 log_entry->command_hash));
1994 log_entry->command_hash++; // Change the command hash to something else.
1995 // Now expect the target to be rebuilt
1996 command_runner_.commands_ran_.clear();
1997 state_.Reset();
1998 EXPECT_TRUE(builder_.AddTarget("out", &err));
1999 EXPECT_EQ("", err);
2000 EXPECT_TRUE(builder_.Build(&err));
2001 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2002 }
2003
TEST_F(BuildTest,InterruptCleanup)2004 TEST_F(BuildTest, InterruptCleanup) {
2005 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2006 "rule interrupt\n"
2007 " command = interrupt\n"
2008 "rule touch-interrupt\n"
2009 " command = touch-interrupt\n"
2010 "build out1: interrupt in1\n"
2011 "build out2: touch-interrupt in2\n"));
2012
2013 fs_.Create("out1", "");
2014 fs_.Create("out2", "");
2015 fs_.Tick();
2016 fs_.Create("in1", "");
2017 fs_.Create("in2", "");
2018
2019 // An untouched output of an interrupted command should be retained.
2020 string err;
2021 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2022 EXPECT_EQ("", err);
2023 EXPECT_FALSE(builder_.Build(&err));
2024 EXPECT_EQ("interrupted by user", err);
2025 builder_.Cleanup();
2026 EXPECT_GT(fs_.Stat("out1", &err), 0);
2027 err = "";
2028
2029 // A touched output of an interrupted command should be deleted.
2030 EXPECT_TRUE(builder_.AddTarget("out2", &err));
2031 EXPECT_EQ("", err);
2032 EXPECT_FALSE(builder_.Build(&err));
2033 EXPECT_EQ("interrupted by user", err);
2034 builder_.Cleanup();
2035 EXPECT_EQ(0, fs_.Stat("out2", &err));
2036 }
2037
TEST_F(BuildTest,StatFailureAbortsBuild)2038 TEST_F(BuildTest, StatFailureAbortsBuild) {
2039 const string kTooLongToStat(400, 'i');
2040 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2041 ("build " + kTooLongToStat + ": cat in\n").c_str()));
2042 fs_.Create("in", "");
2043
2044 // This simulates a stat failure:
2045 fs_.files_[kTooLongToStat].mtime = -1;
2046 fs_.files_[kTooLongToStat].stat_error = "stat failed";
2047
2048 string err;
2049 EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
2050 EXPECT_EQ("stat failed", err);
2051 }
2052
TEST_F(BuildTest,PhonyWithNoInputs)2053 TEST_F(BuildTest, PhonyWithNoInputs) {
2054 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2055 "build nonexistent: phony\n"
2056 "build out1: cat || nonexistent\n"
2057 "build out2: cat nonexistent\n"));
2058 fs_.Create("out1", "");
2059 fs_.Create("out2", "");
2060
2061 // out1 should be up to date even though its input is dirty, because its
2062 // order-only dependency has nothing to do.
2063 string err;
2064 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2065 ASSERT_EQ("", err);
2066 EXPECT_TRUE(builder_.AlreadyUpToDate());
2067
2068 // out2 should still be out of date though, because its input is dirty.
2069 err.clear();
2070 command_runner_.commands_ran_.clear();
2071 state_.Reset();
2072 EXPECT_TRUE(builder_.AddTarget("out2", &err));
2073 ASSERT_EQ("", err);
2074 EXPECT_TRUE(builder_.Build(&err));
2075 EXPECT_EQ("", err);
2076 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2077 }
2078
TEST_F(BuildTest,DepsGccWithEmptyDepfileErrorsOut)2079 TEST_F(BuildTest, DepsGccWithEmptyDepfileErrorsOut) {
2080 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2081 "rule cc\n"
2082 " command = cc\n"
2083 " deps = gcc\n"
2084 "build out: cc\n"));
2085 Dirty("out");
2086
2087 string err;
2088 EXPECT_TRUE(builder_.AddTarget("out", &err));
2089 ASSERT_EQ("", err);
2090 EXPECT_FALSE(builder_.AlreadyUpToDate());
2091
2092 EXPECT_FALSE(builder_.Build(&err));
2093 ASSERT_EQ("subcommand failed", err);
2094 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2095 }
2096
TEST_F(BuildTest,StatusFormatElapsed)2097 TEST_F(BuildTest, StatusFormatElapsed) {
2098 status_.BuildStarted();
2099 // Before any task is done, the elapsed time must be zero.
2100 EXPECT_EQ("[%/e0.000]",
2101 status_.FormatProgressStatus("[%%/e%e]", 0));
2102 }
2103
TEST_F(BuildTest,StatusFormatReplacePlaceholder)2104 TEST_F(BuildTest, StatusFormatReplacePlaceholder) {
2105 EXPECT_EQ("[%/s0/t0/r0/u0/f0]",
2106 status_.FormatProgressStatus("[%%/s%s/t%t/r%r/u%u/f%f]", 0));
2107 }
2108
TEST_F(BuildTest,FailedDepsParse)2109 TEST_F(BuildTest, FailedDepsParse) {
2110 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2111 "build bad_deps.o: cat in1\n"
2112 " deps = gcc\n"
2113 " depfile = in1.d\n"));
2114
2115 string err;
2116 EXPECT_TRUE(builder_.AddTarget("bad_deps.o", &err));
2117 ASSERT_EQ("", err);
2118
2119 // These deps will fail to parse, as they should only have one
2120 // path to the left of the colon.
2121 fs_.Create("in1.d", "AAA BBB");
2122
2123 EXPECT_FALSE(builder_.Build(&err));
2124 EXPECT_EQ("subcommand failed", err);
2125 }
2126
2127 struct BuildWithQueryDepsLogTest : public BuildTest {
BuildWithQueryDepsLogTestBuildWithQueryDepsLogTest2128 BuildWithQueryDepsLogTest() : BuildTest(&log_) {
2129 }
2130
~BuildWithQueryDepsLogTestBuildWithQueryDepsLogTest2131 ~BuildWithQueryDepsLogTest() {
2132 log_.Close();
2133 }
2134
SetUpBuildWithQueryDepsLogTest2135 virtual void SetUp() {
2136 BuildTest::SetUp();
2137
2138 temp_dir_.CreateAndEnter("BuildWithQueryDepsLogTest");
2139
2140 std::string err;
2141 ASSERT_TRUE(log_.OpenForWrite("ninja_deps", &err));
2142 ASSERT_EQ("", err);
2143 }
2144
2145 ScopedTempDir temp_dir_;
2146
2147 DepsLog log_;
2148 };
2149
2150 /// Test a MSVC-style deps log with multiple outputs.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileMSVC)2151 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileMSVC) {
2152 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2153 "rule cp_multi_msvc\n"
2154 " command = echo 'using $in' && for file in $out; do cp $in $$file; done\n"
2155 " deps = msvc\n"
2156 " msvc_deps_prefix = using \n"
2157 "build out1 out2: cp_multi_msvc in1\n"));
2158
2159 std::string err;
2160 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2161 ASSERT_EQ("", err);
2162 EXPECT_TRUE(builder_.Build(&err));
2163 EXPECT_EQ("", err);
2164 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2165 EXPECT_EQ("echo 'using in1' && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2166
2167 Node* out1_node = state_.LookupNode("out1");
2168 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2169 EXPECT_EQ(1, out1_deps->node_count);
2170 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2171
2172 Node* out2_node = state_.LookupNode("out2");
2173 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2174 EXPECT_EQ(1, out2_deps->node_count);
2175 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2176 }
2177
2178 /// Test a GCC-style deps log with multiple outputs.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileGCCOneLine)2179 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOneLine) {
2180 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2181 "rule cp_multi_gcc\n"
2182 " command = echo '$out: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2183 " deps = gcc\n"
2184 " depfile = in.d\n"
2185 "build out1 out2: cp_multi_gcc in1 in2\n"));
2186
2187 std::string err;
2188 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2189 ASSERT_EQ("", err);
2190 fs_.Create("in.d", "out1 out2: in1 in2");
2191 EXPECT_TRUE(builder_.Build(&err));
2192 EXPECT_EQ("", err);
2193 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2194 EXPECT_EQ("echo 'out1 out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2195
2196 Node* out1_node = state_.LookupNode("out1");
2197 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2198 EXPECT_EQ(2, out1_deps->node_count);
2199 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2200 EXPECT_EQ("in2", out1_deps->nodes[1]->path());
2201
2202 Node* out2_node = state_.LookupNode("out2");
2203 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2204 EXPECT_EQ(2, out2_deps->node_count);
2205 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2206 EXPECT_EQ("in2", out2_deps->nodes[1]->path());
2207 }
2208
2209 /// Test a GCC-style deps log with multiple outputs using a line per input.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileGCCMultiLineInput)2210 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCMultiLineInput) {
2211 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2212 "rule cp_multi_gcc\n"
2213 " command = echo '$out: in1\\n$out: in2' > in.d && for file in $out; do cp in1 $$file; done\n"
2214 " deps = gcc\n"
2215 " depfile = in.d\n"
2216 "build out1 out2: cp_multi_gcc in1 in2\n"));
2217
2218 std::string err;
2219 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2220 ASSERT_EQ("", err);
2221 fs_.Create("in.d", "out1 out2: in1\nout1 out2: in2");
2222 EXPECT_TRUE(builder_.Build(&err));
2223 EXPECT_EQ("", err);
2224 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2225 EXPECT_EQ("echo 'out1 out2: in1\\nout1 out2: in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2226
2227 Node* out1_node = state_.LookupNode("out1");
2228 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2229 EXPECT_EQ(2, out1_deps->node_count);
2230 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2231 EXPECT_EQ("in2", out1_deps->nodes[1]->path());
2232
2233 Node* out2_node = state_.LookupNode("out2");
2234 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2235 EXPECT_EQ(2, out2_deps->node_count);
2236 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2237 EXPECT_EQ("in2", out2_deps->nodes[1]->path());
2238 }
2239
2240 /// Test a GCC-style deps log with multiple outputs using a line per output.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileGCCMultiLineOutput)2241 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCMultiLineOutput) {
2242 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2243 "rule cp_multi_gcc\n"
2244 " command = echo 'out1: $in\\nout2: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2245 " deps = gcc\n"
2246 " depfile = in.d\n"
2247 "build out1 out2: cp_multi_gcc in1 in2\n"));
2248
2249 std::string err;
2250 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2251 ASSERT_EQ("", err);
2252 fs_.Create("in.d", "out1: in1 in2\nout2: in1 in2");
2253 EXPECT_TRUE(builder_.Build(&err));
2254 EXPECT_EQ("", err);
2255 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2256 EXPECT_EQ("echo 'out1: in1 in2\\nout2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2257
2258 Node* out1_node = state_.LookupNode("out1");
2259 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2260 EXPECT_EQ(2, out1_deps->node_count);
2261 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2262 EXPECT_EQ("in2", out1_deps->nodes[1]->path());
2263
2264 Node* out2_node = state_.LookupNode("out2");
2265 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2266 EXPECT_EQ(2, out2_deps->node_count);
2267 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2268 EXPECT_EQ("in2", out2_deps->nodes[1]->path());
2269 }
2270
2271 /// Test a GCC-style deps log with multiple outputs mentioning only the main output.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileGCCOnlyMainOutput)2272 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOnlyMainOutput) {
2273 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2274 "rule cp_multi_gcc\n"
2275 " command = echo 'out1: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2276 " deps = gcc\n"
2277 " depfile = in.d\n"
2278 "build out1 out2: cp_multi_gcc in1 in2\n"));
2279
2280 std::string err;
2281 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2282 ASSERT_EQ("", err);
2283 fs_.Create("in.d", "out1: in1 in2");
2284 EXPECT_TRUE(builder_.Build(&err));
2285 EXPECT_EQ("", err);
2286 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2287 EXPECT_EQ("echo 'out1: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2288
2289 Node* out1_node = state_.LookupNode("out1");
2290 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2291 EXPECT_EQ(2, out1_deps->node_count);
2292 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2293 EXPECT_EQ("in2", out1_deps->nodes[1]->path());
2294
2295 Node* out2_node = state_.LookupNode("out2");
2296 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2297 EXPECT_EQ(2, out2_deps->node_count);
2298 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2299 EXPECT_EQ("in2", out2_deps->nodes[1]->path());
2300 }
2301
2302 /// Test a GCC-style deps log with multiple outputs mentioning only the secondary output.
TEST_F(BuildWithQueryDepsLogTest,TwoOutputsDepFileGCCOnlySecondaryOutput)2303 TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOnlySecondaryOutput) {
2304 // Note: This ends up short-circuiting the node creation due to the primary
2305 // output not being present, but it should still work.
2306 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2307 "rule cp_multi_gcc\n"
2308 " command = echo 'out2: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2309 " deps = gcc\n"
2310 " depfile = in.d\n"
2311 "build out1 out2: cp_multi_gcc in1 in2\n"));
2312
2313 std::string err;
2314 EXPECT_TRUE(builder_.AddTarget("out1", &err));
2315 ASSERT_EQ("", err);
2316 fs_.Create("in.d", "out2: in1 in2");
2317 EXPECT_TRUE(builder_.Build(&err));
2318 EXPECT_EQ("", err);
2319 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2320 EXPECT_EQ("echo 'out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2321
2322 Node* out1_node = state_.LookupNode("out1");
2323 DepsLog::Deps* out1_deps = log_.GetDeps(out1_node);
2324 EXPECT_EQ(2, out1_deps->node_count);
2325 EXPECT_EQ("in1", out1_deps->nodes[0]->path());
2326 EXPECT_EQ("in2", out1_deps->nodes[1]->path());
2327
2328 Node* out2_node = state_.LookupNode("out2");
2329 DepsLog::Deps* out2_deps = log_.GetDeps(out2_node);
2330 EXPECT_EQ(2, out2_deps->node_count);
2331 EXPECT_EQ("in1", out2_deps->nodes[0]->path());
2332 EXPECT_EQ("in2", out2_deps->nodes[1]->path());
2333 }
2334
2335 /// Tests of builds involving deps logs necessarily must span
2336 /// multiple builds. We reuse methods on BuildTest but not the
2337 /// builder_ it sets up, because we want pristine objects for
2338 /// each build.
2339 struct BuildWithDepsLogTest : public BuildTest {
BuildWithDepsLogTestBuildWithDepsLogTest2340 BuildWithDepsLogTest() {}
2341
SetUpBuildWithDepsLogTest2342 virtual void SetUp() {
2343 BuildTest::SetUp();
2344
2345 temp_dir_.CreateAndEnter("BuildWithDepsLogTest");
2346 }
2347
TearDownBuildWithDepsLogTest2348 virtual void TearDown() {
2349 temp_dir_.Cleanup();
2350 }
2351
2352 ScopedTempDir temp_dir_;
2353
2354 /// Shadow parent class builder_ so we don't accidentally use it.
2355 void* builder_;
2356 };
2357
2358 /// Run a straightforward build where the deps log is used.
TEST_F(BuildWithDepsLogTest,Straightforward)2359 TEST_F(BuildWithDepsLogTest, Straightforward) {
2360 string err;
2361 // Note: in1 was created by the superclass SetUp().
2362 const char* manifest =
2363 "build out: cat in1\n"
2364 " deps = gcc\n"
2365 " depfile = in1.d\n";
2366 {
2367 State state;
2368 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2369 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2370
2371 // Run the build once, everything should be ok.
2372 DepsLog deps_log;
2373 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2374 ASSERT_EQ("", err);
2375
2376 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2377 builder.command_runner_.reset(&command_runner_);
2378 EXPECT_TRUE(builder.AddTarget("out", &err));
2379 ASSERT_EQ("", err);
2380 fs_.Create("in1.d", "out: in2");
2381 EXPECT_TRUE(builder.Build(&err));
2382 EXPECT_EQ("", err);
2383
2384 // The deps file should have been removed.
2385 EXPECT_EQ(0, fs_.Stat("in1.d", &err));
2386 // Recreate it for the next step.
2387 fs_.Create("in1.d", "out: in2");
2388 deps_log.Close();
2389 builder.command_runner_.release();
2390 }
2391
2392 {
2393 State state;
2394 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2395 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2396
2397 // Touch the file only mentioned in the deps.
2398 fs_.Tick();
2399 fs_.Create("in2", "");
2400
2401 // Run the build again.
2402 DepsLog deps_log;
2403 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2404 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2405
2406 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2407 builder.command_runner_.reset(&command_runner_);
2408 command_runner_.commands_ran_.clear();
2409 EXPECT_TRUE(builder.AddTarget("out", &err));
2410 ASSERT_EQ("", err);
2411 EXPECT_TRUE(builder.Build(&err));
2412 EXPECT_EQ("", err);
2413
2414 // We should have rebuilt the output due to in2 being
2415 // out of date.
2416 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2417
2418 builder.command_runner_.release();
2419 }
2420 }
2421
2422 /// Verify that obsolete dependency info causes a rebuild.
2423 /// 1) Run a successful build where everything has time t, record deps.
2424 /// 2) Move input/output to time t+1 -- despite files in alignment,
2425 /// should still need to rebuild due to deps at older time.
TEST_F(BuildWithDepsLogTest,ObsoleteDeps)2426 TEST_F(BuildWithDepsLogTest, ObsoleteDeps) {
2427 string err;
2428 // Note: in1 was created by the superclass SetUp().
2429 const char* manifest =
2430 "build out: cat in1\n"
2431 " deps = gcc\n"
2432 " depfile = in1.d\n";
2433 {
2434 // Run an ordinary build that gathers dependencies.
2435 fs_.Create("in1", "");
2436 fs_.Create("in1.d", "out: ");
2437
2438 State state;
2439 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2440 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2441
2442 // Run the build once, everything should be ok.
2443 DepsLog deps_log;
2444 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2445 ASSERT_EQ("", err);
2446
2447 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2448 builder.command_runner_.reset(&command_runner_);
2449 EXPECT_TRUE(builder.AddTarget("out", &err));
2450 ASSERT_EQ("", err);
2451 EXPECT_TRUE(builder.Build(&err));
2452 EXPECT_EQ("", err);
2453
2454 deps_log.Close();
2455 builder.command_runner_.release();
2456 }
2457
2458 // Push all files one tick forward so that only the deps are out
2459 // of date.
2460 fs_.Tick();
2461 fs_.Create("in1", "");
2462 fs_.Create("out", "");
2463
2464 // The deps file should have been removed, so no need to timestamp it.
2465 EXPECT_EQ(0, fs_.Stat("in1.d", &err));
2466
2467 {
2468 State state;
2469 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2470 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2471
2472 DepsLog deps_log;
2473 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2474 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2475
2476 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2477 builder.command_runner_.reset(&command_runner_);
2478 command_runner_.commands_ran_.clear();
2479 EXPECT_TRUE(builder.AddTarget("out", &err));
2480 ASSERT_EQ("", err);
2481
2482 // Recreate the deps file here because the build expects them to exist.
2483 fs_.Create("in1.d", "out: ");
2484
2485 EXPECT_TRUE(builder.Build(&err));
2486 EXPECT_EQ("", err);
2487
2488 // We should have rebuilt the output due to the deps being
2489 // out of date.
2490 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2491
2492 builder.command_runner_.release();
2493 }
2494 }
2495
TEST_F(BuildWithDepsLogTest,DepsIgnoredInDryRun)2496 TEST_F(BuildWithDepsLogTest, DepsIgnoredInDryRun) {
2497 const char* manifest =
2498 "build out: cat in1\n"
2499 " deps = gcc\n"
2500 " depfile = in1.d\n";
2501
2502 fs_.Create("out", "");
2503 fs_.Tick();
2504 fs_.Create("in1", "");
2505
2506 State state;
2507 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2508 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2509
2510 // The deps log is NULL in dry runs.
2511 config_.dry_run = true;
2512 Builder builder(&state, config_, NULL, NULL, &fs_, &status_, 0);
2513 builder.command_runner_.reset(&command_runner_);
2514 command_runner_.commands_ran_.clear();
2515
2516 string err;
2517 EXPECT_TRUE(builder.AddTarget("out", &err));
2518 ASSERT_EQ("", err);
2519 EXPECT_TRUE(builder.Build(&err));
2520 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2521
2522 builder.command_runner_.release();
2523 }
2524
2525 /// Check that a restat rule generating a header cancels compilations correctly.
TEST_F(BuildTest,RestatDepfileDependency)2526 TEST_F(BuildTest, RestatDepfileDependency) {
2527 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2528 "rule true\n"
2529 " command = true\n" // Would be "write if out-of-date" in reality.
2530 " restat = 1\n"
2531 "build header.h: true header.in\n"
2532 "build out: cat in1\n"
2533 " depfile = in1.d\n"));
2534
2535 fs_.Create("header.h", "");
2536 fs_.Create("in1.d", "out: header.h");
2537 fs_.Tick();
2538 fs_.Create("header.in", "");
2539
2540 string err;
2541 EXPECT_TRUE(builder_.AddTarget("out", &err));
2542 ASSERT_EQ("", err);
2543 EXPECT_TRUE(builder_.Build(&err));
2544 EXPECT_EQ("", err);
2545 }
2546
2547 /// Check that a restat rule generating a header cancels compilations correctly,
2548 /// depslog case.
TEST_F(BuildWithDepsLogTest,RestatDepfileDependencyDepsLog)2549 TEST_F(BuildWithDepsLogTest, RestatDepfileDependencyDepsLog) {
2550 string err;
2551 // Note: in1 was created by the superclass SetUp().
2552 const char* manifest =
2553 "rule true\n"
2554 " command = true\n" // Would be "write if out-of-date" in reality.
2555 " restat = 1\n"
2556 "build header.h: true header.in\n"
2557 "build out: cat in1\n"
2558 " deps = gcc\n"
2559 " depfile = in1.d\n";
2560 {
2561 State state;
2562 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2563 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2564
2565 // Run the build once, everything should be ok.
2566 DepsLog deps_log;
2567 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2568 ASSERT_EQ("", err);
2569
2570 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2571 builder.command_runner_.reset(&command_runner_);
2572 EXPECT_TRUE(builder.AddTarget("out", &err));
2573 ASSERT_EQ("", err);
2574 fs_.Create("in1.d", "out: header.h");
2575 EXPECT_TRUE(builder.Build(&err));
2576 EXPECT_EQ("", err);
2577
2578 deps_log.Close();
2579 builder.command_runner_.release();
2580 }
2581
2582 {
2583 State state;
2584 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2585 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2586
2587 // Touch the input of the restat rule.
2588 fs_.Tick();
2589 fs_.Create("header.in", "");
2590
2591 // Run the build again.
2592 DepsLog deps_log;
2593 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2594 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2595
2596 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2597 builder.command_runner_.reset(&command_runner_);
2598 command_runner_.commands_ran_.clear();
2599 EXPECT_TRUE(builder.AddTarget("out", &err));
2600 ASSERT_EQ("", err);
2601 EXPECT_TRUE(builder.Build(&err));
2602 EXPECT_EQ("", err);
2603
2604 // Rule "true" should have run again, but the build of "out" should have
2605 // been cancelled due to restat propagating through the depfile header.
2606 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2607
2608 builder.command_runner_.release();
2609 }
2610 }
2611
TEST_F(BuildWithDepsLogTest,DepFileOKDepsLog)2612 TEST_F(BuildWithDepsLogTest, DepFileOKDepsLog) {
2613 string err;
2614 const char* manifest =
2615 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
2616 "build fo$ o.o: cc foo.c\n";
2617
2618 fs_.Create("foo.c", "");
2619
2620 {
2621 State state;
2622 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2623
2624 // Run the build once, everything should be ok.
2625 DepsLog deps_log;
2626 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2627 ASSERT_EQ("", err);
2628
2629 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2630 builder.command_runner_.reset(&command_runner_);
2631 EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
2632 ASSERT_EQ("", err);
2633 fs_.Create("fo o.o.d", "fo\\ o.o: blah.h bar.h\n");
2634 EXPECT_TRUE(builder.Build(&err));
2635 EXPECT_EQ("", err);
2636
2637 deps_log.Close();
2638 builder.command_runner_.release();
2639 }
2640
2641 {
2642 State state;
2643 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2644
2645 DepsLog deps_log;
2646 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2647 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2648 ASSERT_EQ("", err);
2649
2650 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2651 builder.command_runner_.reset(&command_runner_);
2652
2653 Edge* edge = state.edges_.back();
2654
2655 state.GetNode("bar.h", 0)->MarkDirty(); // Mark bar.h as missing.
2656 EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
2657 ASSERT_EQ("", err);
2658
2659 // Expect three new edges: one generating fo o.o, and two more from
2660 // loading the depfile.
2661 ASSERT_EQ(3u, state.edges_.size());
2662 // Expect our edge to now have three inputs: foo.c and two headers.
2663 ASSERT_EQ(3u, edge->inputs_.size());
2664
2665 // Expect the command line we generate to only use the original input.
2666 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
2667
2668 deps_log.Close();
2669 builder.command_runner_.release();
2670 }
2671 }
2672
TEST_F(BuildWithDepsLogTest,DiscoveredDepDuringBuildChanged)2673 TEST_F(BuildWithDepsLogTest, DiscoveredDepDuringBuildChanged) {
2674 string err;
2675 const char* manifest =
2676 "rule touch-out-implicit-dep\n"
2677 " command = touch $out ; sleep 1 ; touch $test_dependency\n"
2678 "rule generate-depfile\n"
2679 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n"
2680 "build out1: touch-out-implicit-dep in1\n"
2681 " test_dependency = inimp\n"
2682 "build out2: generate-depfile in1 || out1\n"
2683 " test_dependency = inimp\n"
2684 " depfile = out2.d\n"
2685 " deps = gcc\n";
2686
2687 fs_.Create("in1", "");
2688 fs_.Tick();
2689
2690 BuildLog build_log;
2691
2692 {
2693 State state;
2694 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2695
2696 DepsLog deps_log;
2697 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2698 ASSERT_EQ("", err);
2699
2700 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2701 builder.command_runner_.reset(&command_runner_);
2702 EXPECT_TRUE(builder.AddTarget("out2", &err));
2703 EXPECT_FALSE(builder.AlreadyUpToDate());
2704
2705 EXPECT_TRUE(builder.Build(&err));
2706 EXPECT_TRUE(builder.AlreadyUpToDate());
2707
2708 deps_log.Close();
2709 builder.command_runner_.release();
2710 }
2711
2712 fs_.Tick();
2713 fs_.Create("in1", "");
2714
2715 {
2716 State state;
2717 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2718
2719 DepsLog deps_log;
2720 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2721 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2722 ASSERT_EQ("", err);
2723
2724 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2725 builder.command_runner_.reset(&command_runner_);
2726 EXPECT_TRUE(builder.AddTarget("out2", &err));
2727 EXPECT_FALSE(builder.AlreadyUpToDate());
2728
2729 EXPECT_TRUE(builder.Build(&err));
2730 EXPECT_TRUE(builder.AlreadyUpToDate());
2731
2732 deps_log.Close();
2733 builder.command_runner_.release();
2734 }
2735
2736 fs_.Tick();
2737
2738 {
2739 State state;
2740 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2741
2742 DepsLog deps_log;
2743 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2744 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2745 ASSERT_EQ("", err);
2746
2747 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2748 builder.command_runner_.reset(&command_runner_);
2749 EXPECT_TRUE(builder.AddTarget("out2", &err));
2750 EXPECT_TRUE(builder.AlreadyUpToDate());
2751
2752 deps_log.Close();
2753 builder.command_runner_.release();
2754 }
2755 }
2756
2757 #ifdef _WIN32
TEST_F(BuildWithDepsLogTest,DepFileDepsLogCanonicalize)2758 TEST_F(BuildWithDepsLogTest, DepFileDepsLogCanonicalize) {
2759 string err;
2760 const char* manifest =
2761 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
2762 "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
2763
2764 fs_.Create("x/y/z/foo.c", "");
2765
2766 {
2767 State state;
2768 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2769
2770 // Run the build once, everything should be ok.
2771 DepsLog deps_log;
2772 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2773 ASSERT_EQ("", err);
2774
2775 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2776 builder.command_runner_.reset(&command_runner_);
2777 EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
2778 ASSERT_EQ("", err);
2779 // Note, different slashes from manifest.
2780 fs_.Create("a/b\\c\\d/e/fo o.o.d",
2781 "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
2782 EXPECT_TRUE(builder.Build(&err));
2783 EXPECT_EQ("", err);
2784
2785 deps_log.Close();
2786 builder.command_runner_.release();
2787 }
2788
2789 {
2790 State state;
2791 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2792
2793 DepsLog deps_log;
2794 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2795 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2796 ASSERT_EQ("", err);
2797
2798 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2799 builder.command_runner_.reset(&command_runner_);
2800
2801 Edge* edge = state.edges_.back();
2802
2803 state.GetNode("bar.h", 0)->MarkDirty(); // Mark bar.h as missing.
2804 EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
2805 ASSERT_EQ("", err);
2806
2807 // Expect three new edges: one generating fo o.o, and two more from
2808 // loading the depfile.
2809 ASSERT_EQ(3u, state.edges_.size());
2810 // Expect our edge to now have three inputs: foo.c and two headers.
2811 ASSERT_EQ(3u, edge->inputs_.size());
2812
2813 // Expect the command line we generate to only use the original input.
2814 // Note, slashes from manifest, not .d.
2815 ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
2816
2817 deps_log.Close();
2818 builder.command_runner_.release();
2819 }
2820 }
2821 #endif
2822
2823 /// Check that a restat rule doesn't clear an edge if the depfile is missing.
2824 /// Follows from: https://github.com/ninja-build/ninja/issues/603
TEST_F(BuildTest,RestatMissingDepfile)2825 TEST_F(BuildTest, RestatMissingDepfile) {
2826 const char* manifest =
2827 "rule true\n"
2828 " command = true\n" // Would be "write if out-of-date" in reality.
2829 " restat = 1\n"
2830 "build header.h: true header.in\n"
2831 "build out: cat header.h\n"
2832 " depfile = out.d\n";
2833
2834 fs_.Create("header.h", "");
2835 fs_.Tick();
2836 fs_.Create("out", "");
2837 fs_.Create("header.in", "");
2838
2839 // Normally, only 'header.h' would be rebuilt, as
2840 // its rule doesn't touch the output and has 'restat=1' set.
2841 // But we are also missing the depfile for 'out',
2842 // which should force its command to run anyway!
2843 RebuildTarget("out", manifest);
2844 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2845 }
2846
2847 /// Check that a restat rule doesn't clear an edge if the deps are missing.
2848 /// https://github.com/ninja-build/ninja/issues/603
TEST_F(BuildWithDepsLogTest,RestatMissingDepfileDepslog)2849 TEST_F(BuildWithDepsLogTest, RestatMissingDepfileDepslog) {
2850 string err;
2851 const char* manifest =
2852 "rule true\n"
2853 " command = true\n" // Would be "write if out-of-date" in reality.
2854 " restat = 1\n"
2855 "build header.h: true header.in\n"
2856 "build out: cat header.h\n"
2857 " deps = gcc\n"
2858 " depfile = out.d\n";
2859
2860 // Build once to populate ninja deps logs from out.d
2861 fs_.Create("header.in", "");
2862 fs_.Create("out.d", "out: header.h");
2863 fs_.Create("header.h", "");
2864
2865 RebuildTarget("out", manifest, "build_log", "ninja_deps");
2866 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2867
2868 // Sanity: this rebuild should be NOOP
2869 RebuildTarget("out", manifest, "build_log", "ninja_deps");
2870 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2871
2872 // Touch 'header.in', blank dependencies log (create a different one).
2873 // Building header.h triggers 'restat' outputs cleanup.
2874 // Validate that out is rebuilt netherless, as deps are missing.
2875 fs_.Tick();
2876 fs_.Create("header.in", "");
2877
2878 // (switch to a new blank deps_log "ninja_deps2")
2879 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2880 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2881
2882 // Sanity: this build should be NOOP
2883 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2884 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2885
2886 // Check that invalidating deps by target timestamp also works here
2887 // Repeat the test but touch target instead of blanking the log.
2888 fs_.Tick();
2889 fs_.Create("header.in", "");
2890 fs_.Create("out", "");
2891 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2892 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2893
2894 // And this build should be NOOP again
2895 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2896 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2897 }
2898
TEST_F(BuildTest,WrongOutputInDepfileCausesRebuild)2899 TEST_F(BuildTest, WrongOutputInDepfileCausesRebuild) {
2900 string err;
2901 const char* manifest =
2902 "rule cc\n"
2903 " command = cc $in\n"
2904 " depfile = $out.d\n"
2905 "build foo.o: cc foo.c\n";
2906
2907 fs_.Create("foo.c", "");
2908 fs_.Create("foo.o", "");
2909 fs_.Create("header.h", "");
2910 fs_.Create("foo.o.d", "bar.o.d: header.h\n");
2911
2912 RebuildTarget("foo.o", manifest, "build_log", "ninja_deps");
2913 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2914 }
2915
TEST_F(BuildTest,Console)2916 TEST_F(BuildTest, Console) {
2917 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2918 "rule console\n"
2919 " command = console\n"
2920 " pool = console\n"
2921 "build cons: console in.txt\n"));
2922
2923 fs_.Create("in.txt", "");
2924
2925 string err;
2926 EXPECT_TRUE(builder_.AddTarget("cons", &err));
2927 ASSERT_EQ("", err);
2928 EXPECT_TRUE(builder_.Build(&err));
2929 EXPECT_EQ("", err);
2930 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2931 }
2932
TEST_F(BuildTest,DyndepMissingAndNoRule)2933 TEST_F(BuildTest, DyndepMissingAndNoRule) {
2934 // Verify that we can diagnose when a dyndep file is missing and
2935 // has no rule to build it.
2936 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2937 "rule touch\n"
2938 " command = touch $out\n"
2939 "build out: touch || dd\n"
2940 " dyndep = dd\n"
2941 ));
2942
2943 string err;
2944 EXPECT_FALSE(builder_.AddTarget("out", &err));
2945 EXPECT_EQ("loading 'dd': No such file or directory", err);
2946 }
2947
TEST_F(BuildTest,DyndepReadyImplicitConnection)2948 TEST_F(BuildTest, DyndepReadyImplicitConnection) {
2949 // Verify that a dyndep file can be loaded immediately to discover
2950 // that one edge has an implicit output that is also an implicit
2951 // input of another edge.
2952 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2953 "rule touch\n"
2954 " command = touch $out $out.imp\n"
2955 "build tmp: touch || dd\n"
2956 " dyndep = dd\n"
2957 "build out: touch || dd\n"
2958 " dyndep = dd\n"
2959 ));
2960 fs_.Create("dd",
2961 "ninja_dyndep_version = 1\n"
2962 "build out | out.imp: dyndep | tmp.imp\n"
2963 "build tmp | tmp.imp: dyndep\n"
2964 );
2965
2966 string err;
2967 EXPECT_TRUE(builder_.AddTarget("out", &err));
2968 ASSERT_EQ("", err);
2969 EXPECT_TRUE(builder_.Build(&err));
2970 EXPECT_EQ("", err);
2971 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2972 EXPECT_EQ("touch tmp tmp.imp", command_runner_.commands_ran_[0]);
2973 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[1]);
2974 }
2975
TEST_F(BuildTest,DyndepReadySyntaxError)2976 TEST_F(BuildTest, DyndepReadySyntaxError) {
2977 // Verify that a dyndep file can be loaded immediately to discover
2978 // and reject a syntax error in it.
2979 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2980 "rule touch\n"
2981 " command = touch $out\n"
2982 "build out: touch || dd\n"
2983 " dyndep = dd\n"
2984 ));
2985 fs_.Create("dd",
2986 "build out: dyndep\n"
2987 );
2988
2989 string err;
2990 EXPECT_FALSE(builder_.AddTarget("out", &err));
2991 EXPECT_EQ("dd:1: expected 'ninja_dyndep_version = ...'\n", err);
2992 }
2993
TEST_F(BuildTest,DyndepReadyCircular)2994 TEST_F(BuildTest, DyndepReadyCircular) {
2995 // Verify that a dyndep file can be loaded immediately to discover
2996 // and reject a circular dependency.
2997 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2998 "rule r\n"
2999 " command = unused\n"
3000 "build out: r in || dd\n"
3001 " dyndep = dd\n"
3002 "build in: r circ\n"
3003 ));
3004 fs_.Create("dd",
3005 "ninja_dyndep_version = 1\n"
3006 "build out | circ: dyndep\n"
3007 );
3008 fs_.Create("out", "");
3009
3010 string err;
3011 EXPECT_FALSE(builder_.AddTarget("out", &err));
3012 EXPECT_EQ("dependency cycle: circ -> in -> circ", err);
3013 }
3014
TEST_F(BuildTest,DyndepBuild)3015 TEST_F(BuildTest, DyndepBuild) {
3016 // Verify that a dyndep file can be built and loaded to discover nothing.
3017 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3018 "rule touch\n"
3019 " command = touch $out\n"
3020 "rule cp\n"
3021 " command = cp $in $out\n"
3022 "build dd: cp dd-in\n"
3023 "build out: touch || dd\n"
3024 " dyndep = dd\n"
3025 ));
3026 fs_.Create("dd-in",
3027 "ninja_dyndep_version = 1\n"
3028 "build out: dyndep\n"
3029 );
3030
3031 string err;
3032 EXPECT_TRUE(builder_.AddTarget("out", &err));
3033 EXPECT_EQ("", err);
3034
3035 size_t files_created = fs_.files_created_.size();
3036 EXPECT_TRUE(builder_.Build(&err));
3037 EXPECT_EQ("", err);
3038
3039 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3040 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3041 EXPECT_EQ("touch out", command_runner_.commands_ran_[1]);
3042 ASSERT_EQ(2u, fs_.files_read_.size());
3043 EXPECT_EQ("dd-in", fs_.files_read_[0]);
3044 EXPECT_EQ("dd", fs_.files_read_[1]);
3045 ASSERT_EQ(2u + files_created, fs_.files_created_.size());
3046 EXPECT_EQ(1u, fs_.files_created_.count("dd"));
3047 EXPECT_EQ(1u, fs_.files_created_.count("out"));
3048 }
3049
TEST_F(BuildTest,DyndepBuildSyntaxError)3050 TEST_F(BuildTest, DyndepBuildSyntaxError) {
3051 // Verify that a dyndep file can be built and loaded to discover
3052 // and reject a syntax error in it.
3053 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3054 "rule touch\n"
3055 " command = touch $out\n"
3056 "rule cp\n"
3057 " command = cp $in $out\n"
3058 "build dd: cp dd-in\n"
3059 "build out: touch || dd\n"
3060 " dyndep = dd\n"
3061 ));
3062 fs_.Create("dd-in",
3063 "build out: dyndep\n"
3064 );
3065
3066 string err;
3067 EXPECT_TRUE(builder_.AddTarget("out", &err));
3068 EXPECT_EQ("", err);
3069
3070 EXPECT_FALSE(builder_.Build(&err));
3071 EXPECT_EQ("dd:1: expected 'ninja_dyndep_version = ...'\n", err);
3072 }
3073
TEST_F(BuildTest,DyndepBuildUnrelatedOutput)3074 TEST_F(BuildTest, DyndepBuildUnrelatedOutput) {
3075 // Verify that a dyndep file can have dependents that do not specify
3076 // it as their dyndep binding.
3077 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3078 "rule touch\n"
3079 " command = touch $out\n"
3080 "rule cp\n"
3081 " command = cp $in $out\n"
3082 "build dd: cp dd-in\n"
3083 "build unrelated: touch || dd\n"
3084 "build out: touch unrelated || dd\n"
3085 " dyndep = dd\n"
3086 ));
3087 fs_.Create("dd-in",
3088 "ninja_dyndep_version = 1\n"
3089 "build out: dyndep\n"
3090 );
3091 fs_.Tick();
3092 fs_.Create("out", "");
3093
3094 string err;
3095 EXPECT_TRUE(builder_.AddTarget("out", &err));
3096 EXPECT_EQ("", err);
3097
3098 EXPECT_TRUE(builder_.Build(&err));
3099 EXPECT_EQ("", err);
3100 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3101 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3102 EXPECT_EQ("touch unrelated", command_runner_.commands_ran_[1]);
3103 EXPECT_EQ("touch out", command_runner_.commands_ran_[2]);
3104 }
3105
TEST_F(BuildTest,DyndepBuildDiscoverNewOutput)3106 TEST_F(BuildTest, DyndepBuildDiscoverNewOutput) {
3107 // Verify that a dyndep file can be built and loaded to discover
3108 // a new output of an edge.
3109 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3110 "rule touch\n"
3111 " command = touch $out $out.imp\n"
3112 "rule cp\n"
3113 " command = cp $in $out\n"
3114 "build dd: cp dd-in\n"
3115 "build out: touch in || dd\n"
3116 " dyndep = dd\n"
3117 ));
3118 fs_.Create("in", "");
3119 fs_.Create("dd-in",
3120 "ninja_dyndep_version = 1\n"
3121 "build out | out.imp: dyndep\n"
3122 );
3123 fs_.Tick();
3124 fs_.Create("out", "");
3125
3126 string err;
3127 EXPECT_TRUE(builder_.AddTarget("out", &err));
3128 EXPECT_EQ("", err);
3129
3130 EXPECT_TRUE(builder_.Build(&err));
3131 EXPECT_EQ("", err);
3132 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3133 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3134 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[1]);
3135 }
3136
TEST_F(BuildTest,DyndepBuildDiscoverNewOutputWithMultipleRules1)3137 TEST_F(BuildTest, DyndepBuildDiscoverNewOutputWithMultipleRules1) {
3138 // Verify that a dyndep file can be built and loaded to discover
3139 // a new output of an edge that is already the output of another edge.
3140 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3141 "rule touch\n"
3142 " command = touch $out $out.imp\n"
3143 "rule cp\n"
3144 " command = cp $in $out\n"
3145 "build dd: cp dd-in\n"
3146 "build out1 | out-twice.imp: touch in\n"
3147 "build out2: touch in || dd\n"
3148 " dyndep = dd\n"
3149 ));
3150 fs_.Create("in", "");
3151 fs_.Create("dd-in",
3152 "ninja_dyndep_version = 1\n"
3153 "build out2 | out-twice.imp: dyndep\n"
3154 );
3155 fs_.Tick();
3156 fs_.Create("out1", "");
3157 fs_.Create("out2", "");
3158
3159 string err;
3160 EXPECT_TRUE(builder_.AddTarget("out1", &err));
3161 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3162 EXPECT_EQ("", err);
3163
3164 EXPECT_FALSE(builder_.Build(&err));
3165 EXPECT_EQ("multiple rules generate out-twice.imp", err);
3166 }
3167
TEST_F(BuildTest,DyndepBuildDiscoverNewOutputWithMultipleRules2)3168 TEST_F(BuildTest, DyndepBuildDiscoverNewOutputWithMultipleRules2) {
3169 // Verify that a dyndep file can be built and loaded to discover
3170 // a new output of an edge that is already the output of another
3171 // edge also discovered by dyndep.
3172 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3173 "rule touch\n"
3174 " command = touch $out $out.imp\n"
3175 "rule cp\n"
3176 " command = cp $in $out\n"
3177 "build dd1: cp dd1-in\n"
3178 "build out1: touch || dd1\n"
3179 " dyndep = dd1\n"
3180 "build dd2: cp dd2-in || dd1\n" // make order predictable for test
3181 "build out2: touch || dd2\n"
3182 " dyndep = dd2\n"
3183 ));
3184 fs_.Create("out1", "");
3185 fs_.Create("out2", "");
3186 fs_.Create("dd1-in",
3187 "ninja_dyndep_version = 1\n"
3188 "build out1 | out-twice.imp: dyndep\n"
3189 );
3190 fs_.Create("dd2-in", "");
3191 fs_.Create("dd2",
3192 "ninja_dyndep_version = 1\n"
3193 "build out2 | out-twice.imp: dyndep\n"
3194 );
3195 fs_.Tick();
3196 fs_.Create("out1", "");
3197 fs_.Create("out2", "");
3198
3199 string err;
3200 EXPECT_TRUE(builder_.AddTarget("out1", &err));
3201 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3202 EXPECT_EQ("", err);
3203
3204 EXPECT_FALSE(builder_.Build(&err));
3205 EXPECT_EQ("multiple rules generate out-twice.imp", err);
3206 }
3207
TEST_F(BuildTest,DyndepBuildDiscoverNewInput)3208 TEST_F(BuildTest, DyndepBuildDiscoverNewInput) {
3209 // Verify that a dyndep file can be built and loaded to discover
3210 // a new input to an edge.
3211 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3212 "rule touch\n"
3213 " command = touch $out\n"
3214 "rule cp\n"
3215 " command = cp $in $out\n"
3216 "build dd: cp dd-in\n"
3217 "build in: touch\n"
3218 "build out: touch || dd\n"
3219 " dyndep = dd\n"
3220 ));
3221 fs_.Create("dd-in",
3222 "ninja_dyndep_version = 1\n"
3223 "build out: dyndep | in\n"
3224 );
3225 fs_.Tick();
3226 fs_.Create("out", "");
3227
3228 string err;
3229 EXPECT_TRUE(builder_.AddTarget("out", &err));
3230 EXPECT_EQ("", err);
3231
3232 EXPECT_TRUE(builder_.Build(&err));
3233 EXPECT_EQ("", err);
3234 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3235 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3236 EXPECT_EQ("touch in", command_runner_.commands_ran_[1]);
3237 EXPECT_EQ("touch out", command_runner_.commands_ran_[2]);
3238 }
3239
TEST_F(BuildTest,DyndepBuildDiscoverNewInputWithValidation)3240 TEST_F(BuildTest, DyndepBuildDiscoverNewInputWithValidation) {
3241 // Verify that a dyndep file cannot contain the |@ validation
3242 // syntax.
3243 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3244 "rule touch\n"
3245 " command = touch $out\n"
3246 "rule cp\n"
3247 " command = cp $in $out\n"
3248 "build dd: cp dd-in\n"
3249 "build out: touch || dd\n"
3250 " dyndep = dd\n"
3251 ));
3252 fs_.Create("dd-in",
3253 "ninja_dyndep_version = 1\n"
3254 "build out: dyndep |@ validation\n"
3255 );
3256
3257 string err;
3258 EXPECT_TRUE(builder_.AddTarget("out", &err));
3259 EXPECT_EQ("", err);
3260
3261 EXPECT_FALSE(builder_.Build(&err));
3262
3263 string err_first_line = err.substr(0, err.find("\n"));
3264 EXPECT_EQ("dd:2: expected newline, got '|@'", err_first_line);
3265 }
3266
TEST_F(BuildTest,DyndepBuildDiscoverNewInputWithTransitiveValidation)3267 TEST_F(BuildTest, DyndepBuildDiscoverNewInputWithTransitiveValidation) {
3268 // Verify that a dyndep file can be built and loaded to discover
3269 // a new input to an edge that has a validation edge.
3270 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3271 "rule touch\n"
3272 " command = touch $out\n"
3273 "rule cp\n"
3274 " command = cp $in $out\n"
3275 "build dd: cp dd-in\n"
3276 "build in: touch |@ validation\n"
3277 "build validation: touch in out\n"
3278 "build out: touch || dd\n"
3279 " dyndep = dd\n"
3280 ));
3281 fs_.Create("dd-in",
3282 "ninja_dyndep_version = 1\n"
3283 "build out: dyndep | in\n"
3284 );
3285 fs_.Tick();
3286 fs_.Create("out", "");
3287
3288 string err;
3289 EXPECT_TRUE(builder_.AddTarget("out", &err));
3290 EXPECT_EQ("", err);
3291
3292 EXPECT_TRUE(builder_.Build(&err));
3293 EXPECT_EQ("", err);
3294 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3295 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3296 EXPECT_EQ("touch in", command_runner_.commands_ran_[1]);
3297 EXPECT_EQ("touch out", command_runner_.commands_ran_[2]);
3298 EXPECT_EQ("touch validation", command_runner_.commands_ran_[3]);
3299 }
3300
TEST_F(BuildTest,DyndepBuildDiscoverImplicitConnection)3301 TEST_F(BuildTest, DyndepBuildDiscoverImplicitConnection) {
3302 // Verify that a dyndep file can be built and loaded to discover
3303 // that one edge has an implicit output that is also an implicit
3304 // input of another edge.
3305 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3306 "rule touch\n"
3307 " command = touch $out $out.imp\n"
3308 "rule cp\n"
3309 " command = cp $in $out\n"
3310 "build dd: cp dd-in\n"
3311 "build tmp: touch || dd\n"
3312 " dyndep = dd\n"
3313 "build out: touch || dd\n"
3314 " dyndep = dd\n"
3315 ));
3316 fs_.Create("dd-in",
3317 "ninja_dyndep_version = 1\n"
3318 "build out | out.imp: dyndep | tmp.imp\n"
3319 "build tmp | tmp.imp: dyndep\n"
3320 );
3321
3322 string err;
3323 EXPECT_TRUE(builder_.AddTarget("out", &err));
3324 ASSERT_EQ("", err);
3325 EXPECT_TRUE(builder_.Build(&err));
3326 EXPECT_EQ("", err);
3327 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3328 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3329 EXPECT_EQ("touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3330 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[2]);
3331 }
3332
TEST_F(BuildTest,DyndepBuildDiscoverOutputAndDepfileInput)3333 TEST_F(BuildTest, DyndepBuildDiscoverOutputAndDepfileInput) {
3334 // Verify that a dyndep file can be built and loaded to discover
3335 // that one edge has an implicit output that is also reported by
3336 // a depfile as an input of another edge.
3337 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3338 "rule touch\n"
3339 " command = touch $out $out.imp\n"
3340 "rule cp\n"
3341 " command = cp $in $out\n"
3342 "build dd: cp dd-in\n"
3343 "build tmp: touch || dd\n"
3344 " dyndep = dd\n"
3345 "build out: cp tmp\n"
3346 " depfile = out.d\n"
3347 ));
3348 fs_.Create("out.d", "out: tmp.imp\n");
3349 fs_.Create("dd-in",
3350 "ninja_dyndep_version = 1\n"
3351 "build tmp | tmp.imp: dyndep\n"
3352 );
3353
3354 string err;
3355 EXPECT_TRUE(builder_.AddTarget("out", &err));
3356 ASSERT_EQ("", err);
3357
3358 // Loading the depfile gave tmp.imp a phony input edge.
3359 ASSERT_TRUE(GetNode("tmp.imp")->in_edge()->is_phony());
3360
3361 EXPECT_TRUE(builder_.Build(&err));
3362 EXPECT_EQ("", err);
3363
3364 // Loading the dyndep file gave tmp.imp a real input edge.
3365 ASSERT_FALSE(GetNode("tmp.imp")->in_edge()->is_phony());
3366
3367 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3368 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3369 EXPECT_EQ("touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3370 EXPECT_EQ("cp tmp out", command_runner_.commands_ran_[2]);
3371 EXPECT_EQ(1u, fs_.files_created_.count("tmp.imp"));
3372 EXPECT_TRUE(builder_.AlreadyUpToDate());
3373 }
3374
TEST_F(BuildTest,DyndepBuildDiscoverNowWantEdge)3375 TEST_F(BuildTest, DyndepBuildDiscoverNowWantEdge) {
3376 // Verify that a dyndep file can be built and loaded to discover
3377 // that an edge is actually wanted due to a missing implicit output.
3378 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3379 "rule touch\n"
3380 " command = touch $out $out.imp\n"
3381 "rule cp\n"
3382 " command = cp $in $out\n"
3383 "build dd: cp dd-in\n"
3384 "build tmp: touch || dd\n"
3385 " dyndep = dd\n"
3386 "build out: touch tmp || dd\n"
3387 " dyndep = dd\n"
3388 ));
3389 fs_.Create("tmp", "");
3390 fs_.Create("out", "");
3391 fs_.Create("dd-in",
3392 "ninja_dyndep_version = 1\n"
3393 "build out: dyndep\n"
3394 "build tmp | tmp.imp: dyndep\n"
3395 );
3396
3397 string err;
3398 EXPECT_TRUE(builder_.AddTarget("out", &err));
3399 ASSERT_EQ("", err);
3400 EXPECT_TRUE(builder_.Build(&err));
3401 EXPECT_EQ("", err);
3402 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3403 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3404 EXPECT_EQ("touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3405 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[2]);
3406 }
3407
TEST_F(BuildTest,DyndepBuildDiscoverNowWantEdgeAndDependent)3408 TEST_F(BuildTest, DyndepBuildDiscoverNowWantEdgeAndDependent) {
3409 // Verify that a dyndep file can be built and loaded to discover
3410 // that an edge and a dependent are actually wanted.
3411 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3412 "rule touch\n"
3413 " command = touch $out $out.imp\n"
3414 "rule cp\n"
3415 " command = cp $in $out\n"
3416 "build dd: cp dd-in\n"
3417 "build tmp: touch || dd\n"
3418 " dyndep = dd\n"
3419 "build out: touch tmp\n"
3420 ));
3421 fs_.Create("tmp", "");
3422 fs_.Create("out", "");
3423 fs_.Create("dd-in",
3424 "ninja_dyndep_version = 1\n"
3425 "build tmp | tmp.imp: dyndep\n"
3426 );
3427
3428 string err;
3429 EXPECT_TRUE(builder_.AddTarget("out", &err));
3430 ASSERT_EQ("", err);
3431 EXPECT_TRUE(builder_.Build(&err));
3432 EXPECT_EQ("", err);
3433 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3434 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3435 EXPECT_EQ("touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3436 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[2]);
3437 }
3438
TEST_F(BuildTest,DyndepBuildDiscoverCircular)3439 TEST_F(BuildTest, DyndepBuildDiscoverCircular) {
3440 // Verify that a dyndep file can be built and loaded to discover
3441 // and reject a circular dependency.
3442 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3443 "rule r\n"
3444 " command = unused\n"
3445 "rule cp\n"
3446 " command = cp $in $out\n"
3447 "build dd: cp dd-in\n"
3448 "build out: r in || dd\n"
3449 " depfile = out.d\n"
3450 " dyndep = dd\n"
3451 "build in: r || dd\n"
3452 " dyndep = dd\n"
3453 ));
3454 fs_.Create("out.d", "out: inimp\n");
3455 fs_.Create("dd-in",
3456 "ninja_dyndep_version = 1\n"
3457 "build out | circ: dyndep\n"
3458 "build in: dyndep | circ\n"
3459 );
3460 fs_.Create("out", "");
3461
3462 string err;
3463 EXPECT_TRUE(builder_.AddTarget("out", &err));
3464 EXPECT_EQ("", err);
3465
3466 EXPECT_FALSE(builder_.Build(&err));
3467 // Depending on how the pointers in Plan::ready_ work out, we could have
3468 // discovered the cycle from either starting point.
3469 EXPECT_TRUE(err == "dependency cycle: circ -> in -> circ" ||
3470 err == "dependency cycle: in -> circ -> in");
3471 }
3472
TEST_F(BuildWithLogTest,DyndepBuildDiscoverRestat)3473 TEST_F(BuildWithLogTest, DyndepBuildDiscoverRestat) {
3474 // Verify that a dyndep file can be built and loaded to discover
3475 // that an edge has a restat binding.
3476 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3477 "rule true\n"
3478 " command = true\n"
3479 "rule cp\n"
3480 " command = cp $in $out\n"
3481 "build dd: cp dd-in\n"
3482 "build out1: true in || dd\n"
3483 " dyndep = dd\n"
3484 "build out2: cat out1\n"));
3485
3486 fs_.Create("out1", "");
3487 fs_.Create("out2", "");
3488 fs_.Create("dd-in",
3489 "ninja_dyndep_version = 1\n"
3490 "build out1: dyndep\n"
3491 " restat = 1\n"
3492 );
3493 fs_.Tick();
3494 fs_.Create("in", "");
3495
3496 // Do a pre-build so that there's commands in the log for the outputs,
3497 // otherwise, the lack of an entry in the build log will cause "out2" to
3498 // rebuild regardless of restat.
3499 string err;
3500 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3501 ASSERT_EQ("", err);
3502 EXPECT_TRUE(builder_.Build(&err));
3503 ASSERT_EQ("", err);
3504 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3505 EXPECT_EQ("cp dd-in dd", command_runner_.commands_ran_[0]);
3506 EXPECT_EQ("true", command_runner_.commands_ran_[1]);
3507 EXPECT_EQ("cat out1 > out2", command_runner_.commands_ran_[2]);
3508
3509 command_runner_.commands_ran_.clear();
3510 state_.Reset();
3511 fs_.Tick();
3512 fs_.Create("in", "");
3513
3514 // We touched "in", so we should build "out1". But because "true" does not
3515 // touch "out1", we should cancel the build of "out2".
3516 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3517 ASSERT_EQ("", err);
3518 EXPECT_TRUE(builder_.Build(&err));
3519 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3520 EXPECT_EQ("true", command_runner_.commands_ran_[0]);
3521 }
3522
TEST_F(BuildTest,DyndepBuildDiscoverScheduledEdge)3523 TEST_F(BuildTest, DyndepBuildDiscoverScheduledEdge) {
3524 // Verify that a dyndep file can be built and loaded to discover a
3525 // new input that itself is an output from an edge that has already
3526 // been scheduled but not finished. We should not re-schedule it.
3527 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3528 "rule touch\n"
3529 " command = touch $out $out.imp\n"
3530 "rule cp\n"
3531 " command = cp $in $out\n"
3532 "build out1 | out1.imp: touch\n"
3533 "build zdd: cp zdd-in\n"
3534 " verify_active_edge = out1\n" // verify out1 is active when zdd is finished
3535 "build out2: cp out1 || zdd\n"
3536 " dyndep = zdd\n"
3537 ));
3538 fs_.Create("zdd-in",
3539 "ninja_dyndep_version = 1\n"
3540 "build out2: dyndep | out1.imp\n"
3541 );
3542
3543 // Enable concurrent builds so that we can load the dyndep file
3544 // while another edge is still active.
3545 command_runner_.max_active_edges_ = 2;
3546
3547 // During the build "out1" and "zdd" should be built concurrently.
3548 // The fake command runner will finish these in reverse order
3549 // of the names of the first outputs, so "zdd" will finish first
3550 // and we will load the dyndep file while the edge for "out1" is
3551 // still active. This will add a new dependency on "out1.imp",
3552 // also produced by the active edge. The builder should not
3553 // re-schedule the already-active edge.
3554
3555 string err;
3556 EXPECT_TRUE(builder_.AddTarget("out1", &err));
3557 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3558 ASSERT_EQ("", err);
3559 EXPECT_TRUE(builder_.Build(&err));
3560 EXPECT_EQ("", err);
3561 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3562 // Depending on how the pointers in Plan::ready_ work out, the first
3563 // two commands may have run in either order.
3564 EXPECT_TRUE((command_runner_.commands_ran_[0] == "touch out1 out1.imp" &&
3565 command_runner_.commands_ran_[1] == "cp zdd-in zdd") ||
3566 (command_runner_.commands_ran_[1] == "touch out1 out1.imp" &&
3567 command_runner_.commands_ran_[0] == "cp zdd-in zdd"));
3568 EXPECT_EQ("cp out1 out2", command_runner_.commands_ran_[2]);
3569 }
3570
TEST_F(BuildTest,DyndepTwoLevelDirect)3571 TEST_F(BuildTest, DyndepTwoLevelDirect) {
3572 // Verify that a clean dyndep file can depend on a dirty dyndep file
3573 // and be loaded properly after the dirty one is built and loaded.
3574 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3575 "rule touch\n"
3576 " command = touch $out $out.imp\n"
3577 "rule cp\n"
3578 " command = cp $in $out\n"
3579 "build dd1: cp dd1-in\n"
3580 "build out1 | out1.imp: touch || dd1\n"
3581 " dyndep = dd1\n"
3582 "build dd2: cp dd2-in || dd1\n" // direct order-only dep on dd1
3583 "build out2: touch || dd2\n"
3584 " dyndep = dd2\n"
3585 ));
3586 fs_.Create("out1.imp", "");
3587 fs_.Create("out2", "");
3588 fs_.Create("out2.imp", "");
3589 fs_.Create("dd1-in",
3590 "ninja_dyndep_version = 1\n"
3591 "build out1: dyndep\n"
3592 );
3593 fs_.Create("dd2-in", "");
3594 fs_.Create("dd2",
3595 "ninja_dyndep_version = 1\n"
3596 "build out2 | out2.imp: dyndep | out1.imp\n"
3597 );
3598
3599 // During the build dd1 should be built and loaded. The RecomputeDirty
3600 // called as a result of loading dd1 should not cause dd2 to be loaded
3601 // because the builder will never get a chance to update the build plan
3602 // to account for dd2. Instead dd2 should only be later loaded once the
3603 // builder recognizes that it is now ready (as its order-only dependency
3604 // on dd1 has been satisfied). This test case verifies that each dyndep
3605 // file is loaded to update the build graph independently.
3606
3607 string err;
3608 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3609 ASSERT_EQ("", err);
3610 EXPECT_TRUE(builder_.Build(&err));
3611 EXPECT_EQ("", err);
3612 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3613 EXPECT_EQ("cp dd1-in dd1", command_runner_.commands_ran_[0]);
3614 EXPECT_EQ("touch out1 out1.imp", command_runner_.commands_ran_[1]);
3615 EXPECT_EQ("touch out2 out2.imp", command_runner_.commands_ran_[2]);
3616 }
3617
TEST_F(BuildTest,DyndepTwoLevelIndirect)3618 TEST_F(BuildTest, DyndepTwoLevelIndirect) {
3619 // Verify that dyndep files can add to an edge new implicit inputs that
3620 // correspond to implicit outputs added to other edges by other dyndep
3621 // files on which they (order-only) depend.
3622 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3623 "rule touch\n"
3624 " command = touch $out $out.imp\n"
3625 "rule cp\n"
3626 " command = cp $in $out\n"
3627 "build dd1: cp dd1-in\n"
3628 "build out1: touch || dd1\n"
3629 " dyndep = dd1\n"
3630 "build dd2: cp dd2-in || out1\n" // indirect order-only dep on dd1
3631 "build out2: touch || dd2\n"
3632 " dyndep = dd2\n"
3633 ));
3634 fs_.Create("out1.imp", "");
3635 fs_.Create("out2", "");
3636 fs_.Create("out2.imp", "");
3637 fs_.Create("dd1-in",
3638 "ninja_dyndep_version = 1\n"
3639 "build out1 | out1.imp: dyndep\n"
3640 );
3641 fs_.Create("dd2-in", "");
3642 fs_.Create("dd2",
3643 "ninja_dyndep_version = 1\n"
3644 "build out2 | out2.imp: dyndep | out1.imp\n"
3645 );
3646
3647 // During the build dd1 should be built and loaded. Then dd2 should
3648 // be built and loaded. Loading dd2 should cause the builder to
3649 // recognize that out2 needs to be built even though it was originally
3650 // clean without dyndep info.
3651
3652 string err;
3653 EXPECT_TRUE(builder_.AddTarget("out2", &err));
3654 ASSERT_EQ("", err);
3655 EXPECT_TRUE(builder_.Build(&err));
3656 EXPECT_EQ("", err);
3657 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3658 EXPECT_EQ("cp dd1-in dd1", command_runner_.commands_ran_[0]);
3659 EXPECT_EQ("touch out1 out1.imp", command_runner_.commands_ran_[1]);
3660 EXPECT_EQ("touch out2 out2.imp", command_runner_.commands_ran_[2]);
3661 }
3662
TEST_F(BuildTest,DyndepTwoLevelDiscoveredReady)3663 TEST_F(BuildTest, DyndepTwoLevelDiscoveredReady) {
3664 // Verify that a dyndep file can discover a new input whose
3665 // edge also has a dyndep file that is ready to load immediately.
3666 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3667 "rule touch\n"
3668 " command = touch $out\n"
3669 "rule cp\n"
3670 " command = cp $in $out\n"
3671 "build dd0: cp dd0-in\n"
3672 "build dd1: cp dd1-in\n"
3673 "build in: touch\n"
3674 "build tmp: touch || dd0\n"
3675 " dyndep = dd0\n"
3676 "build out: touch || dd1\n"
3677 " dyndep = dd1\n"
3678 ));
3679 fs_.Create("dd1-in",
3680 "ninja_dyndep_version = 1\n"
3681 "build out: dyndep | tmp\n"
3682 );
3683 fs_.Create("dd0-in", "");
3684 fs_.Create("dd0",
3685 "ninja_dyndep_version = 1\n"
3686 "build tmp: dyndep | in\n"
3687 );
3688 fs_.Tick();
3689 fs_.Create("out", "");
3690
3691 string err;
3692 EXPECT_TRUE(builder_.AddTarget("out", &err));
3693 EXPECT_EQ("", err);
3694
3695 EXPECT_TRUE(builder_.Build(&err));
3696 EXPECT_EQ("", err);
3697 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3698 EXPECT_EQ("cp dd1-in dd1", command_runner_.commands_ran_[0]);
3699 EXPECT_EQ("touch in", command_runner_.commands_ran_[1]);
3700 EXPECT_EQ("touch tmp", command_runner_.commands_ran_[2]);
3701 EXPECT_EQ("touch out", command_runner_.commands_ran_[3]);
3702 }
3703
TEST_F(BuildTest,DyndepTwoLevelDiscoveredDirty)3704 TEST_F(BuildTest, DyndepTwoLevelDiscoveredDirty) {
3705 // Verify that a dyndep file can discover a new input whose
3706 // edge also has a dyndep file that needs to be built.
3707 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3708 "rule touch\n"
3709 " command = touch $out\n"
3710 "rule cp\n"
3711 " command = cp $in $out\n"
3712 "build dd0: cp dd0-in\n"
3713 "build dd1: cp dd1-in\n"
3714 "build in: touch\n"
3715 "build tmp: touch || dd0\n"
3716 " dyndep = dd0\n"
3717 "build out: touch || dd1\n"
3718 " dyndep = dd1\n"
3719 ));
3720 fs_.Create("dd1-in",
3721 "ninja_dyndep_version = 1\n"
3722 "build out: dyndep | tmp\n"
3723 );
3724 fs_.Create("dd0-in",
3725 "ninja_dyndep_version = 1\n"
3726 "build tmp: dyndep | in\n"
3727 );
3728 fs_.Tick();
3729 fs_.Create("out", "");
3730
3731 string err;
3732 EXPECT_TRUE(builder_.AddTarget("out", &err));
3733 EXPECT_EQ("", err);
3734
3735 EXPECT_TRUE(builder_.Build(&err));
3736 EXPECT_EQ("", err);
3737 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
3738 EXPECT_EQ("cp dd1-in dd1", command_runner_.commands_ran_[0]);
3739 EXPECT_EQ("cp dd0-in dd0", command_runner_.commands_ran_[1]);
3740 EXPECT_EQ("touch in", command_runner_.commands_ran_[2]);
3741 EXPECT_EQ("touch tmp", command_runner_.commands_ran_[3]);
3742 EXPECT_EQ("touch out", command_runner_.commands_ran_[4]);
3743 }
3744
TEST_F(BuildTest,Validation)3745 TEST_F(BuildTest, Validation) {
3746 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3747 "build out: cat in |@ validate\n"
3748 "build validate: cat in2\n"));
3749
3750 fs_.Create("in", "");
3751 fs_.Create("in2", "");
3752
3753 string err;
3754 EXPECT_TRUE(builder_.AddTarget("out", &err));
3755 EXPECT_EQ("", err);
3756
3757 EXPECT_TRUE(builder_.Build(&err));
3758 EXPECT_EQ("", err);
3759
3760 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3761
3762 // Test touching "in" only rebuilds "out" ("validate" doesn't depend on
3763 // "out").
3764 fs_.Tick();
3765 fs_.Create("in", "");
3766
3767 err.clear();
3768 command_runner_.commands_ran_.clear();
3769 state_.Reset();
3770 EXPECT_TRUE(builder_.AddTarget("out", &err));
3771 ASSERT_EQ("", err);
3772
3773 EXPECT_TRUE(builder_.Build(&err));
3774 EXPECT_EQ("", err);
3775
3776 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3777 EXPECT_EQ("cat in > out", command_runner_.commands_ran_[0]);
3778
3779 // Test touching "in2" only rebuilds "validate" ("out" doesn't depend on
3780 // "validate").
3781 fs_.Tick();
3782 fs_.Create("in2", "");
3783
3784 err.clear();
3785 command_runner_.commands_ran_.clear();
3786 state_.Reset();
3787 EXPECT_TRUE(builder_.AddTarget("out", &err));
3788 ASSERT_EQ("", err);
3789
3790 EXPECT_TRUE(builder_.Build(&err));
3791 EXPECT_EQ("", err);
3792
3793 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3794 EXPECT_EQ("cat in2 > validate", command_runner_.commands_ran_[0]);
3795 }
3796
TEST_F(BuildTest,ValidationDependsOnOutput)3797 TEST_F(BuildTest, ValidationDependsOnOutput) {
3798 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3799 "build out: cat in |@ validate\n"
3800 "build validate: cat in2 | out\n"));
3801
3802 fs_.Create("in", "");
3803 fs_.Create("in2", "");
3804
3805 string err;
3806 EXPECT_TRUE(builder_.AddTarget("out", &err));
3807 EXPECT_EQ("", err);
3808
3809 EXPECT_TRUE(builder_.Build(&err));
3810 EXPECT_EQ("", err);
3811
3812 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3813
3814 // Test touching "in" rebuilds "out" and "validate".
3815 fs_.Tick();
3816 fs_.Create("in", "");
3817
3818 err.clear();
3819 command_runner_.commands_ran_.clear();
3820 state_.Reset();
3821 EXPECT_TRUE(builder_.AddTarget("out", &err));
3822 ASSERT_EQ("", err);
3823
3824 EXPECT_TRUE(builder_.Build(&err));
3825 EXPECT_EQ("", err);
3826
3827 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3828
3829 // Test touching "in2" only rebuilds "validate" ("out" doesn't depend on
3830 // "validate").
3831 fs_.Tick();
3832 fs_.Create("in2", "");
3833
3834 err.clear();
3835 command_runner_.commands_ran_.clear();
3836 state_.Reset();
3837 EXPECT_TRUE(builder_.AddTarget("out", &err));
3838 ASSERT_EQ("", err);
3839
3840 EXPECT_TRUE(builder_.Build(&err));
3841 EXPECT_EQ("", err);
3842
3843 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3844 EXPECT_EQ("cat in2 > validate", command_runner_.commands_ran_[0]);
3845 }
3846
TEST_F(BuildWithDepsLogTest,ValidationThroughDepfile)3847 TEST_F(BuildWithDepsLogTest, ValidationThroughDepfile) {
3848 const char* manifest =
3849 "build out: cat in |@ validate\n"
3850 "build validate: cat in2 | out\n"
3851 "build out2: cat in3\n"
3852 " deps = gcc\n"
3853 " depfile = out2.d\n";
3854
3855 string err;
3856
3857 {
3858 fs_.Create("in", "");
3859 fs_.Create("in2", "");
3860 fs_.Create("in3", "");
3861 fs_.Create("out2.d", "out: out");
3862
3863 State state;
3864 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3865 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3866
3867 DepsLog deps_log;
3868 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3869 ASSERT_EQ("", err);
3870
3871 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3872 builder.command_runner_.reset(&command_runner_);
3873
3874 EXPECT_TRUE(builder.AddTarget("out2", &err));
3875 ASSERT_EQ("", err);
3876
3877 EXPECT_TRUE(builder.Build(&err));
3878 EXPECT_EQ("", err);
3879
3880 // On the first build, only the out2 command is run.
3881 ASSERT_EQ(command_runner_.commands_ran_.size(), 1);
3882 EXPECT_EQ("cat in3 > out2", command_runner_.commands_ran_[0]);
3883
3884 // The deps file should have been removed.
3885 EXPECT_EQ(0, fs_.Stat("out2.d", &err));
3886
3887 deps_log.Close();
3888 builder.command_runner_.release();
3889 }
3890
3891 fs_.Tick();
3892 command_runner_.commands_ran_.clear();
3893
3894 {
3895 fs_.Create("in2", "");
3896 fs_.Create("in3", "");
3897
3898 State state;
3899 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3900 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3901
3902 DepsLog deps_log;
3903 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
3904 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3905 ASSERT_EQ("", err);
3906
3907 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3908 builder.command_runner_.reset(&command_runner_);
3909
3910 EXPECT_TRUE(builder.AddTarget("out2", &err));
3911 ASSERT_EQ("", err);
3912
3913 EXPECT_TRUE(builder.Build(&err));
3914 EXPECT_EQ("", err);
3915
3916 // The out and validate actions should have been run as well as out2.
3917 ASSERT_EQ(command_runner_.commands_ran_.size(), 3);
3918 // out has to run first, as both out2 and validate depend on it.
3919 EXPECT_EQ("cat in > out", command_runner_.commands_ran_[0]);
3920
3921 deps_log.Close();
3922 builder.command_runner_.release();
3923 }
3924 }
3925
TEST_F(BuildTest,ValidationCircular)3926 TEST_F(BuildTest, ValidationCircular) {
3927 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3928 "build out: cat in |@ out2\n"
3929 "build out2: cat in2 |@ out\n"));
3930
3931 fs_.Create("in", "");
3932 fs_.Create("in2", "");
3933
3934 string err;
3935 EXPECT_TRUE(builder_.AddTarget("out", &err));
3936 EXPECT_EQ("", err);
3937
3938 EXPECT_TRUE(builder_.Build(&err));
3939 EXPECT_EQ("", err);
3940
3941 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3942
3943 // Test touching "in" rebuilds "out".
3944 fs_.Tick();
3945 fs_.Create("in", "");
3946
3947 err.clear();
3948 command_runner_.commands_ran_.clear();
3949 state_.Reset();
3950 EXPECT_TRUE(builder_.AddTarget("out", &err));
3951 ASSERT_EQ("", err);
3952
3953 EXPECT_TRUE(builder_.Build(&err));
3954 EXPECT_EQ("", err);
3955
3956 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3957 EXPECT_EQ("cat in > out", command_runner_.commands_ran_[0]);
3958
3959 // Test touching "in2" rebuilds "out2".
3960 fs_.Tick();
3961 fs_.Create("in2", "");
3962
3963 err.clear();
3964 command_runner_.commands_ran_.clear();
3965 state_.Reset();
3966 EXPECT_TRUE(builder_.AddTarget("out", &err));
3967 ASSERT_EQ("", err);
3968
3969 EXPECT_TRUE(builder_.Build(&err));
3970 EXPECT_EQ("", err);
3971
3972 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3973 EXPECT_EQ("cat in2 > out2", command_runner_.commands_ran_[0]);
3974 }
3975
TEST_F(BuildTest,ValidationWithCircularDependency)3976 TEST_F(BuildTest, ValidationWithCircularDependency) {
3977 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3978 "build out: cat in |@ validate\n"
3979 "build validate: cat validate_in | out\n"
3980 "build validate_in: cat validate\n"));
3981
3982 fs_.Create("in", "");
3983
3984 string err;
3985 EXPECT_FALSE(builder_.AddTarget("out", &err));
3986 EXPECT_EQ("dependency cycle: validate -> validate_in -> validate", err);
3987 }
3988