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