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