1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
19 #include "build_log.h"
24 /// Fixture for tests involving Plan.
25 // Though Plan doesn't use State, it's useful to have one around
26 // to create Nodes and Edges.
27 struct PlanTest : public StateTestWithBuiltinRules {
30 /// Because FindWork does not return Edges in any sort of predictable order,
31 // provide a means to get available Edges in order and in a format which is
32 // easy to write tests around.
33 void FindWorkSorted(deque<Edge*>* ret, int count) {
34 struct CompareEdgesByOutput {
35 static bool cmp(const Edge* a, const Edge* b) {
36 return a->outputs_[0]->path() < b->outputs_[0]->path();
40 for (int i = 0; i < count; ++i) {
41 ASSERT_TRUE(plan_.more_to_do());
42 Edge* edge = plan_.FindWork();
46 ASSERT_FALSE(plan_.FindWork());
47 sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp);
50 void TestPoolWithDepthOne(const char *test_case);
53 TEST_F(PlanTest, Basic) {
54 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
55 "build out: cat mid\n"
56 "build mid: cat in\n"));
57 GetNode("mid")->MarkDirty();
58 GetNode("out")->MarkDirty();
60 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
62 ASSERT_TRUE(plan_.more_to_do());
64 Edge* edge = plan_.FindWork();
66 ASSERT_EQ("in", edge->inputs_[0]->path());
67 ASSERT_EQ("mid", edge->outputs_[0]->path());
69 ASSERT_FALSE(plan_.FindWork());
71 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
73 edge = plan_.FindWork();
75 ASSERT_EQ("mid", edge->inputs_[0]->path());
76 ASSERT_EQ("out", edge->outputs_[0]->path());
78 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
80 ASSERT_FALSE(plan_.more_to_do());
81 edge = plan_.FindWork();
85 // Test that two outputs from one rule can be handled as inputs to the next.
86 TEST_F(PlanTest, DoubleOutputDirect) {
87 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
88 "build out: cat mid1 mid2\n"
89 "build mid1 mid2: cat in\n"));
90 GetNode("mid1")->MarkDirty();
91 GetNode("mid2")->MarkDirty();
92 GetNode("out")->MarkDirty();
95 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
97 ASSERT_TRUE(plan_.more_to_do());
100 edge = plan_.FindWork();
101 ASSERT_TRUE(edge); // cat in
102 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
104 edge = plan_.FindWork();
105 ASSERT_TRUE(edge); // cat mid1 mid2
106 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
108 edge = plan_.FindWork();
109 ASSERT_FALSE(edge); // done
112 // Test that two outputs from one rule can eventually be routed to another.
113 TEST_F(PlanTest, DoubleOutputIndirect) {
114 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
115 "build out: cat b1 b2\n"
118 "build a1 a2: cat in\n"));
119 GetNode("a1")->MarkDirty();
120 GetNode("a2")->MarkDirty();
121 GetNode("b1")->MarkDirty();
122 GetNode("b2")->MarkDirty();
123 GetNode("out")->MarkDirty();
125 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
127 ASSERT_TRUE(plan_.more_to_do());
130 edge = plan_.FindWork();
131 ASSERT_TRUE(edge); // cat in
132 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
134 edge = plan_.FindWork();
135 ASSERT_TRUE(edge); // cat a1
136 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
138 edge = plan_.FindWork();
139 ASSERT_TRUE(edge); // cat a2
140 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
142 edge = plan_.FindWork();
143 ASSERT_TRUE(edge); // cat b1 b2
144 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
146 edge = plan_.FindWork();
147 ASSERT_FALSE(edge); // done
150 // Test that two edges from one output can both execute.
151 TEST_F(PlanTest, DoubleDependent) {
152 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
153 "build out: cat a1 a2\n"
154 "build a1: cat mid\n"
155 "build a2: cat mid\n"
156 "build mid: cat in\n"));
157 GetNode("mid")->MarkDirty();
158 GetNode("a1")->MarkDirty();
159 GetNode("a2")->MarkDirty();
160 GetNode("out")->MarkDirty();
163 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
165 ASSERT_TRUE(plan_.more_to_do());
168 edge = plan_.FindWork();
169 ASSERT_TRUE(edge); // cat in
170 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
172 edge = plan_.FindWork();
173 ASSERT_TRUE(edge); // cat mid
174 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
176 edge = plan_.FindWork();
177 ASSERT_TRUE(edge); // cat mid
178 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
180 edge = plan_.FindWork();
181 ASSERT_TRUE(edge); // cat a1 a2
182 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
184 edge = plan_.FindWork();
185 ASSERT_FALSE(edge); // done
188 void PlanTest::TestPoolWithDepthOne(const char* test_case) {
189 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, test_case));
190 GetNode("out1")->MarkDirty();
191 GetNode("out2")->MarkDirty();
193 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
195 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
197 ASSERT_TRUE(plan_.more_to_do());
199 Edge* edge = plan_.FindWork();
201 ASSERT_EQ("in", edge->inputs_[0]->path());
202 ASSERT_EQ("out1", edge->outputs_[0]->path());
204 // This will be false since poolcat is serialized
205 ASSERT_FALSE(plan_.FindWork());
207 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
209 edge = plan_.FindWork();
211 ASSERT_EQ("in", edge->inputs_[0]->path());
212 ASSERT_EQ("out2", edge->outputs_[0]->path());
214 ASSERT_FALSE(plan_.FindWork());
216 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
218 ASSERT_FALSE(plan_.more_to_do());
219 edge = plan_.FindWork();
223 TEST_F(PlanTest, PoolWithDepthOne) {
224 TestPoolWithDepthOne(
228 " command = cat $in > $out\n"
230 "build out1: poolcat in\n"
231 "build out2: poolcat in\n");
234 TEST_F(PlanTest, ConsolePool) {
235 TestPoolWithDepthOne(
237 " command = cat $in > $out\n"
239 "build out1: poolcat in\n"
240 "build out2: poolcat in\n");
243 TEST_F(PlanTest, PoolsWithDepthTwo) {
244 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
250 " command = cat $in > $out\n"
253 " command = cat $in > $out\n"
255 "build out1: foocat in\n"
256 "build out2: foocat in\n"
257 "build out3: foocat in\n"
258 "build outb1: bazcat in\n"
259 "build outb2: bazcat in\n"
260 "build outb3: bazcat in\n"
262 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
264 // Mark all the out* nodes dirty
265 for (int i = 0; i < 3; ++i) {
266 GetNode("out" + string(1, '1' + static_cast<char>(i)))->MarkDirty();
267 GetNode("outb" + string(1, '1' + static_cast<char>(i)))->MarkDirty();
269 GetNode("allTheThings")->MarkDirty();
272 EXPECT_TRUE(plan_.AddTarget(GetNode("allTheThings"), &err));
276 FindWorkSorted(&edges, 5);
278 for (int i = 0; i < 4; ++i) {
279 Edge *edge = edges[i];
280 ASSERT_EQ("in", edge->inputs_[0]->path());
281 string base_name(i < 2 ? "out" : "outb");
282 ASSERT_EQ(base_name + string(1, '1' + (i % 2)), edge->outputs_[0]->path());
285 // outb3 is exempt because it has an empty pool
286 Edge* edge = edges[4];
288 ASSERT_EQ("in", edge->inputs_[0]->path());
289 ASSERT_EQ("outb3", edge->outputs_[0]->path());
292 plan_.EdgeFinished(edges.front(), Plan::kEdgeSucceeded);
295 // out3 should be available
296 Edge* out3 = plan_.FindWork();
298 ASSERT_EQ("in", out3->inputs_[0]->path());
299 ASSERT_EQ("out3", out3->outputs_[0]->path());
301 ASSERT_FALSE(plan_.FindWork());
303 plan_.EdgeFinished(out3, Plan::kEdgeSucceeded);
305 ASSERT_FALSE(plan_.FindWork());
307 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
308 plan_.EdgeFinished(*it, Plan::kEdgeSucceeded);
311 Edge* last = plan_.FindWork();
313 ASSERT_EQ("allTheThings", last->outputs_[0]->path());
315 plan_.EdgeFinished(last, Plan::kEdgeSucceeded);
317 ASSERT_FALSE(plan_.more_to_do());
318 ASSERT_FALSE(plan_.FindWork());
321 TEST_F(PlanTest, PoolWithRedundantEdges) {
322 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
326 " command = touch foo.cpp\n"
328 " command = touch bar.cpp\n"
330 " command = echo $out > $out\n"
331 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
333 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
335 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
336 "build foo.cpp: gen_foo\n"
337 "build bar.cpp: gen_bar\n"
338 "build all: phony libfoo.a\n"));
339 GetNode("foo.cpp")->MarkDirty();
340 GetNode("foo.cpp.obj")->MarkDirty();
341 GetNode("bar.cpp")->MarkDirty();
342 GetNode("bar.cpp.obj")->MarkDirty();
343 GetNode("libfoo.a")->MarkDirty();
344 GetNode("all")->MarkDirty();
346 EXPECT_TRUE(plan_.AddTarget(GetNode("all"), &err));
348 ASSERT_TRUE(plan_.more_to_do());
352 deque<Edge*> initial_edges;
353 FindWorkSorted(&initial_edges, 2);
355 edge = initial_edges[1]; // Foo first
356 ASSERT_EQ("foo.cpp", edge->outputs_[0]->path());
357 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
359 edge = plan_.FindWork();
361 ASSERT_FALSE(plan_.FindWork());
362 ASSERT_EQ("foo.cpp", edge->inputs_[0]->path());
363 ASSERT_EQ("foo.cpp", edge->inputs_[1]->path());
364 ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path());
365 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
367 edge = initial_edges[0]; // Now for bar
368 ASSERT_EQ("bar.cpp", edge->outputs_[0]->path());
369 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
371 edge = plan_.FindWork();
373 ASSERT_FALSE(plan_.FindWork());
374 ASSERT_EQ("bar.cpp", edge->inputs_[0]->path());
375 ASSERT_EQ("bar.cpp", edge->inputs_[1]->path());
376 ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path());
377 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
379 edge = plan_.FindWork();
381 ASSERT_FALSE(plan_.FindWork());
382 ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path());
383 ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path());
384 ASSERT_EQ("libfoo.a", edge->outputs_[0]->path());
385 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
387 edge = plan_.FindWork();
389 ASSERT_FALSE(plan_.FindWork());
390 ASSERT_EQ("libfoo.a", edge->inputs_[0]->path());
391 ASSERT_EQ("all", edge->outputs_[0]->path());
392 plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
394 edge = plan_.FindWork();
396 ASSERT_FALSE(plan_.more_to_do());
399 TEST_F(PlanTest, PoolWithFailingEdge) {
400 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
404 " command = cat $in > $out\n"
406 "build out1: poolcat in\n"
407 "build out2: poolcat in\n"));
408 GetNode("out1")->MarkDirty();
409 GetNode("out2")->MarkDirty();
411 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
413 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
415 ASSERT_TRUE(plan_.more_to_do());
417 Edge* edge = plan_.FindWork();
419 ASSERT_EQ("in", edge->inputs_[0]->path());
420 ASSERT_EQ("out1", edge->outputs_[0]->path());
422 // This will be false since poolcat is serialized
423 ASSERT_FALSE(plan_.FindWork());
425 plan_.EdgeFinished(edge, Plan::kEdgeFailed);
427 edge = plan_.FindWork();
429 ASSERT_EQ("in", edge->inputs_[0]->path());
430 ASSERT_EQ("out2", edge->outputs_[0]->path());
432 ASSERT_FALSE(plan_.FindWork());
434 plan_.EdgeFinished(edge, Plan::kEdgeFailed);
436 ASSERT_TRUE(plan_.more_to_do()); // Jobs have failed
437 edge = plan_.FindWork();
441 /// Fake implementation of CommandRunner, useful for tests.
442 struct FakeCommandRunner : public CommandRunner {
443 explicit FakeCommandRunner(VirtualFileSystem* fs) :
444 last_command_(NULL), fs_(fs) {}
446 // CommandRunner impl
447 virtual bool CanRunMore();
448 virtual bool StartCommand(Edge* edge);
449 virtual bool WaitForCommand(Result* result);
450 virtual vector<Edge*> GetActiveEdges();
451 virtual void Abort();
453 vector<string> commands_ran_;
455 VirtualFileSystem* fs_;
458 struct BuildTest : public StateTestWithBuiltinRules, public BuildLogUser {
459 BuildTest() : config_(MakeConfig()), command_runner_(&fs_),
460 builder_(&state_, config_, NULL, NULL, &fs_),
464 virtual void SetUp() {
465 StateTestWithBuiltinRules::SetUp();
467 builder_.command_runner_.reset(&command_runner_);
469 "build cat1: cat in1\n"
470 "build cat2: cat in1 in2\n"
471 "build cat12: cat cat1 cat2\n");
473 fs_.Create("in1", "");
474 fs_.Create("in2", "");
478 builder_.command_runner_.release();
481 virtual bool IsPathDead(StringPiece s) const { return false; }
483 /// Rebuild target in the 'working tree' (fs_).
484 /// State of command_runner_ and logs contents (if specified) ARE MODIFIED.
485 /// Handy to check for NOOP builds, and higher-level rebuild tests.
486 void RebuildTarget(const string& target, const char* manifest,
487 const char* log_path = NULL, const char* deps_path = NULL,
488 State* state = NULL);
490 // Mark a path dirty.
491 void Dirty(const string& path);
493 BuildConfig MakeConfig() {
495 config.verbosity = BuildConfig::QUIET;
500 FakeCommandRunner command_runner_;
501 VirtualFileSystem fs_;
507 void BuildTest::RebuildTarget(const string& target, const char* manifest,
508 const char* log_path, const char* deps_path,
510 State local_state, *pstate = &local_state;
513 ASSERT_NO_FATAL_FAILURE(AddCatRule(pstate));
514 AssertParse(pstate, manifest);
517 BuildLog build_log, *pbuild_log = NULL;
519 ASSERT_TRUE(build_log.Load(log_path, &err));
520 ASSERT_TRUE(build_log.OpenForWrite(log_path, *this, &err));
522 pbuild_log = &build_log;
525 DepsLog deps_log, *pdeps_log = NULL;
527 ASSERT_TRUE(deps_log.Load(deps_path, pstate, &err));
528 ASSERT_TRUE(deps_log.OpenForWrite(deps_path, &err));
530 pdeps_log = &deps_log;
533 Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_);
534 EXPECT_TRUE(builder.AddTarget(target, &err));
536 command_runner_.commands_ran_.clear();
537 builder.command_runner_.reset(&command_runner_);
538 if (!builder.AlreadyUpToDate()) {
539 bool build_res = builder.Build(&err);
540 EXPECT_TRUE(build_res);
542 builder.command_runner_.release();
545 bool FakeCommandRunner::CanRunMore() {
546 // Only run one at a time.
547 return last_command_ == NULL;
550 bool FakeCommandRunner::StartCommand(Edge* edge) {
551 assert(!last_command_);
552 commands_ran_.push_back(edge->EvaluateCommand());
553 if (edge->rule().name() == "cat" ||
554 edge->rule().name() == "cat_rsp" ||
555 edge->rule().name() == "cat_rsp_out" ||
556 edge->rule().name() == "cc" ||
557 edge->rule().name() == "touch" ||
558 edge->rule().name() == "touch-interrupt" ||
559 edge->rule().name() == "touch-fail-tick2") {
560 for (vector<Node*>::iterator out = edge->outputs_.begin();
561 out != edge->outputs_.end(); ++out) {
562 fs_->Create((*out)->path(), "");
564 } else if (edge->rule().name() == "true" ||
565 edge->rule().name() == "fail" ||
566 edge->rule().name() == "interrupt" ||
567 edge->rule().name() == "console") {
568 // Don't do anything.
570 printf("unknown command\n");
574 last_command_ = edge;
578 bool FakeCommandRunner::WaitForCommand(Result* result) {
582 Edge* edge = last_command_;
585 if (edge->rule().name() == "interrupt" ||
586 edge->rule().name() == "touch-interrupt") {
587 result->status = ExitInterrupted;
591 if (edge->rule().name() == "console") {
592 if (edge->use_console())
593 result->status = ExitSuccess;
595 result->status = ExitFailure;
596 last_command_ = NULL;
600 if (edge->rule().name() == "fail" ||
601 (edge->rule().name() == "touch-fail-tick2" && fs_->now_ == 2))
602 result->status = ExitFailure;
604 result->status = ExitSuccess;
605 last_command_ = NULL;
609 vector<Edge*> FakeCommandRunner::GetActiveEdges() {
612 edges.push_back(last_command_);
616 void FakeCommandRunner::Abort() {
617 last_command_ = NULL;
620 void BuildTest::Dirty(const string& path) {
621 Node* node = GetNode(path);
624 // If it's an input file, mark that we've already stat()ed it and
626 if (!node->in_edge())
630 TEST_F(BuildTest, NoWork) {
632 EXPECT_TRUE(builder_.AlreadyUpToDate());
635 TEST_F(BuildTest, OneStep) {
636 // Given a dirty target with one ready input,
637 // we should rebuild the target.
640 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
642 EXPECT_TRUE(builder_.Build(&err));
645 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
646 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
649 TEST_F(BuildTest, OneStep2) {
650 // Given a target with one dirty input,
651 // we should rebuild the target.
654 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
656 EXPECT_TRUE(builder_.Build(&err));
659 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
660 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
663 TEST_F(BuildTest, TwoStep) {
665 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
667 EXPECT_TRUE(builder_.Build(&err));
669 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
670 // Depending on how the pointers work out, we could've ran
671 // the first two commands in either order.
672 EXPECT_TRUE((command_runner_.commands_ran_[0] == "cat in1 > cat1" &&
673 command_runner_.commands_ran_[1] == "cat in1 in2 > cat2") ||
674 (command_runner_.commands_ran_[1] == "cat in1 > cat1" &&
675 command_runner_.commands_ran_[0] == "cat in1 in2 > cat2"));
677 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
681 // Modifying in2 requires rebuilding one intermediate file
682 // and the final file.
683 fs_.Create("in2", "");
685 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
687 EXPECT_TRUE(builder_.Build(&err));
689 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
690 EXPECT_EQ("cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
691 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
694 TEST_F(BuildTest, TwoOutputs) {
695 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
697 " command = touch $out\n"
698 "build out1 out2: touch in.txt\n"));
700 fs_.Create("in.txt", "");
703 EXPECT_TRUE(builder_.AddTarget("out1", &err));
705 EXPECT_TRUE(builder_.Build(&err));
707 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
708 EXPECT_EQ("touch out1 out2", command_runner_.commands_ran_[0]);
711 TEST_F(BuildTest, ImplicitOutput) {
712 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
714 " command = touch $out $out.imp\n"
715 "build out | out.imp: touch in.txt\n"));
716 fs_.Create("in.txt", "");
719 EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
721 EXPECT_TRUE(builder_.Build(&err));
723 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
724 EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[0]);
728 // https://github.com/ninja-build/ninja/issues/148
729 TEST_F(BuildTest, MultiOutIn) {
730 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
732 " command = touch $out\n"
733 "build in1 otherfile: touch in\n"
734 "build out: touch in | in1\n"));
736 fs_.Create("in", "");
738 fs_.Create("in1", "");
741 EXPECT_TRUE(builder_.AddTarget("out", &err));
743 EXPECT_TRUE(builder_.Build(&err));
747 TEST_F(BuildTest, Chain) {
748 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
752 "build c5: cat c4\n"));
754 fs_.Create("c1", "");
757 EXPECT_TRUE(builder_.AddTarget("c5", &err));
759 EXPECT_TRUE(builder_.Build(&err));
761 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
764 command_runner_.commands_ran_.clear();
766 EXPECT_TRUE(builder_.AddTarget("c5", &err));
768 EXPECT_TRUE(builder_.AlreadyUpToDate());
772 fs_.Create("c3", "");
774 command_runner_.commands_ran_.clear();
776 EXPECT_TRUE(builder_.AddTarget("c5", &err));
778 EXPECT_FALSE(builder_.AlreadyUpToDate());
779 EXPECT_TRUE(builder_.Build(&err));
780 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // 3->4, 4->5
783 TEST_F(BuildTest, MissingInput) {
784 // Input is referenced by build file, but no rule for it.
787 EXPECT_FALSE(builder_.AddTarget("cat1", &err));
788 EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it",
792 TEST_F(BuildTest, MissingTarget) {
793 // Target is not referenced by build file.
795 EXPECT_FALSE(builder_.AddTarget("meow", &err));
796 EXPECT_EQ("unknown target: 'meow'", err);
799 TEST_F(BuildTest, MakeDirs) {
803 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
804 "build subdir\\dir2\\file: cat in1\n"));
806 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
807 "build subdir/dir2/file: cat in1\n"));
809 EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err));
812 EXPECT_TRUE(builder_.Build(&err));
814 ASSERT_EQ(2u, fs_.directories_made_.size());
815 EXPECT_EQ("subdir", fs_.directories_made_[0]);
816 EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
819 TEST_F(BuildTest, DepFileMissing) {
821 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
822 "rule cc\n command = cc $in\n depfile = $out.d\n"
823 "build fo$ o.o: cc foo.c\n"));
824 fs_.Create("foo.c", "");
826 EXPECT_TRUE(builder_.AddTarget("fo o.o", &err));
828 ASSERT_EQ(1u, fs_.files_read_.size());
829 EXPECT_EQ("fo o.o.d", fs_.files_read_[0]);
832 TEST_F(BuildTest, DepFileOK) {
834 int orig_edges = state_.edges_.size();
835 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
836 "rule cc\n command = cc $in\n depfile = $out.d\n"
837 "build foo.o: cc foo.c\n"));
838 Edge* edge = state_.edges_.back();
840 fs_.Create("foo.c", "");
841 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
842 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
843 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
845 ASSERT_EQ(1u, fs_.files_read_.size());
846 EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
848 // Expect three new edges: one generating foo.o, and two more from
849 // loading the depfile.
850 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
851 // Expect our edge to now have three inputs: foo.c and two headers.
852 ASSERT_EQ(3u, edge->inputs_.size());
854 // Expect the command line we generate to only use the original input.
855 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
858 TEST_F(BuildTest, DepFileParseError) {
860 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
861 "rule cc\n command = cc $in\n depfile = $out.d\n"
862 "build foo.o: cc foo.c\n"));
863 fs_.Create("foo.c", "");
864 fs_.Create("foo.o.d", "randomtext\n");
865 EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
866 EXPECT_EQ("foo.o.d: expected ':' in depfile", err);
869 TEST_F(BuildTest, EncounterReadyTwice) {
871 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
873 " command = touch $out\n"
875 "build b: touch || c\n"
876 "build a: touch | b || c\n"));
878 vector<Edge*> c_out = GetNode("c")->out_edges();
879 ASSERT_EQ(2u, c_out.size());
880 EXPECT_EQ("b", c_out[0]->outputs_[0]->path());
881 EXPECT_EQ("a", c_out[1]->outputs_[0]->path());
884 EXPECT_TRUE(builder_.AddTarget("a", &err));
887 EXPECT_TRUE(builder_.Build(&err));
889 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
892 TEST_F(BuildTest, OrderOnlyDeps) {
894 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
895 "rule cc\n command = cc $in\n depfile = $out.d\n"
896 "build foo.o: cc foo.c || otherfile\n"));
897 Edge* edge = state_.edges_.back();
899 fs_.Create("foo.c", "");
900 fs_.Create("otherfile", "");
901 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
902 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
905 // One explicit, two implicit, one order only.
906 ASSERT_EQ(4u, edge->inputs_.size());
907 EXPECT_EQ(2, edge->implicit_deps_);
908 EXPECT_EQ(1, edge->order_only_deps_);
909 // Verify the inputs are in the order we expect
910 // (explicit then implicit then orderonly).
911 EXPECT_EQ("foo.c", edge->inputs_[0]->path());
912 EXPECT_EQ("blah.h", edge->inputs_[1]->path());
913 EXPECT_EQ("bar.h", edge->inputs_[2]->path());
914 EXPECT_EQ("otherfile", edge->inputs_[3]->path());
916 // Expect the command line we generate to only use the original input.
917 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
919 // explicit dep dirty, expect a rebuild.
920 EXPECT_TRUE(builder_.Build(&err));
922 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
926 // Recreate the depfile, as it should have been deleted by the build.
927 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
929 // implicit dep dirty, expect a rebuild.
930 fs_.Create("blah.h", "");
931 fs_.Create("bar.h", "");
932 command_runner_.commands_ran_.clear();
934 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
935 EXPECT_TRUE(builder_.Build(&err));
937 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
941 // Recreate the depfile, as it should have been deleted by the build.
942 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
944 // order only dep dirty, no rebuild.
945 fs_.Create("otherfile", "");
946 command_runner_.commands_ran_.clear();
948 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
950 EXPECT_TRUE(builder_.AlreadyUpToDate());
952 // implicit dep missing, expect rebuild.
953 fs_.RemoveFile("bar.h");
954 command_runner_.commands_ran_.clear();
956 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
957 EXPECT_TRUE(builder_.Build(&err));
959 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
962 TEST_F(BuildTest, RebuildOrderOnlyDeps) {
964 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
965 "rule cc\n command = cc $in\n"
966 "rule true\n command = true\n"
967 "build oo.h: cc oo.h.in\n"
968 "build foo.o: cc foo.c || oo.h\n"));
970 fs_.Create("foo.c", "");
971 fs_.Create("oo.h.in", "");
973 // foo.o and order-only dep dirty, build both.
974 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
975 EXPECT_TRUE(builder_.Build(&err));
977 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
979 // all clean, no rebuild.
980 command_runner_.commands_ran_.clear();
982 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
984 EXPECT_TRUE(builder_.AlreadyUpToDate());
986 // order-only dep missing, build it only.
987 fs_.RemoveFile("oo.h");
988 command_runner_.commands_ran_.clear();
990 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
991 EXPECT_TRUE(builder_.Build(&err));
993 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
994 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
998 // order-only dep dirty, build it only.
999 fs_.Create("oo.h.in", "");
1000 command_runner_.commands_ran_.clear();
1002 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
1003 EXPECT_TRUE(builder_.Build(&err));
1005 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1006 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
1010 TEST_F(BuildTest, DepFileCanonicalize) {
1012 int orig_edges = state_.edges_.size();
1013 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1014 "rule cc\n command = cc $in\n depfile = $out.d\n"
1015 "build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
1016 Edge* edge = state_.edges_.back();
1018 fs_.Create("x/y/z/foo.c", "");
1019 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
1020 // Note, different slashes from manifest.
1021 fs_.Create("gen/stuff\\things/foo.o.d",
1022 "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
1023 EXPECT_TRUE(builder_.AddTarget("gen/stuff/things/foo.o", &err));
1025 ASSERT_EQ(1u, fs_.files_read_.size());
1026 // The depfile path does not get Canonicalize as it seems unnecessary.
1027 EXPECT_EQ("gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
1029 // Expect three new edges: one generating foo.o, and two more from
1030 // loading the depfile.
1031 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
1032 // Expect our edge to now have three inputs: foo.c and two headers.
1033 ASSERT_EQ(3u, edge->inputs_.size());
1035 // Expect the command line we generate to only use the original input, and
1036 // using the slashes from the manifest.
1037 ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
1041 TEST_F(BuildTest, Phony) {
1043 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1044 "build out: cat bar.cc\n"
1045 "build all: phony out\n"));
1046 fs_.Create("bar.cc", "");
1048 EXPECT_TRUE(builder_.AddTarget("all", &err));
1051 // Only one command to run, because phony runs no command.
1052 EXPECT_FALSE(builder_.AlreadyUpToDate());
1053 EXPECT_TRUE(builder_.Build(&err));
1055 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1058 TEST_F(BuildTest, PhonyNoWork) {
1060 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1061 "build out: cat bar.cc\n"
1062 "build all: phony out\n"));
1063 fs_.Create("bar.cc", "");
1064 fs_.Create("out", "");
1066 EXPECT_TRUE(builder_.AddTarget("all", &err));
1068 EXPECT_TRUE(builder_.AlreadyUpToDate());
1071 TEST_F(BuildTest, Fail) {
1072 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1075 "build out1: fail\n"));
1078 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1081 EXPECT_FALSE(builder_.Build(&err));
1082 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1083 ASSERT_EQ("subcommand failed", err);
1086 TEST_F(BuildTest, SwallowFailures) {
1087 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1090 "build out1: fail\n"
1091 "build out2: fail\n"
1092 "build out3: fail\n"
1093 "build all: phony out1 out2 out3\n"));
1095 // Swallow two failures, die on the third.
1096 config_.failures_allowed = 3;
1099 EXPECT_TRUE(builder_.AddTarget("all", &err));
1102 EXPECT_FALSE(builder_.Build(&err));
1103 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1104 ASSERT_EQ("subcommands failed", err);
1107 TEST_F(BuildTest, SwallowFailuresLimit) {
1108 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1111 "build out1: fail\n"
1112 "build out2: fail\n"
1113 "build out3: fail\n"
1114 "build final: cat out1 out2 out3\n"));
1116 // Swallow ten failures; we should stop before building final.
1117 config_.failures_allowed = 11;
1120 EXPECT_TRUE(builder_.AddTarget("final", &err));
1123 EXPECT_FALSE(builder_.Build(&err));
1124 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1125 ASSERT_EQ("cannot make progress due to previous errors", err);
1128 TEST_F(BuildTest, SwallowFailuresPool) {
1129 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1134 " pool = failpool\n"
1135 "build out1: fail\n"
1136 "build out2: fail\n"
1137 "build out3: fail\n"
1138 "build final: cat out1 out2 out3\n"));
1140 // Swallow ten failures; we should stop before building final.
1141 config_.failures_allowed = 11;
1144 EXPECT_TRUE(builder_.AddTarget("final", &err));
1147 EXPECT_FALSE(builder_.Build(&err));
1148 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1149 ASSERT_EQ("cannot make progress due to previous errors", err);
1152 TEST_F(BuildTest, PoolEdgesReadyButNotWanted) {
1153 fs_.Create("x", "");
1155 const char* manifest =
1159 " command = touch $out\n"
1160 " pool = some_pool\n"
1162 " command = touch grit\n"
1164 "build B.d.stamp: cc | x\n"
1165 "build C.stamp: touch B.d.stamp\n"
1166 "build final.stamp: touch || C.stamp\n";
1168 RebuildTarget("final.stamp", manifest);
1170 fs_.RemoveFile("B.d.stamp");
1173 RebuildTarget("final.stamp", manifest, NULL, NULL, &save_state);
1174 EXPECT_GE(save_state.LookupPool("some_pool")->current_use(), 0);
1177 struct BuildWithLogTest : public BuildTest {
1178 BuildWithLogTest() {
1179 builder_.SetBuildLog(&build_log_);
1182 BuildLog build_log_;
1185 TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
1186 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1189 "build out1: cc in\n"));
1191 // Create input/output that would be considered up to date when
1192 // not considering the command line hash.
1193 fs_.Create("in", "");
1194 fs_.Create("out1", "");
1197 // Because it's not in the log, it should not be up-to-date until
1199 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1200 EXPECT_FALSE(builder_.AlreadyUpToDate());
1202 command_runner_.commands_ran_.clear();
1205 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1206 EXPECT_TRUE(builder_.Build(&err));
1207 EXPECT_TRUE(builder_.AlreadyUpToDate());
1210 TEST_F(BuildWithLogTest, RebuildAfterFailure) {
1211 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1212 "rule touch-fail-tick2\n"
1213 " command = touch-fail-tick2\n"
1214 "build out1: touch-fail-tick2 in\n"));
1218 fs_.Create("in", "");
1220 // Run once successfully to get out1 in the log
1221 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1222 EXPECT_TRUE(builder_.Build(&err));
1224 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1226 command_runner_.commands_ran_.clear();
1229 builder_.plan_.Reset();
1232 fs_.Create("in", "");
1234 // Run again with a failure that updates the output file timestamp
1235 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1236 EXPECT_FALSE(builder_.Build(&err));
1237 EXPECT_EQ("subcommand failed", err);
1238 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1240 command_runner_.commands_ran_.clear();
1243 builder_.plan_.Reset();
1247 // Run again, should rerun even though the output file is up to date on disk
1248 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1249 EXPECT_FALSE(builder_.AlreadyUpToDate());
1250 EXPECT_TRUE(builder_.Build(&err));
1251 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1255 TEST_F(BuildWithLogTest, RebuildWithNoInputs) {
1256 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1258 " command = touch\n"
1259 "build out1: touch\n"
1260 "build out2: touch in\n"));
1264 fs_.Create("in", "");
1266 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1267 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1268 EXPECT_TRUE(builder_.Build(&err));
1270 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
1272 command_runner_.commands_ran_.clear();
1277 fs_.Create("in", "");
1279 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1280 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1281 EXPECT_TRUE(builder_.Build(&err));
1283 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1286 TEST_F(BuildWithLogTest, RestatTest) {
1287 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1294 "build out1: cc in\n"
1295 "build out2: true out1\n"
1296 "build out3: cat out2\n"));
1298 fs_.Create("out1", "");
1299 fs_.Create("out2", "");
1300 fs_.Create("out3", "");
1304 fs_.Create("in", "");
1306 // Do a pre-build so that there's commands in the log for the outputs,
1307 // otherwise, the lack of an entry in the build log will cause out3 to rebuild
1308 // regardless of restat.
1310 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1312 EXPECT_TRUE(builder_.Build(&err));
1314 EXPECT_EQ("[3/3]", builder_.status_->FormatProgressStatus("[%s/%t]",
1315 BuildStatus::kEdgeStarted));
1316 command_runner_.commands_ran_.clear();
1321 fs_.Create("in", "");
1322 // "cc" touches out1, so we should build out2. But because "true" does not
1323 // touch out2, we should cancel the build of out3.
1324 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1326 EXPECT_TRUE(builder_.Build(&err));
1327 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1329 // If we run again, it should be a no-op, because the build log has recorded
1330 // that we've already built out2 with an input timestamp of 2 (from out1).
1331 command_runner_.commands_ran_.clear();
1333 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1335 EXPECT_TRUE(builder_.AlreadyUpToDate());
1339 fs_.Create("in", "");
1341 // The build log entry should not, however, prevent us from rebuilding out2
1343 command_runner_.commands_ran_.clear();
1345 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1347 EXPECT_TRUE(builder_.Build(&err));
1348 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1351 TEST_F(BuildWithLogTest, RestatMissingFile) {
1352 // If a restat rule doesn't create its output, and the output didn't
1353 // exist before the rule was run, consider that behavior equivalent
1354 // to a rule that doesn't modify its existent output file.
1356 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1362 "build out1: true in\n"
1363 "build out2: cc out1\n"));
1365 fs_.Create("in", "");
1366 fs_.Create("out2", "");
1368 // Do a pre-build so that there's commands in the log for the outputs,
1369 // otherwise, the lack of an entry in the build log will cause out2 to rebuild
1370 // regardless of restat.
1372 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1374 EXPECT_TRUE(builder_.Build(&err));
1376 command_runner_.commands_ran_.clear();
1380 fs_.Create("in", "");
1381 fs_.Create("out2", "");
1383 // Run a build, expect only the first command to run.
1384 // It doesn't touch its output (due to being the "true" command), so
1385 // we shouldn't run the dependent build.
1386 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1388 EXPECT_TRUE(builder_.Build(&err));
1389 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1392 TEST_F(BuildWithLogTest, RestatSingleDependentOutputDirty) {
1393 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1398 " command = touch\n"
1399 "build out1: true in\n"
1400 "build out2 out3: touch out1\n"
1401 "build out4: touch out2\n"
1404 // Create the necessary files
1405 fs_.Create("in", "");
1408 EXPECT_TRUE(builder_.AddTarget("out4", &err));
1410 EXPECT_TRUE(builder_.Build(&err));
1412 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1415 fs_.Create("in", "");
1416 fs_.RemoveFile("out3");
1418 // Since "in" is missing, out1 will be built. Since "out3" is missing,
1419 // out2 and out3 will be built even though "in" is not touched when built.
1420 // Then, since out2 is rebuilt, out4 should be rebuilt -- the restat on the
1421 // "true" rule should not lead to the "touch" edge writing out2 and out3 being
1423 command_runner_.commands_ran_.clear();
1425 EXPECT_TRUE(builder_.AddTarget("out4", &err));
1427 EXPECT_TRUE(builder_.Build(&err));
1429 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1432 // Test scenario, in which an input file is removed, but output isn't changed
1433 // https://github.com/ninja-build/ninja/issues/295
1434 TEST_F(BuildWithLogTest, RestatMissingInput) {
1435 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1438 " depfile = $out.d\n"
1442 "build out1: true in\n"
1443 "build out2: cc out1\n"));
1445 // Create all necessary files
1446 fs_.Create("in", "");
1448 // The implicit dependencies and the depfile itself
1449 // are newer than the output
1450 TimeStamp restat_mtime = fs_.Tick();
1451 fs_.Create("out1.d", "out1: will.be.deleted restat.file\n");
1452 fs_.Create("will.be.deleted", "");
1453 fs_.Create("restat.file", "");
1455 // Run the build, out1 and out2 get built
1457 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1459 EXPECT_TRUE(builder_.Build(&err));
1460 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1462 // See that an entry in the logfile is created, capturing
1464 BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out1");
1465 ASSERT_TRUE(NULL != log_entry);
1466 ASSERT_EQ(restat_mtime, log_entry->mtime);
1468 // Now remove a file, referenced from depfile, so that target becomes
1469 // dirty, but the output does not change
1470 fs_.RemoveFile("will.be.deleted");
1472 // Trigger the build again - only out1 gets built
1473 command_runner_.commands_ran_.clear();
1475 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1477 EXPECT_TRUE(builder_.Build(&err));
1478 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1480 // Check that the logfile entry remains correctly set
1481 log_entry = build_log_.LookupByOutput("out1");
1482 ASSERT_TRUE(NULL != log_entry);
1483 ASSERT_EQ(restat_mtime, log_entry->mtime);
1486 struct BuildDryRun : public BuildWithLogTest {
1488 config_.dry_run = true;
1492 TEST_F(BuildDryRun, AllCommandsShown) {
1493 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1500 "build out1: cc in\n"
1501 "build out2: true out1\n"
1502 "build out3: cat out2\n"));
1504 fs_.Create("out1", "");
1505 fs_.Create("out2", "");
1506 fs_.Create("out3", "");
1510 fs_.Create("in", "");
1512 // "cc" touches out1, so we should build out2. But because "true" does not
1513 // touch out2, we should cancel the build of out3.
1515 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1517 EXPECT_TRUE(builder_.Build(&err));
1518 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1521 // Test that RSP files are created when & where appropriate and deleted after
1522 // successful execution.
1523 TEST_F(BuildTest, RspFileSuccess)
1525 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1527 " command = cat $rspfile > $out\n"
1528 " rspfile = $rspfile\n"
1529 " rspfile_content = $long_command\n"
1530 "rule cat_rsp_out\n"
1531 " command = cat $rspfile > $out\n"
1532 " rspfile = $out.rsp\n"
1533 " rspfile_content = $long_command\n"
1534 "build out1: cat in\n"
1535 "build out2: cat_rsp in\n"
1536 " rspfile = out 2.rsp\n"
1537 " long_command = Some very long command\n"
1538 "build out$ 3: cat_rsp_out in\n"
1539 " long_command = Some very long command\n"));
1541 fs_.Create("out1", "");
1542 fs_.Create("out2", "");
1543 fs_.Create("out 3", "");
1547 fs_.Create("in", "");
1550 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1552 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1554 EXPECT_TRUE(builder_.AddTarget("out 3", &err));
1557 size_t files_created = fs_.files_created_.size();
1558 size_t files_removed = fs_.files_removed_.size();
1560 EXPECT_TRUE(builder_.Build(&err));
1561 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1563 // The RSP files were created
1564 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1565 ASSERT_EQ(1u, fs_.files_created_.count("out 2.rsp"));
1566 ASSERT_EQ(1u, fs_.files_created_.count("out 3.rsp"));
1568 // The RSP files were removed
1569 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1570 ASSERT_EQ(1u, fs_.files_removed_.count("out 2.rsp"));
1571 ASSERT_EQ(1u, fs_.files_removed_.count("out 3.rsp"));
1574 // Test that RSP file is created but not removed for commands, which fail
1575 TEST_F(BuildTest, RspFileFailure) {
1576 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1579 " rspfile = $rspfile\n"
1580 " rspfile_content = $long_command\n"
1581 "build out: fail in\n"
1582 " rspfile = out.rsp\n"
1583 " long_command = Another very long command\n"));
1585 fs_.Create("out", "");
1587 fs_.Create("in", "");
1590 EXPECT_TRUE(builder_.AddTarget("out", &err));
1593 size_t files_created = fs_.files_created_.size();
1594 size_t files_removed = fs_.files_removed_.size();
1596 EXPECT_FALSE(builder_.Build(&err));
1597 ASSERT_EQ("subcommand failed", err);
1598 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1600 // The RSP file was created
1601 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1602 ASSERT_EQ(1u, fs_.files_created_.count("out.rsp"));
1604 // The RSP file was NOT removed
1605 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1606 ASSERT_EQ(0u, fs_.files_removed_.count("out.rsp"));
1608 // The RSP file contains what it should
1609 ASSERT_EQ("Another very long command", fs_.files_["out.rsp"].contents);
1612 // Test that contents of the RSP file behaves like a regular part of
1613 // command line, i.e. triggers a rebuild if changed
1614 TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
1615 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1617 " command = cat $rspfile > $out\n"
1618 " rspfile = $rspfile\n"
1619 " rspfile_content = $long_command\n"
1620 "build out: cat_rsp in\n"
1621 " rspfile = out.rsp\n"
1622 " long_command = Original very long command\n"));
1624 fs_.Create("out", "");
1626 fs_.Create("in", "");
1629 EXPECT_TRUE(builder_.AddTarget("out", &err));
1632 // 1. Build for the 1st time (-> populate log)
1633 EXPECT_TRUE(builder_.Build(&err));
1634 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1636 // 2. Build again (no change)
1637 command_runner_.commands_ran_.clear();
1639 EXPECT_TRUE(builder_.AddTarget("out", &err));
1641 ASSERT_TRUE(builder_.AlreadyUpToDate());
1643 // 3. Alter the entry in the logfile
1644 // (to simulate a change in the command line between 2 builds)
1645 BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out");
1646 ASSERT_TRUE(NULL != log_entry);
1647 ASSERT_NO_FATAL_FAILURE(AssertHash(
1648 "cat out.rsp > out;rspfile=Original very long command",
1649 log_entry->command_hash));
1650 log_entry->command_hash++; // Change the command hash to something else.
1651 // Now expect the target to be rebuilt
1652 command_runner_.commands_ran_.clear();
1654 EXPECT_TRUE(builder_.AddTarget("out", &err));
1656 EXPECT_TRUE(builder_.Build(&err));
1657 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1660 TEST_F(BuildTest, InterruptCleanup) {
1661 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1663 " command = interrupt\n"
1664 "rule touch-interrupt\n"
1665 " command = touch-interrupt\n"
1666 "build out1: interrupt in1\n"
1667 "build out2: touch-interrupt in2\n"));
1669 fs_.Create("out1", "");
1670 fs_.Create("out2", "");
1672 fs_.Create("in1", "");
1673 fs_.Create("in2", "");
1675 // An untouched output of an interrupted command should be retained.
1677 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1679 EXPECT_FALSE(builder_.Build(&err));
1680 EXPECT_EQ("interrupted by user", err);
1682 EXPECT_GT(fs_.Stat("out1", &err), 0);
1685 // A touched output of an interrupted command should be deleted.
1686 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1688 EXPECT_FALSE(builder_.Build(&err));
1689 EXPECT_EQ("interrupted by user", err);
1691 EXPECT_EQ(0, fs_.Stat("out2", &err));
1694 TEST_F(BuildTest, StatFailureAbortsBuild) {
1695 const string kTooLongToStat(400, 'i');
1696 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1697 ("build " + kTooLongToStat + ": cat in\n").c_str()));
1698 fs_.Create("in", "");
1700 // This simulates a stat failure:
1701 fs_.files_[kTooLongToStat].mtime = -1;
1702 fs_.files_[kTooLongToStat].stat_error = "stat failed";
1705 EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
1706 EXPECT_EQ("stat failed", err);
1709 TEST_F(BuildTest, PhonyWithNoInputs) {
1710 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1711 "build nonexistent: phony\n"
1712 "build out1: cat || nonexistent\n"
1713 "build out2: cat nonexistent\n"));
1714 fs_.Create("out1", "");
1715 fs_.Create("out2", "");
1717 // out1 should be up to date even though its input is dirty, because its
1718 // order-only dependency has nothing to do.
1720 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1722 EXPECT_TRUE(builder_.AlreadyUpToDate());
1724 // out2 should still be out of date though, because its input is dirty.
1726 command_runner_.commands_ran_.clear();
1728 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1730 EXPECT_TRUE(builder_.Build(&err));
1732 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1735 TEST_F(BuildTest, DepsGccWithEmptyDepfileErrorsOut) {
1736 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1740 "build out: cc\n"));
1744 EXPECT_TRUE(builder_.AddTarget("out", &err));
1746 EXPECT_FALSE(builder_.AlreadyUpToDate());
1748 EXPECT_FALSE(builder_.Build(&err));
1749 ASSERT_EQ("subcommand failed", err);
1750 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1753 TEST_F(BuildTest, StatusFormatElapsed) {
1754 status_.BuildStarted();
1755 // Before any task is done, the elapsed time must be zero.
1756 EXPECT_EQ("[%/e0.000]",
1757 status_.FormatProgressStatus("[%%/e%e]",
1758 BuildStatus::kEdgeStarted));
1761 TEST_F(BuildTest, StatusFormatReplacePlaceholder) {
1762 EXPECT_EQ("[%/s0/t0/r0/u0/f0]",
1763 status_.FormatProgressStatus("[%%/s%s/t%t/r%r/u%u/f%f]",
1764 BuildStatus::kEdgeStarted));
1767 TEST_F(BuildTest, FailedDepsParse) {
1768 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1769 "build bad_deps.o: cat in1\n"
1771 " depfile = in1.d\n"));
1774 EXPECT_TRUE(builder_.AddTarget("bad_deps.o", &err));
1777 // These deps will fail to parse, as they should only have one
1778 // path to the left of the colon.
1779 fs_.Create("in1.d", "AAA BBB");
1781 EXPECT_FALSE(builder_.Build(&err));
1782 EXPECT_EQ("subcommand failed", err);
1785 /// Tests of builds involving deps logs necessarily must span
1786 /// multiple builds. We reuse methods on BuildTest but not the
1787 /// builder_ it sets up, because we want pristine objects for
1789 struct BuildWithDepsLogTest : public BuildTest {
1790 BuildWithDepsLogTest() {}
1792 virtual void SetUp() {
1795 temp_dir_.CreateAndEnter("BuildWithDepsLogTest");
1798 virtual void TearDown() {
1799 temp_dir_.Cleanup();
1802 ScopedTempDir temp_dir_;
1804 /// Shadow parent class builder_ so we don't accidentally use it.
1808 /// Run a straightforwad build where the deps log is used.
1809 TEST_F(BuildWithDepsLogTest, Straightforward) {
1811 // Note: in1 was created by the superclass SetUp().
1812 const char* manifest =
1813 "build out: cat in1\n"
1815 " depfile = in1.d\n";
1818 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1819 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1821 // Run the build once, everything should be ok.
1823 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1826 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1827 builder.command_runner_.reset(&command_runner_);
1828 EXPECT_TRUE(builder.AddTarget("out", &err));
1830 fs_.Create("in1.d", "out: in2");
1831 EXPECT_TRUE(builder.Build(&err));
1834 // The deps file should have been removed.
1835 EXPECT_EQ(0, fs_.Stat("in1.d", &err));
1836 // Recreate it for the next step.
1837 fs_.Create("in1.d", "out: in2");
1839 builder.command_runner_.release();
1844 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1845 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1847 // Touch the file only mentioned in the deps.
1849 fs_.Create("in2", "");
1851 // Run the build again.
1853 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
1854 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1856 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1857 builder.command_runner_.reset(&command_runner_);
1858 command_runner_.commands_ran_.clear();
1859 EXPECT_TRUE(builder.AddTarget("out", &err));
1861 EXPECT_TRUE(builder.Build(&err));
1864 // We should have rebuilt the output due to in2 being
1866 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1868 builder.command_runner_.release();
1872 /// Verify that obsolete dependency info causes a rebuild.
1873 /// 1) Run a successful build where everything has time t, record deps.
1874 /// 2) Move input/output to time t+1 -- despite files in alignment,
1875 /// should still need to rebuild due to deps at older time.
1876 TEST_F(BuildWithDepsLogTest, ObsoleteDeps) {
1878 // Note: in1 was created by the superclass SetUp().
1879 const char* manifest =
1880 "build out: cat in1\n"
1882 " depfile = in1.d\n";
1884 // Run an ordinary build that gathers dependencies.
1885 fs_.Create("in1", "");
1886 fs_.Create("in1.d", "out: ");
1889 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1890 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1892 // Run the build once, everything should be ok.
1894 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1897 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1898 builder.command_runner_.reset(&command_runner_);
1899 EXPECT_TRUE(builder.AddTarget("out", &err));
1901 EXPECT_TRUE(builder.Build(&err));
1905 builder.command_runner_.release();
1908 // Push all files one tick forward so that only the deps are out
1911 fs_.Create("in1", "");
1912 fs_.Create("out", "");
1914 // The deps file should have been removed, so no need to timestamp it.
1915 EXPECT_EQ(0, fs_.Stat("in1.d", &err));
1919 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1920 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1923 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
1924 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1926 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1927 builder.command_runner_.reset(&command_runner_);
1928 command_runner_.commands_ran_.clear();
1929 EXPECT_TRUE(builder.AddTarget("out", &err));
1932 // Recreate the deps file here because the build expects them to exist.
1933 fs_.Create("in1.d", "out: ");
1935 EXPECT_TRUE(builder.Build(&err));
1938 // We should have rebuilt the output due to the deps being
1940 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1942 builder.command_runner_.release();
1946 TEST_F(BuildWithDepsLogTest, DepsIgnoredInDryRun) {
1947 const char* manifest =
1948 "build out: cat in1\n"
1950 " depfile = in1.d\n";
1952 fs_.Create("out", "");
1954 fs_.Create("in1", "");
1957 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1958 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1960 // The deps log is NULL in dry runs.
1961 config_.dry_run = true;
1962 Builder builder(&state, config_, NULL, NULL, &fs_);
1963 builder.command_runner_.reset(&command_runner_);
1964 command_runner_.commands_ran_.clear();
1967 EXPECT_TRUE(builder.AddTarget("out", &err));
1969 EXPECT_TRUE(builder.Build(&err));
1970 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1972 builder.command_runner_.release();
1975 /// Check that a restat rule generating a header cancels compilations correctly.
1976 TEST_F(BuildTest, RestatDepfileDependency) {
1977 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1979 " command = true\n" // Would be "write if out-of-date" in reality.
1981 "build header.h: true header.in\n"
1982 "build out: cat in1\n"
1983 " depfile = in1.d\n"));
1985 fs_.Create("header.h", "");
1986 fs_.Create("in1.d", "out: header.h");
1988 fs_.Create("header.in", "");
1991 EXPECT_TRUE(builder_.AddTarget("out", &err));
1993 EXPECT_TRUE(builder_.Build(&err));
1997 /// Check that a restat rule generating a header cancels compilations correctly,
1999 TEST_F(BuildWithDepsLogTest, RestatDepfileDependencyDepsLog) {
2001 // Note: in1 was created by the superclass SetUp().
2002 const char* manifest =
2004 " command = true\n" // Would be "write if out-of-date" in reality.
2006 "build header.h: true header.in\n"
2007 "build out: cat in1\n"
2009 " depfile = in1.d\n";
2012 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2013 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2015 // Run the build once, everything should be ok.
2017 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2020 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2021 builder.command_runner_.reset(&command_runner_);
2022 EXPECT_TRUE(builder.AddTarget("out", &err));
2024 fs_.Create("in1.d", "out: header.h");
2025 EXPECT_TRUE(builder.Build(&err));
2029 builder.command_runner_.release();
2034 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2035 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2037 // Touch the input of the restat rule.
2039 fs_.Create("header.in", "");
2041 // Run the build again.
2043 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2044 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2046 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2047 builder.command_runner_.reset(&command_runner_);
2048 command_runner_.commands_ran_.clear();
2049 EXPECT_TRUE(builder.AddTarget("out", &err));
2051 EXPECT_TRUE(builder.Build(&err));
2054 // Rule "true" should have run again, but the build of "out" should have
2055 // been cancelled due to restat propagating through the depfile header.
2056 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2058 builder.command_runner_.release();
2062 TEST_F(BuildWithDepsLogTest, DepFileOKDepsLog) {
2064 const char* manifest =
2065 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
2066 "build fo$ o.o: cc foo.c\n";
2068 fs_.Create("foo.c", "");
2072 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2074 // Run the build once, everything should be ok.
2076 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2079 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2080 builder.command_runner_.reset(&command_runner_);
2081 EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
2083 fs_.Create("fo o.o.d", "fo\\ o.o: blah.h bar.h\n");
2084 EXPECT_TRUE(builder.Build(&err));
2088 builder.command_runner_.release();
2093 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2096 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2097 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2100 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2101 builder.command_runner_.reset(&command_runner_);
2103 Edge* edge = state.edges_.back();
2105 state.GetNode("bar.h", 0)->MarkDirty(); // Mark bar.h as missing.
2106 EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
2109 // Expect three new edges: one generating fo o.o, and two more from
2110 // loading the depfile.
2111 ASSERT_EQ(3u, state.edges_.size());
2112 // Expect our edge to now have three inputs: foo.c and two headers.
2113 ASSERT_EQ(3u, edge->inputs_.size());
2115 // Expect the command line we generate to only use the original input.
2116 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
2119 builder.command_runner_.release();
2124 TEST_F(BuildWithDepsLogTest, DepFileDepsLogCanonicalize) {
2126 const char* manifest =
2127 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
2128 "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
2130 fs_.Create("x/y/z/foo.c", "");
2134 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2136 // Run the build once, everything should be ok.
2138 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2141 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2142 builder.command_runner_.reset(&command_runner_);
2143 EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
2145 // Note, different slashes from manifest.
2146 fs_.Create("a/b\\c\\d/e/fo o.o.d",
2147 "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
2148 EXPECT_TRUE(builder.Build(&err));
2152 builder.command_runner_.release();
2157 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
2160 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
2161 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
2164 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2165 builder.command_runner_.reset(&command_runner_);
2167 Edge* edge = state.edges_.back();
2169 state.GetNode("bar.h", 0)->MarkDirty(); // Mark bar.h as missing.
2170 EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
2173 // Expect three new edges: one generating fo o.o, and two more from
2174 // loading the depfile.
2175 ASSERT_EQ(3u, state.edges_.size());
2176 // Expect our edge to now have three inputs: foo.c and two headers.
2177 ASSERT_EQ(3u, edge->inputs_.size());
2179 // Expect the command line we generate to only use the original input.
2180 // Note, slashes from manifest, not .d.
2181 ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
2184 builder.command_runner_.release();
2189 /// Check that a restat rule doesn't clear an edge if the depfile is missing.
2190 /// Follows from: https://github.com/ninja-build/ninja/issues/603
2191 TEST_F(BuildTest, RestatMissingDepfile) {
2192 const char* manifest =
2194 " command = true\n" // Would be "write if out-of-date" in reality.
2196 "build header.h: true header.in\n"
2197 "build out: cat header.h\n"
2198 " depfile = out.d\n";
2200 fs_.Create("header.h", "");
2202 fs_.Create("out", "");
2203 fs_.Create("header.in", "");
2205 // Normally, only 'header.h' would be rebuilt, as
2206 // its rule doesn't touch the output and has 'restat=1' set.
2207 // But we are also missing the depfile for 'out',
2208 // which should force its command to run anyway!
2209 RebuildTarget("out", manifest);
2210 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2213 /// Check that a restat rule doesn't clear an edge if the deps are missing.
2214 /// https://github.com/ninja-build/ninja/issues/603
2215 TEST_F(BuildWithDepsLogTest, RestatMissingDepfileDepslog) {
2217 const char* manifest =
2219 " command = true\n" // Would be "write if out-of-date" in reality.
2221 "build header.h: true header.in\n"
2222 "build out: cat header.h\n"
2224 " depfile = out.d\n";
2226 // Build once to populate ninja deps logs from out.d
2227 fs_.Create("header.in", "");
2228 fs_.Create("out.d", "out: header.h");
2229 fs_.Create("header.h", "");
2231 RebuildTarget("out", manifest, "build_log", "ninja_deps");
2232 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2234 // Sanity: this rebuild should be NOOP
2235 RebuildTarget("out", manifest, "build_log", "ninja_deps");
2236 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2238 // Touch 'header.in', blank dependencies log (create a different one).
2239 // Building header.h triggers 'restat' outputs cleanup.
2240 // Validate that out is rebuilt netherless, as deps are missing.
2242 fs_.Create("header.in", "");
2244 // (switch to a new blank deps_log "ninja_deps2")
2245 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2246 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2248 // Sanity: this build should be NOOP
2249 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2250 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2252 // Check that invalidating deps by target timestamp also works here
2253 // Repeat the test but touch target instead of blanking the log.
2255 fs_.Create("header.in", "");
2256 fs_.Create("out", "");
2257 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2258 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2260 // And this build should be NOOP again
2261 RebuildTarget("out", manifest, "build_log", "ninja_deps2");
2262 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2265 TEST_F(BuildTest, WrongOutputInDepfileCausesRebuild) {
2267 const char* manifest =
2269 " command = cc $in\n"
2270 " depfile = $out.d\n"
2271 "build foo.o: cc foo.c\n";
2273 fs_.Create("foo.c", "");
2274 fs_.Create("foo.o", "");
2275 fs_.Create("header.h", "");
2276 fs_.Create("foo.o.d", "bar.o.d: header.h\n");
2278 RebuildTarget("foo.o", manifest, "build_log", "ninja_deps");
2279 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2282 TEST_F(BuildTest, Console) {
2283 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2285 " command = console\n"
2287 "build cons: console in.txt\n"));
2289 fs_.Create("in.txt", "");
2292 EXPECT_TRUE(builder_.AddTarget("cons", &err));
2294 EXPECT_TRUE(builder_.Build(&err));
2296 ASSERT_EQ(1u, command_runner_.commands_ran_.size());