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.
17 #include "build_log.h"
22 /// Fixture for tests involving Plan.
23 // Though Plan doesn't use State, it's useful to have one around
24 // to create Nodes and Edges.
25 struct PlanTest : public StateTestWithBuiltinRules {
29 TEST_F(PlanTest, Basic) {
31 "build out: cat mid\n"
32 "build mid: cat in\n");
33 GetNode("mid")->MarkDirty();
34 GetNode("out")->MarkDirty();
36 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
38 ASSERT_TRUE(plan_.more_to_do());
40 Edge* edge = plan_.FindWork();
42 ASSERT_EQ("in", edge->inputs_[0]->path());
43 ASSERT_EQ("mid", edge->outputs_[0]->path());
45 ASSERT_FALSE(plan_.FindWork());
47 plan_.EdgeFinished(edge);
49 edge = plan_.FindWork();
51 ASSERT_EQ("mid", edge->inputs_[0]->path());
52 ASSERT_EQ("out", edge->outputs_[0]->path());
54 plan_.EdgeFinished(edge);
56 ASSERT_FALSE(plan_.more_to_do());
57 edge = plan_.FindWork();
61 // Test that two outputs from one rule can be handled as inputs to the next.
62 TEST_F(PlanTest, DoubleOutputDirect) {
64 "build out: cat mid1 mid2\n"
65 "build mid1 mid2: cat in\n");
66 GetNode("mid1")->MarkDirty();
67 GetNode("mid2")->MarkDirty();
68 GetNode("out")->MarkDirty();
71 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
73 ASSERT_TRUE(plan_.more_to_do());
76 edge = plan_.FindWork();
77 ASSERT_TRUE(edge); // cat in
78 plan_.EdgeFinished(edge);
80 edge = plan_.FindWork();
81 ASSERT_TRUE(edge); // cat mid1 mid2
82 plan_.EdgeFinished(edge);
84 edge = plan_.FindWork();
85 ASSERT_FALSE(edge); // done
88 // Test that two outputs from one rule can eventually be routed to another.
89 TEST_F(PlanTest, DoubleOutputIndirect) {
91 "build out: cat b1 b2\n"
94 "build a1 a2: cat in\n");
95 GetNode("a1")->MarkDirty();
96 GetNode("a2")->MarkDirty();
97 GetNode("b1")->MarkDirty();
98 GetNode("b2")->MarkDirty();
99 GetNode("out")->MarkDirty();
101 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
103 ASSERT_TRUE(plan_.more_to_do());
106 edge = plan_.FindWork();
107 ASSERT_TRUE(edge); // cat in
108 plan_.EdgeFinished(edge);
110 edge = plan_.FindWork();
111 ASSERT_TRUE(edge); // cat a1
112 plan_.EdgeFinished(edge);
114 edge = plan_.FindWork();
115 ASSERT_TRUE(edge); // cat a2
116 plan_.EdgeFinished(edge);
118 edge = plan_.FindWork();
119 ASSERT_TRUE(edge); // cat b1 b2
120 plan_.EdgeFinished(edge);
122 edge = plan_.FindWork();
123 ASSERT_FALSE(edge); // done
126 // Test that two edges from one output can both execute.
127 TEST_F(PlanTest, DoubleDependent) {
129 "build out: cat a1 a2\n"
130 "build a1: cat mid\n"
131 "build a2: cat mid\n"
132 "build mid: cat in\n");
133 GetNode("mid")->MarkDirty();
134 GetNode("a1")->MarkDirty();
135 GetNode("a2")->MarkDirty();
136 GetNode("out")->MarkDirty();
139 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
141 ASSERT_TRUE(plan_.more_to_do());
144 edge = plan_.FindWork();
145 ASSERT_TRUE(edge); // cat in
146 plan_.EdgeFinished(edge);
148 edge = plan_.FindWork();
149 ASSERT_TRUE(edge); // cat mid
150 plan_.EdgeFinished(edge);
152 edge = plan_.FindWork();
153 ASSERT_TRUE(edge); // cat mid
154 plan_.EdgeFinished(edge);
156 edge = plan_.FindWork();
157 ASSERT_TRUE(edge); // cat a1 a2
158 plan_.EdgeFinished(edge);
160 edge = plan_.FindWork();
161 ASSERT_FALSE(edge); // done
164 TEST_F(PlanTest, DependencyCycle) {
166 "build out: cat mid\n"
167 "build mid: cat in\n"
168 "build in: cat pre\n"
169 "build pre: cat out\n");
170 GetNode("out")->MarkDirty();
171 GetNode("mid")->MarkDirty();
172 GetNode("in")->MarkDirty();
173 GetNode("pre")->MarkDirty();
176 EXPECT_FALSE(plan_.AddTarget(GetNode("out"), &err));
177 ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err);
180 TEST_F(PlanTest, PoolWithDepthOne) {
181 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
185 " command = cat $in > $out\n"
187 "build out1: poolcat in\n"
188 "build out2: poolcat in\n"));
189 GetNode("out1")->MarkDirty();
190 GetNode("out2")->MarkDirty();
192 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
194 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
196 ASSERT_TRUE(plan_.more_to_do());
198 Edge* edge = plan_.FindWork();
200 ASSERT_EQ("in", edge->inputs_[0]->path());
201 ASSERT_EQ("out1", edge->outputs_[0]->path());
203 // This will be false since poolcat is serialized
204 ASSERT_FALSE(plan_.FindWork());
206 plan_.EdgeFinished(edge);
208 edge = plan_.FindWork();
210 ASSERT_EQ("in", edge->inputs_[0]->path());
211 ASSERT_EQ("out2", edge->outputs_[0]->path());
213 ASSERT_FALSE(plan_.FindWork());
215 plan_.EdgeFinished(edge);
217 ASSERT_FALSE(plan_.more_to_do());
218 edge = plan_.FindWork();
222 TEST_F(PlanTest, PoolsWithDepthTwo) {
223 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
229 " command = cat $in > $out\n"
232 " command = cat $in > $out\n"
234 "build out1: foocat in\n"
235 "build out2: foocat in\n"
236 "build out3: foocat in\n"
237 "build outb1: bazcat in\n"
238 "build outb2: bazcat in\n"
239 "build outb3: bazcat in\n"
241 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
243 // Mark all the out* nodes dirty
244 for (int i = 0; i < 3; ++i) {
245 GetNode("out" + string(1, '1' + i))->MarkDirty();
246 GetNode("outb" + string(1, '1' + i))->MarkDirty();
248 GetNode("allTheThings")->MarkDirty();
251 EXPECT_TRUE(plan_.AddTarget(GetNode("allTheThings"), &err));
254 // Grab the first 4 edges, out1 out2 outb1 outb2
256 for (int i = 0; i < 4; ++i) {
257 ASSERT_TRUE(plan_.more_to_do());
258 Edge* edge = plan_.FindWork();
260 ASSERT_EQ("in", edge->inputs_[0]->path());
261 string base_name(i < 2 ? "out" : "outb");
262 ASSERT_EQ(base_name + string(1, '1' + (i % 2)), edge->outputs_[0]->path());
263 edges.push_back(edge);
266 // outb3 is exempt because it has an empty pool
267 ASSERT_TRUE(plan_.more_to_do());
268 Edge* edge = plan_.FindWork();
270 ASSERT_EQ("in", edge->inputs_[0]->path());
271 ASSERT_EQ("outb3", edge->outputs_[0]->path());
272 edges.push_back(edge);
274 ASSERT_FALSE(plan_.FindWork());
277 plan_.EdgeFinished(edges.front());
280 // out3 should be available
281 Edge* out3 = plan_.FindWork();
283 ASSERT_EQ("in", out3->inputs_[0]->path());
284 ASSERT_EQ("out3", out3->outputs_[0]->path());
286 ASSERT_FALSE(plan_.FindWork());
288 plan_.EdgeFinished(out3);
290 ASSERT_FALSE(plan_.FindWork());
292 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
293 plan_.EdgeFinished(*it);
296 Edge* final = plan_.FindWork();
298 ASSERT_EQ("allTheThings", final->outputs_[0]->path());
300 plan_.EdgeFinished(final);
302 ASSERT_FALSE(plan_.more_to_do());
303 ASSERT_FALSE(plan_.FindWork());
306 TEST_F(PlanTest, PoolWithRedundantEdges) {
307 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
311 " command = touch foo.cpp\n"
313 " command = touch bar.cpp\n"
315 " command = echo $out > $out\n"
316 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
318 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
320 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
321 "build foo.cpp: gen_foo\n"
322 "build bar.cpp: gen_bar\n"
323 "build all: phony libfoo.a\n"));
324 GetNode("foo.cpp")->MarkDirty();
325 GetNode("foo.cpp.obj")->MarkDirty();
326 GetNode("bar.cpp")->MarkDirty();
327 GetNode("bar.cpp.obj")->MarkDirty();
328 GetNode("libfoo.a")->MarkDirty();
329 GetNode("all")->MarkDirty();
331 EXPECT_TRUE(plan_.AddTarget(GetNode("all"), &err));
333 ASSERT_TRUE(plan_.more_to_do());
337 edge = plan_.FindWork();
339 ASSERT_EQ("foo.cpp", edge->outputs_[0]->path());
340 plan_.EdgeFinished(edge);
342 edge = plan_.FindWork();
344 ASSERT_EQ("foo.cpp", edge->inputs_[0]->path());
345 ASSERT_EQ("foo.cpp", edge->inputs_[1]->path());
346 ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path());
347 plan_.EdgeFinished(edge);
349 edge = plan_.FindWork();
351 ASSERT_EQ("bar.cpp", edge->outputs_[0]->path());
352 plan_.EdgeFinished(edge);
354 edge = plan_.FindWork();
356 ASSERT_EQ("bar.cpp", edge->inputs_[0]->path());
357 ASSERT_EQ("bar.cpp", edge->inputs_[1]->path());
358 ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path());
359 plan_.EdgeFinished(edge);
361 edge = plan_.FindWork();
363 ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path());
364 ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path());
365 ASSERT_EQ("libfoo.a", edge->outputs_[0]->path());
366 plan_.EdgeFinished(edge);
368 edge = plan_.FindWork();
370 ASSERT_EQ("libfoo.a", edge->inputs_[0]->path());
371 ASSERT_EQ("all", edge->outputs_[0]->path());
372 plan_.EdgeFinished(edge);
374 edge = plan_.FindWork();
376 ASSERT_FALSE(plan_.more_to_do());
379 /// Fake implementation of CommandRunner, useful for tests.
380 struct FakeCommandRunner : public CommandRunner {
381 explicit FakeCommandRunner(VirtualFileSystem* fs) :
382 last_command_(NULL), fs_(fs) {}
384 // CommandRunner impl
385 virtual bool CanRunMore();
386 virtual bool StartCommand(Edge* edge);
387 virtual bool WaitForCommand(Result* result);
388 virtual vector<Edge*> GetActiveEdges();
389 virtual void Abort();
391 vector<string> commands_ran_;
393 VirtualFileSystem* fs_;
396 struct BuildTest : public StateTestWithBuiltinRules {
397 BuildTest() : config_(MakeConfig()), command_runner_(&fs_),
398 builder_(&state_, config_, NULL, NULL, &fs_),
402 virtual void SetUp() {
403 StateTestWithBuiltinRules::SetUp();
405 builder_.command_runner_.reset(&command_runner_);
407 "build cat1: cat in1\n"
408 "build cat2: cat in1 in2\n"
409 "build cat12: cat cat1 cat2\n");
411 fs_.Create("in1", "");
412 fs_.Create("in2", "");
416 builder_.command_runner_.release();
419 // Mark a path dirty.
420 void Dirty(const string& path);
422 BuildConfig MakeConfig() {
424 config.verbosity = BuildConfig::QUIET;
429 FakeCommandRunner command_runner_;
430 VirtualFileSystem fs_;
436 bool FakeCommandRunner::CanRunMore() {
437 // Only run one at a time.
438 return last_command_ == NULL;
441 bool FakeCommandRunner::StartCommand(Edge* edge) {
442 assert(!last_command_);
443 commands_ran_.push_back(edge->EvaluateCommand());
444 if (edge->rule().name() == "cat" ||
445 edge->rule().name() == "cat_rsp" ||
446 edge->rule().name() == "cc" ||
447 edge->rule().name() == "touch" ||
448 edge->rule().name() == "touch-interrupt") {
449 for (vector<Node*>::iterator out = edge->outputs_.begin();
450 out != edge->outputs_.end(); ++out) {
451 fs_->Create((*out)->path(), "");
453 } else if (edge->rule().name() == "true" ||
454 edge->rule().name() == "fail" ||
455 edge->rule().name() == "interrupt") {
456 // Don't do anything.
458 printf("unknown command\n");
462 last_command_ = edge;
466 bool FakeCommandRunner::WaitForCommand(Result* result) {
470 Edge* edge = last_command_;
473 if (edge->rule().name() == "interrupt" ||
474 edge->rule().name() == "touch-interrupt") {
475 result->status = ExitInterrupted;
479 if (edge->rule().name() == "fail")
480 result->status = ExitFailure;
482 result->status = ExitSuccess;
483 last_command_ = NULL;
487 vector<Edge*> FakeCommandRunner::GetActiveEdges() {
490 edges.push_back(last_command_);
494 void FakeCommandRunner::Abort() {
495 last_command_ = NULL;
498 void BuildTest::Dirty(const string& path) {
499 Node* node = GetNode(path);
502 // If it's an input file, mark that we've already stat()ed it and
504 if (!node->in_edge())
508 TEST_F(BuildTest, NoWork) {
510 EXPECT_TRUE(builder_.AlreadyUpToDate());
513 TEST_F(BuildTest, OneStep) {
514 // Given a dirty target with one ready input,
515 // we should rebuild the target.
518 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
520 EXPECT_TRUE(builder_.Build(&err));
523 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
524 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
527 TEST_F(BuildTest, OneStep2) {
528 // Given a target with one dirty input,
529 // we should rebuild the target.
532 EXPECT_TRUE(builder_.AddTarget("cat1", &err));
534 EXPECT_TRUE(builder_.Build(&err));
537 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
538 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
541 TEST_F(BuildTest, TwoStep) {
543 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
545 EXPECT_TRUE(builder_.Build(&err));
547 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
548 // Depending on how the pointers work out, we could've ran
549 // the first two commands in either order.
550 EXPECT_TRUE((command_runner_.commands_ran_[0] == "cat in1 > cat1" &&
551 command_runner_.commands_ran_[1] == "cat in1 in2 > cat2") ||
552 (command_runner_.commands_ran_[1] == "cat in1 > cat1" &&
553 command_runner_.commands_ran_[0] == "cat in1 in2 > cat2"));
555 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
559 // Modifying in2 requires rebuilding one intermediate file
560 // and the final file.
561 fs_.Create("in2", "");
563 EXPECT_TRUE(builder_.AddTarget("cat12", &err));
565 EXPECT_TRUE(builder_.Build(&err));
567 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
568 EXPECT_EQ("cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
569 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
572 TEST_F(BuildTest, TwoOutputs) {
573 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
575 " command = touch $out\n"
576 "build out1 out2: touch in.txt\n"));
578 fs_.Create("in.txt", "");
581 EXPECT_TRUE(builder_.AddTarget("out1", &err));
583 EXPECT_TRUE(builder_.Build(&err));
585 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
586 EXPECT_EQ("touch out1 out2", command_runner_.commands_ran_[0]);
590 // https://github.com/martine/ninja/issues/148
591 TEST_F(BuildTest, MultiOutIn) {
592 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
594 " command = touch $out\n"
595 "build in1 otherfile: touch in\n"
596 "build out: touch in | in1\n"));
598 fs_.Create("in", "");
600 fs_.Create("in1", "");
603 EXPECT_TRUE(builder_.AddTarget("out", &err));
605 EXPECT_TRUE(builder_.Build(&err));
609 TEST_F(BuildTest, Chain) {
610 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
614 "build c5: cat c4\n"));
616 fs_.Create("c1", "");
619 EXPECT_TRUE(builder_.AddTarget("c5", &err));
621 EXPECT_TRUE(builder_.Build(&err));
623 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
626 command_runner_.commands_ran_.clear();
628 EXPECT_TRUE(builder_.AddTarget("c5", &err));
630 EXPECT_TRUE(builder_.AlreadyUpToDate());
634 fs_.Create("c3", "");
636 command_runner_.commands_ran_.clear();
638 EXPECT_TRUE(builder_.AddTarget("c5", &err));
640 EXPECT_FALSE(builder_.AlreadyUpToDate());
641 EXPECT_TRUE(builder_.Build(&err));
642 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // 3->4, 4->5
645 TEST_F(BuildTest, MissingInput) {
646 // Input is referenced by build file, but no rule for it.
649 EXPECT_FALSE(builder_.AddTarget("cat1", &err));
650 EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it",
654 TEST_F(BuildTest, MissingTarget) {
655 // Target is not referenced by build file.
657 EXPECT_FALSE(builder_.AddTarget("meow", &err));
658 EXPECT_EQ("unknown target: 'meow'", err);
661 TEST_F(BuildTest, MakeDirs) {
665 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
666 "build subdir\\dir2\\file: cat in1\n"));
667 EXPECT_TRUE(builder_.AddTarget("subdir\\dir2\\file", &err));
669 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
670 "build subdir/dir2/file: cat in1\n"));
671 EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err));
675 EXPECT_TRUE(builder_.Build(&err));
677 ASSERT_EQ(2u, fs_.directories_made_.size());
678 EXPECT_EQ("subdir", fs_.directories_made_[0]);
680 EXPECT_EQ("subdir\\dir2", fs_.directories_made_[1]);
682 EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
686 TEST_F(BuildTest, DepFileMissing) {
688 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
689 "rule cc\n command = cc $in\n depfile = $out.d\n"
690 "build foo.o: cc foo.c\n"));
691 fs_.Create("foo.c", "");
693 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
695 ASSERT_EQ(1u, fs_.files_read_.size());
696 EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
699 TEST_F(BuildTest, DepFileOK) {
701 int orig_edges = state_.edges_.size();
702 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
703 "rule cc\n command = cc $in\n depfile = $out.d\n"
704 "build foo.o: cc foo.c\n"));
705 Edge* edge = state_.edges_.back();
707 fs_.Create("foo.c", "");
708 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
709 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
710 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
712 ASSERT_EQ(1u, fs_.files_read_.size());
713 EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
715 // Expect three new edges: one generating foo.o, and two more from
716 // loading the depfile.
717 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
718 // Expect our edge to now have three inputs: foo.c and two headers.
719 ASSERT_EQ(3u, edge->inputs_.size());
721 // Expect the command line we generate to only use the original input.
722 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
725 TEST_F(BuildTest, DepFileParseError) {
727 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
728 "rule cc\n command = cc $in\n depfile = $out.d\n"
729 "build foo.o: cc foo.c\n"));
730 fs_.Create("foo.c", "");
731 fs_.Create("foo.o.d", "randomtext\n");
732 EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
733 EXPECT_EQ("expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
737 TEST_F(BuildTest, OrderOnlyDeps) {
739 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
740 "rule cc\n command = cc $in\n depfile = $out.d\n"
741 "build foo.o: cc foo.c || otherfile\n"));
742 Edge* edge = state_.edges_.back();
744 fs_.Create("foo.c", "");
745 fs_.Create("otherfile", "");
746 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
747 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
750 // One explicit, two implicit, one order only.
751 ASSERT_EQ(4u, edge->inputs_.size());
752 EXPECT_EQ(2, edge->implicit_deps_);
753 EXPECT_EQ(1, edge->order_only_deps_);
754 // Verify the inputs are in the order we expect
755 // (explicit then implicit then orderonly).
756 EXPECT_EQ("foo.c", edge->inputs_[0]->path());
757 EXPECT_EQ("blah.h", edge->inputs_[1]->path());
758 EXPECT_EQ("bar.h", edge->inputs_[2]->path());
759 EXPECT_EQ("otherfile", edge->inputs_[3]->path());
761 // Expect the command line we generate to only use the original input.
762 ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
764 // explicit dep dirty, expect a rebuild.
765 EXPECT_TRUE(builder_.Build(&err));
767 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
771 // Recreate the depfile, as it should have been deleted by the build.
772 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
774 // implicit dep dirty, expect a rebuild.
775 fs_.Create("blah.h", "");
776 fs_.Create("bar.h", "");
777 command_runner_.commands_ran_.clear();
779 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
780 EXPECT_TRUE(builder_.Build(&err));
782 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
786 // Recreate the depfile, as it should have been deleted by the build.
787 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
789 // order only dep dirty, no rebuild.
790 fs_.Create("otherfile", "");
791 command_runner_.commands_ran_.clear();
793 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
795 EXPECT_TRUE(builder_.AlreadyUpToDate());
797 // implicit dep missing, expect rebuild.
798 fs_.RemoveFile("bar.h");
799 command_runner_.commands_ran_.clear();
801 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
802 EXPECT_TRUE(builder_.Build(&err));
804 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
807 TEST_F(BuildTest, RebuildOrderOnlyDeps) {
809 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
810 "rule cc\n command = cc $in\n"
811 "rule true\n command = true\n"
812 "build oo.h: cc oo.h.in\n"
813 "build foo.o: cc foo.c || oo.h\n"));
815 fs_.Create("foo.c", "");
816 fs_.Create("oo.h.in", "");
818 // foo.o and order-only dep dirty, build both.
819 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
820 EXPECT_TRUE(builder_.Build(&err));
822 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
824 // all clean, no rebuild.
825 command_runner_.commands_ran_.clear();
827 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
829 EXPECT_TRUE(builder_.AlreadyUpToDate());
831 // order-only dep missing, build it only.
832 fs_.RemoveFile("oo.h");
833 command_runner_.commands_ran_.clear();
835 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
836 EXPECT_TRUE(builder_.Build(&err));
838 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
839 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
843 // order-only dep dirty, build it only.
844 fs_.Create("oo.h.in", "");
845 command_runner_.commands_ran_.clear();
847 EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
848 EXPECT_TRUE(builder_.Build(&err));
850 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
851 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
854 TEST_F(BuildTest, Phony) {
856 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
857 "build out: cat bar.cc\n"
858 "build all: phony out\n"));
859 fs_.Create("bar.cc", "");
861 EXPECT_TRUE(builder_.AddTarget("all", &err));
864 // Only one command to run, because phony runs no command.
865 EXPECT_FALSE(builder_.AlreadyUpToDate());
866 EXPECT_TRUE(builder_.Build(&err));
868 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
871 TEST_F(BuildTest, PhonyNoWork) {
873 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
874 "build out: cat bar.cc\n"
875 "build all: phony out\n"));
876 fs_.Create("bar.cc", "");
877 fs_.Create("out", "");
879 EXPECT_TRUE(builder_.AddTarget("all", &err));
881 EXPECT_TRUE(builder_.AlreadyUpToDate());
884 TEST_F(BuildTest, Fail) {
885 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
888 "build out1: fail\n"));
891 EXPECT_TRUE(builder_.AddTarget("out1", &err));
894 EXPECT_FALSE(builder_.Build(&err));
895 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
896 ASSERT_EQ("subcommand failed", err);
899 TEST_F(BuildTest, SwallowFailures) {
900 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
906 "build all: phony out1 out2 out3\n"));
908 // Swallow two failures, die on the third.
909 config_.failures_allowed = 3;
912 EXPECT_TRUE(builder_.AddTarget("all", &err));
915 EXPECT_FALSE(builder_.Build(&err));
916 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
917 ASSERT_EQ("subcommands failed", err);
920 TEST_F(BuildTest, SwallowFailuresLimit) {
921 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
927 "build final: cat out1 out2 out3\n"));
929 // Swallow ten failures; we should stop before building final.
930 config_.failures_allowed = 11;
933 EXPECT_TRUE(builder_.AddTarget("final", &err));
936 EXPECT_FALSE(builder_.Build(&err));
937 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
938 ASSERT_EQ("cannot make progress due to previous errors", err);
941 struct BuildWithLogTest : public BuildTest {
943 builder_.SetBuildLog(&build_log_);
949 TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
950 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
953 "build out1: cc in\n"));
955 // Create input/output that would be considered up to date when
956 // not considering the command line hash.
957 fs_.Create("in", "");
958 fs_.Create("out1", "");
961 // Because it's not in the log, it should not be up-to-date until
963 EXPECT_TRUE(builder_.AddTarget("out1", &err));
964 EXPECT_FALSE(builder_.AlreadyUpToDate());
966 command_runner_.commands_ran_.clear();
969 EXPECT_TRUE(builder_.AddTarget("out1", &err));
970 EXPECT_TRUE(builder_.Build(&err));
971 EXPECT_TRUE(builder_.AlreadyUpToDate());
974 TEST_F(BuildWithLogTest, RestatTest) {
975 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
982 "build out1: cc in\n"
983 "build out2: true out1\n"
984 "build out3: cat out2\n"));
986 fs_.Create("out1", "");
987 fs_.Create("out2", "");
988 fs_.Create("out3", "");
992 fs_.Create("in", "");
994 // Do a pre-build so that there's commands in the log for the outputs,
995 // otherwise, the lack of an entry in the build log will cause out3 to rebuild
996 // regardless of restat.
998 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1000 EXPECT_TRUE(builder_.Build(&err));
1002 command_runner_.commands_ran_.clear();
1007 fs_.Create("in", "");
1008 // "cc" touches out1, so we should build out2. But because "true" does not
1009 // touch out2, we should cancel the build of out3.
1010 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1012 EXPECT_TRUE(builder_.Build(&err));
1013 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1015 // If we run again, it should be a no-op, because the build log has recorded
1016 // that we've already built out2 with an input timestamp of 2 (from out1).
1017 command_runner_.commands_ran_.clear();
1019 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1021 EXPECT_TRUE(builder_.AlreadyUpToDate());
1025 fs_.Create("in", "");
1027 // The build log entry should not, however, prevent us from rebuilding out2
1029 command_runner_.commands_ran_.clear();
1031 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1033 EXPECT_TRUE(builder_.Build(&err));
1034 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1037 TEST_F(BuildWithLogTest, RestatMissingFile) {
1038 // If a restat rule doesn't create its output, and the output didn't
1039 // exist before the rule was run, consider that behavior equivalent
1040 // to a rule that doesn't modify its existent output file.
1042 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1048 "build out1: true in\n"
1049 "build out2: cc out1\n"));
1051 fs_.Create("in", "");
1052 fs_.Create("out2", "");
1054 // Do a pre-build so that there's commands in the log for the outputs,
1055 // otherwise, the lack of an entry in the build log will cause out2 to rebuild
1056 // regardless of restat.
1058 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1060 EXPECT_TRUE(builder_.Build(&err));
1062 command_runner_.commands_ran_.clear();
1066 fs_.Create("in", "");
1067 fs_.Create("out2", "");
1069 // Run a build, expect only the first command to run.
1070 // It doesn't touch its output (due to being the "true" command), so
1071 // we shouldn't run the dependent build.
1072 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1074 EXPECT_TRUE(builder_.Build(&err));
1075 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1078 // Test scenario, in which an input file is removed, but output isn't changed
1079 // https://github.com/martine/ninja/issues/295
1080 TEST_F(BuildWithLogTest, RestatMissingInput) {
1081 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1084 " depfile = $out.d\n"
1088 "build out1: true in\n"
1089 "build out2: cc out1\n"));
1091 // Create all necessary files
1092 fs_.Create("in", "");
1094 // The implicit dependencies and the depfile itself
1095 // are newer than the output
1096 TimeStamp restat_mtime = fs_.Tick();
1097 fs_.Create("out1.d", "out1: will.be.deleted restat.file\n");
1098 fs_.Create("will.be.deleted", "");
1099 fs_.Create("restat.file", "");
1101 // Run the build, out1 and out2 get built
1103 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1105 EXPECT_TRUE(builder_.Build(&err));
1106 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1108 // See that an entry in the logfile is created, capturing
1110 BuildLog::LogEntry * log_entry = build_log_.LookupByOutput("out1");
1111 ASSERT_TRUE(NULL != log_entry);
1112 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1114 // Now remove a file, referenced from depfile, so that target becomes
1115 // dirty, but the output does not change
1116 fs_.RemoveFile("will.be.deleted");
1118 // Trigger the build again - only out1 gets built
1119 command_runner_.commands_ran_.clear();
1121 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1123 EXPECT_TRUE(builder_.Build(&err));
1124 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1126 // Check that the logfile entry remains correctly set
1127 log_entry = build_log_.LookupByOutput("out1");
1128 ASSERT_TRUE(NULL != log_entry);
1129 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1132 struct BuildDryRun : public BuildWithLogTest {
1134 config_.dry_run = true;
1138 TEST_F(BuildDryRun, AllCommandsShown) {
1139 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1146 "build out1: cc in\n"
1147 "build out2: true out1\n"
1148 "build out3: cat out2\n"));
1150 fs_.Create("out1", "");
1151 fs_.Create("out2", "");
1152 fs_.Create("out3", "");
1156 fs_.Create("in", "");
1158 // "cc" touches out1, so we should build out2. But because "true" does not
1159 // touch out2, we should cancel the build of out3.
1161 EXPECT_TRUE(builder_.AddTarget("out3", &err));
1163 EXPECT_TRUE(builder_.Build(&err));
1164 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1167 // Test that RSP files are created when & where appropriate and deleted after
1168 // successful execution.
1169 TEST_F(BuildTest, RspFileSuccess)
1171 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1173 " command = cat $rspfile > $out\n"
1174 " rspfile = $rspfile\n"
1175 " rspfile_content = $long_command\n"
1176 "build out1: cat in\n"
1177 "build out2: cat_rsp in\n"
1178 " rspfile = out2.rsp\n"
1179 " long_command = Some very long command\n"));
1181 fs_.Create("out1", "");
1182 fs_.Create("out2", "");
1183 fs_.Create("out3", "");
1187 fs_.Create("in", "");
1190 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1192 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1195 size_t files_created = fs_.files_created_.size();
1196 size_t files_removed = fs_.files_removed_.size();
1198 EXPECT_TRUE(builder_.Build(&err));
1199 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // cat + cat_rsp
1201 // The RSP file was created
1202 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1203 ASSERT_EQ(1u, fs_.files_created_.count("out2.rsp"));
1205 // The RSP file was removed
1206 ASSERT_EQ(files_removed + 1, fs_.files_removed_.size());
1207 ASSERT_EQ(1u, fs_.files_removed_.count("out2.rsp"));
1210 // Test that RSP file is created but not removed for commands, which fail
1211 TEST_F(BuildTest, RspFileFailure) {
1212 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1215 " rspfile = $rspfile\n"
1216 " rspfile_content = $long_command\n"
1217 "build out: fail in\n"
1218 " rspfile = out.rsp\n"
1219 " long_command = Another very long command\n"));
1221 fs_.Create("out", "");
1223 fs_.Create("in", "");
1226 EXPECT_TRUE(builder_.AddTarget("out", &err));
1229 size_t files_created = fs_.files_created_.size();
1230 size_t files_removed = fs_.files_removed_.size();
1232 EXPECT_FALSE(builder_.Build(&err));
1233 ASSERT_EQ("subcommand failed", err);
1234 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1236 // The RSP file was created
1237 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1238 ASSERT_EQ(1u, fs_.files_created_.count("out.rsp"));
1240 // The RSP file was NOT removed
1241 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1242 ASSERT_EQ(0u, fs_.files_removed_.count("out.rsp"));
1244 // The RSP file contains what it should
1245 ASSERT_EQ("Another very long command", fs_.files_["out.rsp"].contents);
1248 // Test that contens of the RSP file behaves like a regular part of
1249 // command line, i.e. triggers a rebuild if changed
1250 TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
1251 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1253 " command = cat $rspfile > $out\n"
1254 " rspfile = $rspfile\n"
1255 " rspfile_content = $long_command\n"
1256 "build out: cat_rsp in\n"
1257 " rspfile = out.rsp\n"
1258 " long_command = Original very long command\n"));
1260 fs_.Create("out", "");
1262 fs_.Create("in", "");
1265 EXPECT_TRUE(builder_.AddTarget("out", &err));
1268 // 1. Build for the 1st time (-> populate log)
1269 EXPECT_TRUE(builder_.Build(&err));
1270 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1272 // 2. Build again (no change)
1273 command_runner_.commands_ran_.clear();
1275 EXPECT_TRUE(builder_.AddTarget("out", &err));
1277 ASSERT_TRUE(builder_.AlreadyUpToDate());
1279 // 3. Alter the entry in the logfile
1280 // (to simulate a change in the command line between 2 builds)
1281 BuildLog::LogEntry * log_entry = build_log_.LookupByOutput("out");
1282 ASSERT_TRUE(NULL != log_entry);
1283 ASSERT_NO_FATAL_FAILURE(AssertHash(
1284 "cat out.rsp > out;rspfile=Original very long command",
1285 log_entry->command_hash));
1286 log_entry->command_hash++; // Change the command hash to something else.
1287 // Now expect the target to be rebuilt
1288 command_runner_.commands_ran_.clear();
1290 EXPECT_TRUE(builder_.AddTarget("out", &err));
1292 EXPECT_TRUE(builder_.Build(&err));
1293 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1296 TEST_F(BuildTest, InterruptCleanup) {
1297 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1299 " command = interrupt\n"
1300 "rule touch-interrupt\n"
1301 " command = touch-interrupt\n"
1302 "build out1: interrupt in1\n"
1303 "build out2: touch-interrupt in2\n"));
1305 fs_.Create("out1", "");
1306 fs_.Create("out2", "");
1308 fs_.Create("in1", "");
1309 fs_.Create("in2", "");
1311 // An untouched output of an interrupted command should be retained.
1313 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1315 EXPECT_FALSE(builder_.Build(&err));
1316 EXPECT_EQ("interrupted by user", err);
1318 EXPECT_GT(fs_.Stat("out1"), 0);
1321 // A touched output of an interrupted command should be deleted.
1322 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1324 EXPECT_FALSE(builder_.Build(&err));
1325 EXPECT_EQ("interrupted by user", err);
1327 EXPECT_EQ(0, fs_.Stat("out2"));
1330 TEST_F(BuildTest, PhonyWithNoInputs) {
1331 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1332 "build nonexistent: phony\n"
1333 "build out1: cat || nonexistent\n"
1334 "build out2: cat nonexistent\n"));
1335 fs_.Create("out1", "");
1336 fs_.Create("out2", "");
1338 // out1 should be up to date even though its input is dirty, because its
1339 // order-only dependency has nothing to do.
1341 EXPECT_TRUE(builder_.AddTarget("out1", &err));
1343 EXPECT_TRUE(builder_.AlreadyUpToDate());
1345 // out2 should still be out of date though, because its input is dirty.
1347 command_runner_.commands_ran_.clear();
1349 EXPECT_TRUE(builder_.AddTarget("out2", &err));
1351 EXPECT_TRUE(builder_.Build(&err));
1353 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1356 TEST_F(BuildTest, DepsGccWithEmptyDeps) {
1357 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1361 "build out: cc\n"));
1365 EXPECT_TRUE(builder_.AddTarget("out", &err));
1367 EXPECT_FALSE(builder_.AlreadyUpToDate());
1369 EXPECT_FALSE(builder_.Build(&err));
1370 ASSERT_EQ("subcommand failed", err);
1371 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1374 TEST_F(BuildTest, StatusFormatReplacePlaceholder) {
1375 EXPECT_EQ("[%/s0/t0/r0/u0/f0]",
1376 status_.FormatProgressStatus("[%%/s%s/t%t/r%r/u%u/f%f]"));
1379 TEST_F(BuildTest, FailedDepsParse) {
1380 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1381 "build bad_deps.o: cat in1\n"
1383 " depfile = in1.d\n"));
1386 EXPECT_TRUE(builder_.AddTarget("bad_deps.o", &err));
1389 // These deps will fail to parse, as they should only have one
1390 // path to the left of the colon.
1391 fs_.Create("in1.d", "AAA BBB");
1393 EXPECT_FALSE(builder_.Build(&err));
1394 EXPECT_EQ("subcommand failed", err);
1397 /// Tests of builds involving deps logs necessarily must span
1398 /// multiple builds. We reuse methods on BuildTest but not the
1399 /// builder_ it sets up, because we want pristine objects for
1401 struct BuildWithDepsLogTest : public BuildTest {
1402 BuildWithDepsLogTest() {}
1404 virtual void SetUp() {
1407 temp_dir_.CreateAndEnter("BuildWithDepsLogTest");
1410 virtual void TearDown() {
1411 temp_dir_.Cleanup();
1414 ScopedTempDir temp_dir_;
1416 /// Shadow parent class builder_ so we don't accidentally use it.
1420 /// Run a straightforwad build where the deps log is used.
1421 TEST_F(BuildWithDepsLogTest, Straightforward) {
1423 // Note: in1 was created by the superclass SetUp().
1424 const char* manifest =
1425 "build out: cat in1\n"
1427 " depfile = in1.d\n";
1430 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1431 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1433 // Run the build once, everything should be ok.
1435 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1438 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1439 builder.command_runner_.reset(&command_runner_);
1440 EXPECT_TRUE(builder.AddTarget("out", &err));
1442 fs_.Create("in1.d", "out: in2");
1443 EXPECT_TRUE(builder.Build(&err));
1446 // The deps file should have been removed.
1447 EXPECT_EQ(0, fs_.Stat("in1.d"));
1448 // Recreate it for the next step.
1449 fs_.Create("in1.d", "out: in2");
1451 builder.command_runner_.release();
1456 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1457 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1459 // Touch the file only mentioned in the deps.
1461 fs_.Create("in2", "");
1463 // Run the build again.
1465 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
1466 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1468 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1469 builder.command_runner_.reset(&command_runner_);
1470 command_runner_.commands_ran_.clear();
1471 EXPECT_TRUE(builder.AddTarget("out", &err));
1473 EXPECT_TRUE(builder.Build(&err));
1476 // We should have rebuilt the output due to in2 being
1478 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1480 builder.command_runner_.release();
1484 /// Verify that obsolete dependency info causes a rebuild.
1485 /// 1) Run a successful build where everything has time t, record deps.
1486 /// 2) Move input/output to time t+1 -- despite files in alignment,
1487 /// should still need to rebuild due to deps at older time.
1488 TEST_F(BuildWithDepsLogTest, ObsoleteDeps) {
1490 // Note: in1 was created by the superclass SetUp().
1491 const char* manifest =
1492 "build out: cat in1\n"
1494 " depfile = in1.d\n";
1496 // Run an ordinary build that gathers dependencies.
1497 fs_.Create("in1", "");
1498 fs_.Create("in1.d", "out: ");
1501 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1502 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1504 // Run the build once, everything should be ok.
1506 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1509 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1510 builder.command_runner_.reset(&command_runner_);
1511 EXPECT_TRUE(builder.AddTarget("out", &err));
1513 EXPECT_TRUE(builder.Build(&err));
1517 builder.command_runner_.release();
1520 // Push all files one tick forward so that only the deps are out
1523 fs_.Create("in1", "");
1524 fs_.Create("out", "");
1526 // The deps file should have been removed, so no need to timestamp it.
1527 EXPECT_EQ(0, fs_.Stat("in1.d"));
1531 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1532 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
1535 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
1536 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
1538 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1539 builder.command_runner_.reset(&command_runner_);
1540 command_runner_.commands_ran_.clear();
1541 EXPECT_TRUE(builder.AddTarget("out", &err));
1544 // Recreate the deps file here because the build expects them to exist.
1545 fs_.Create("in1.d", "out: ");
1547 EXPECT_TRUE(builder.Build(&err));
1550 // We should have rebuilt the output due to the deps being
1552 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1554 builder.command_runner_.release();