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