497faa4228ceb6f3c9ae73bcff933c068cca4e72
[platform/upstream/ninja.git] / src / build_test.cc
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 "build_log.h"
18 #include "graph.h"
19 #include "test.h"
20
21 /// Fixture for tests involving Plan.
22 // Though Plan doesn't use State, it's useful to have one around
23 // to create Nodes and Edges.
24 struct PlanTest : public StateTestWithBuiltinRules {
25   Plan plan_;
26 };
27
28 TEST_F(PlanTest, Basic) {
29   AssertParse(&state_,
30 "build out: cat mid\n"
31 "build mid: cat in\n");
32   GetNode("mid")->MarkDirty();
33   GetNode("out")->MarkDirty();
34   string err;
35   EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
36   ASSERT_EQ("", err);
37   ASSERT_TRUE(plan_.more_to_do());
38
39   Edge* edge = plan_.FindWork();
40   ASSERT_TRUE(edge);
41   ASSERT_EQ("in",  edge->inputs_[0]->path());
42   ASSERT_EQ("mid", edge->outputs_[0]->path());
43
44   ASSERT_FALSE(plan_.FindWork());
45
46   plan_.EdgeFinished(edge);
47
48   edge = plan_.FindWork();
49   ASSERT_TRUE(edge);
50   ASSERT_EQ("mid", edge->inputs_[0]->path());
51   ASSERT_EQ("out", edge->outputs_[0]->path());
52
53   plan_.EdgeFinished(edge);
54
55   ASSERT_FALSE(plan_.more_to_do());
56   edge = plan_.FindWork();
57   ASSERT_EQ(0, edge);
58 }
59
60 // Test that two outputs from one rule can be handled as inputs to the next.
61 TEST_F(PlanTest, DoubleOutputDirect) {
62   AssertParse(&state_,
63 "build out: cat mid1 mid2\n"
64 "build mid1 mid2: cat in\n");
65   GetNode("mid1")->MarkDirty();
66   GetNode("mid2")->MarkDirty();
67   GetNode("out")->MarkDirty();
68
69   string err;
70   EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
71   ASSERT_EQ("", err);
72   ASSERT_TRUE(plan_.more_to_do());
73
74   Edge* edge;
75   edge = plan_.FindWork();
76   ASSERT_TRUE(edge);  // cat in
77   plan_.EdgeFinished(edge);
78
79   edge = plan_.FindWork();
80   ASSERT_TRUE(edge);  // cat mid1 mid2
81   plan_.EdgeFinished(edge);
82
83   edge = plan_.FindWork();
84   ASSERT_FALSE(edge);  // done
85 }
86
87 // Test that two outputs from one rule can eventually be routed to another.
88 TEST_F(PlanTest, DoubleOutputIndirect) {
89   AssertParse(&state_,
90 "build out: cat b1 b2\n"
91 "build b1: cat a1\n"
92 "build b2: cat a2\n"
93 "build a1 a2: cat in\n");
94   GetNode("a1")->MarkDirty();
95   GetNode("a2")->MarkDirty();
96   GetNode("b1")->MarkDirty();
97   GetNode("b2")->MarkDirty();
98   GetNode("out")->MarkDirty();
99   string err;
100   EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
101   ASSERT_EQ("", err);
102   ASSERT_TRUE(plan_.more_to_do());
103
104   Edge* edge;
105   edge = plan_.FindWork();
106   ASSERT_TRUE(edge);  // cat in
107   plan_.EdgeFinished(edge);
108
109   edge = plan_.FindWork();
110   ASSERT_TRUE(edge);  // cat a1
111   plan_.EdgeFinished(edge);
112
113   edge = plan_.FindWork();
114   ASSERT_TRUE(edge);  // cat a2
115   plan_.EdgeFinished(edge);
116
117   edge = plan_.FindWork();
118   ASSERT_TRUE(edge);  // cat b1 b2
119   plan_.EdgeFinished(edge);
120
121   edge = plan_.FindWork();
122   ASSERT_FALSE(edge);  // done
123 }
124
125 // Test that two edges from one output can both execute.
126 TEST_F(PlanTest, DoubleDependent) {
127   AssertParse(&state_,
128 "build out: cat a1 a2\n"
129 "build a1: cat mid\n"
130 "build a2: cat mid\n"
131 "build mid: cat in\n");
132   GetNode("mid")->MarkDirty();
133   GetNode("a1")->MarkDirty();
134   GetNode("a2")->MarkDirty();
135   GetNode("out")->MarkDirty();
136
137   string err;
138   EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err));
139   ASSERT_EQ("", err);
140   ASSERT_TRUE(plan_.more_to_do());
141
142   Edge* edge;
143   edge = plan_.FindWork();
144   ASSERT_TRUE(edge);  // cat in
145   plan_.EdgeFinished(edge);
146
147   edge = plan_.FindWork();
148   ASSERT_TRUE(edge);  // cat mid
149   plan_.EdgeFinished(edge);
150
151   edge = plan_.FindWork();
152   ASSERT_TRUE(edge);  // cat mid
153   plan_.EdgeFinished(edge);
154
155   edge = plan_.FindWork();
156   ASSERT_TRUE(edge);  // cat a1 a2
157   plan_.EdgeFinished(edge);
158
159   edge = plan_.FindWork();
160   ASSERT_FALSE(edge);  // done
161 }
162
163 TEST_F(PlanTest, DependencyCycle) {
164   AssertParse(&state_,
165 "build out: cat mid\n"
166 "build mid: cat in\n"
167 "build in: cat pre\n"
168 "build pre: cat out\n");
169   GetNode("out")->MarkDirty();
170   GetNode("mid")->MarkDirty();
171   GetNode("in")->MarkDirty();
172   GetNode("pre")->MarkDirty();
173
174   string err;
175   EXPECT_FALSE(plan_.AddTarget(GetNode("out"), &err));
176   ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err);
177 }
178
179 struct BuildTest : public StateTestWithBuiltinRules,
180                    public CommandRunner {
181   BuildTest() : config_(MakeConfig()), builder_(&state_, config_), now_(1),
182                 last_command_(NULL) {
183     builder_.disk_interface_ = &fs_;
184     builder_.command_runner_ = this;
185     AssertParse(&state_,
186 "build cat1: cat in1\n"
187 "build cat2: cat in1 in2\n"
188 "build cat12: cat cat1 cat2\n");
189
190     fs_.Create("in1", now_, "");
191     fs_.Create("in2", now_, "");
192   }
193
194   // Mark a path dirty.
195   void Dirty(const string& path);
196
197   // CommandRunner impl
198   virtual bool CanRunMore();
199   virtual bool StartCommand(Edge* edge);
200   virtual Edge* WaitForCommand(bool* success, string* output);
201
202   BuildConfig MakeConfig() {
203     BuildConfig config;
204     config.verbosity = BuildConfig::QUIET;
205     return config;
206   }
207
208   BuildConfig config_;
209   Builder builder_;
210   int now_;
211
212   VirtualFileSystem fs_;
213
214   vector<string> commands_ran_;
215   Edge* last_command_;
216 };
217
218 void BuildTest::Dirty(const string& path) {
219   Node* node = GetNode(path);
220   node->MarkDirty();
221
222   // If it's an input file, mark that we've already stat()ed it and
223   // it's missing.
224   if (!node->in_edge())
225     node->MarkMissing();
226 }
227
228 bool BuildTest::CanRunMore() {
229   // Only run one at a time.
230   return last_command_ == NULL;
231 }
232
233 bool BuildTest::StartCommand(Edge* edge) {
234   assert(!last_command_);
235   commands_ran_.push_back(edge->EvaluateCommand());
236   if (edge->rule().name() == "cat" || edge->rule_->name() == "cc" ||
237       edge->rule().name() == "touch") {
238     for (vector<Node*>::iterator out = edge->outputs_.begin();
239          out != edge->outputs_.end(); ++out) {
240       fs_.Create((*out)->path(), now_, "");
241     }
242   } else if (edge->rule().name() == "true" ||
243              edge->rule().name() == "fail") {
244     // Don't do anything.
245   } else {
246     printf("unknown command\n");
247     return false;
248   }
249
250   last_command_ = edge;
251   return true;
252 }
253
254 Edge* BuildTest::WaitForCommand(bool* success, string* output) {
255   if (Edge* edge = last_command_) {
256     if (edge->rule().name() == "fail")
257       *success = false;
258     else
259       *success = true;
260     last_command_ = NULL;
261     return edge;
262   }
263   return NULL;
264 }
265
266 TEST_F(BuildTest, NoWork) {
267   string err;
268   EXPECT_TRUE(builder_.AlreadyUpToDate());
269 }
270
271 TEST_F(BuildTest, OneStep) {
272   // Given a dirty target with one ready input,
273   // we should rebuild the target.
274   Dirty("cat1");
275   string err;
276   EXPECT_TRUE(builder_.AddTarget("cat1", &err));
277   ASSERT_EQ("", err);
278   EXPECT_TRUE(builder_.Build(&err));
279   ASSERT_EQ("", err);
280
281   ASSERT_EQ(1u, commands_ran_.size());
282   EXPECT_EQ("cat in1 > cat1", commands_ran_[0]);
283 }
284
285 TEST_F(BuildTest, OneStep2) {
286   // Given a target with one dirty input,
287   // we should rebuild the target.
288   Dirty("cat1");
289   string err;
290   EXPECT_TRUE(builder_.AddTarget("cat1", &err));
291   ASSERT_EQ("", err);
292   EXPECT_TRUE(builder_.Build(&err));
293   EXPECT_EQ("", err);
294
295   ASSERT_EQ(1u, commands_ran_.size());
296   EXPECT_EQ("cat in1 > cat1", commands_ran_[0]);
297 }
298
299 TEST_F(BuildTest, TwoStep) {
300   string err;
301   EXPECT_TRUE(builder_.AddTarget("cat12", &err));
302   ASSERT_EQ("", err);
303   EXPECT_TRUE(builder_.Build(&err));
304   EXPECT_EQ("", err);
305   ASSERT_EQ(3u, commands_ran_.size());
306   // Depending on how the pointers work out, we could've ran
307   // the first two commands in either order.
308   EXPECT_TRUE((commands_ran_[0] == "cat in1 > cat1" &&
309                commands_ran_[1] == "cat in1 in2 > cat2") ||
310               (commands_ran_[1] == "cat in1 > cat1" &&
311                commands_ran_[0] == "cat in1 in2 > cat2"));
312
313   EXPECT_EQ("cat cat1 cat2 > cat12", commands_ran_[2]);
314
315   now_++;
316
317   // Modifying in2 requires rebuilding one intermediate file
318   // and the final file.
319   fs_.Create("in2", now_, "");
320   state_.Reset();
321   EXPECT_TRUE(builder_.AddTarget("cat12", &err));
322   ASSERT_EQ("", err);
323   EXPECT_TRUE(builder_.Build(&err));
324   ASSERT_EQ("", err);
325   ASSERT_EQ(5u, commands_ran_.size());
326   EXPECT_EQ("cat in1 in2 > cat2", commands_ran_[3]);
327   EXPECT_EQ("cat cat1 cat2 > cat12", commands_ran_[4]);
328 }
329
330 TEST_F(BuildTest, TwoOutputs) {
331   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
332 "rule touch\n"
333 "  command = touch $out\n"
334 "build out1 out2: touch in.txt\n"));
335
336   fs_.Create("in.txt", now_, "");
337
338   string err;
339   EXPECT_TRUE(builder_.AddTarget("out1", &err));
340   ASSERT_EQ("", err);
341   EXPECT_TRUE(builder_.Build(&err));
342   EXPECT_EQ("", err);
343   ASSERT_EQ(1u, commands_ran_.size());
344   EXPECT_EQ("touch out1 out2", commands_ran_[0]);
345 }
346
347 // Test case from
348 //   https://github.com/martine/ninja/issues/148
349 TEST_F(BuildTest, MultiOutIn) {
350   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
351 "rule touch\n"
352 "  command = touch $out\n"
353 "build in1 otherfile: touch in\n"
354 "build out: touch in | in1\n"));
355
356   fs_.Create("in", now_, "");
357   fs_.Create("in1", ++now_, "");
358
359   string err;
360   EXPECT_TRUE(builder_.AddTarget("out", &err));
361   ASSERT_EQ("", err);
362   EXPECT_TRUE(builder_.Build(&err));
363   EXPECT_EQ("", err);
364 }
365
366 TEST_F(BuildTest, Chain) {
367   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
368 "build c2: cat c1\n"
369 "build c3: cat c2\n"
370 "build c4: cat c3\n"
371 "build c5: cat c4\n"));
372
373   fs_.Create("c1", now_, "");
374
375   string err;
376   EXPECT_TRUE(builder_.AddTarget("c5", &err));
377   ASSERT_EQ("", err);
378   EXPECT_TRUE(builder_.Build(&err));
379   EXPECT_EQ("", err);
380   ASSERT_EQ(4u, commands_ran_.size());
381
382   err.clear();
383   commands_ran_.clear();
384   state_.Reset();
385   EXPECT_TRUE(builder_.AddTarget("c5", &err));
386   ASSERT_EQ("", err);
387   EXPECT_TRUE(builder_.AlreadyUpToDate());
388
389   now_++;
390
391   fs_.Create("c3", now_, "");
392   err.clear();
393   commands_ran_.clear();
394   state_.Reset();
395   EXPECT_TRUE(builder_.AddTarget("c5", &err));
396   ASSERT_EQ("", err);
397   EXPECT_FALSE(builder_.AlreadyUpToDate());
398   EXPECT_TRUE(builder_.Build(&err));
399   ASSERT_EQ(2u, commands_ran_.size());  // 3->4, 4->5
400 }
401
402 TEST_F(BuildTest, MissingInput) {
403   // Input is referenced by build file, but no rule for it.
404   string err;
405   Dirty("in1");
406   EXPECT_FALSE(builder_.AddTarget("cat1", &err));
407   EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it",
408             err);
409 }
410
411 TEST_F(BuildTest, MissingTarget) {
412   // Target is not referenced by build file.
413   string err;
414   EXPECT_FALSE(builder_.AddTarget("meow", &err));
415   EXPECT_EQ("unknown target: 'meow'", err);
416 }
417
418 TEST_F(BuildTest, MakeDirs) {
419   string err;
420
421 #ifdef WIN32
422   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir\\dir2\\file: cat in1\n"));
423   EXPECT_TRUE(builder_.AddTarget("subdir\\dir2\\file", &err));
424 #else
425   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir/dir2/file: cat in1\n"));
426   EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err));
427 #endif
428
429   EXPECT_EQ("", err);
430   now_ = 0;  // Make all stat()s return file not found.
431   EXPECT_TRUE(builder_.Build(&err));
432   ASSERT_EQ("", err);
433   ASSERT_EQ(2u, fs_.directories_made_.size());
434   EXPECT_EQ("subdir", fs_.directories_made_[0]);
435 #ifdef WIN32
436   EXPECT_EQ("subdir\\dir2", fs_.directories_made_[1]);
437 #else
438   EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
439 #endif
440 }
441
442 TEST_F(BuildTest, DepFileMissing) {
443   string err;
444   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
445 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
446 "build foo.o: cc foo.c\n"));
447   fs_.Create("foo.c", now_, "");
448
449   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
450   ASSERT_EQ("", err);
451   ASSERT_EQ(1u, fs_.files_read_.size());
452   EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
453 }
454
455 TEST_F(BuildTest, DepFileOK) {
456   string err;
457   int orig_edges = state_.edges_.size();
458   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
459 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
460 "build foo.o: cc foo.c\n"));
461   Edge* edge = state_.edges_.back();
462
463   fs_.Create("foo.c", now_, "");
464   GetNode("bar.h")->MarkDirty();  // Mark bar.h as missing.
465   fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
466   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
467   ASSERT_EQ("", err);
468   ASSERT_EQ(1u, fs_.files_read_.size());
469   EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
470
471   // Expect three new edges: one generating foo.o, and two more from
472   // loading the depfile.
473   ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
474   // Expect our edge to now have three inputs: foo.c and two headers.
475   ASSERT_EQ(3u, edge->inputs_.size());
476
477   // Expect the command line we generate to only use the original input.
478   ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
479 }
480
481 TEST_F(BuildTest, DepFileParseError) {
482   string err;
483   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
484 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
485 "build foo.o: cc foo.c\n"));
486   fs_.Create("foo.c", now_, "");
487   fs_.Create("foo.o.d", now_, "randomtext\n");
488   EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
489   EXPECT_EQ("expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
490             err);
491 }
492
493 TEST_F(BuildTest, OrderOnlyDeps) {
494   string err;
495   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
496 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
497 "build foo.o: cc foo.c || otherfile\n"));
498   Edge* edge = state_.edges_.back();
499
500   fs_.Create("foo.c", now_, "");
501   fs_.Create("otherfile", now_, "");
502   fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
503   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
504   ASSERT_EQ("", err);
505
506   // One explicit, two implicit, one order only.
507   ASSERT_EQ(4u, edge->inputs_.size());
508   EXPECT_EQ(2, edge->implicit_deps_);
509   EXPECT_EQ(1, edge->order_only_deps_);
510   // Verify the inputs are in the order we expect
511   // (explicit then implicit then orderonly).
512   EXPECT_EQ("foo.c", edge->inputs_[0]->path());
513   EXPECT_EQ("blah.h", edge->inputs_[1]->path());
514   EXPECT_EQ("bar.h", edge->inputs_[2]->path());
515   EXPECT_EQ("otherfile", edge->inputs_[3]->path());
516
517   // Expect the command line we generate to only use the original input.
518   ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
519
520   // explicit dep dirty, expect a rebuild.
521   EXPECT_TRUE(builder_.Build(&err));
522   ASSERT_EQ("", err);
523   ASSERT_EQ(1u, commands_ran_.size());
524
525   now_++;
526
527   // implicit dep dirty, expect a rebuild.
528   fs_.Create("blah.h", now_, "");
529   fs_.Create("bar.h", now_, "");
530   commands_ran_.clear();
531   state_.Reset();
532   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
533   EXPECT_TRUE(builder_.Build(&err));
534   ASSERT_EQ("", err);
535   ASSERT_EQ(1u, commands_ran_.size());
536
537   now_++;
538
539   // order only dep dirty, no rebuild.
540   fs_.Create("otherfile", now_, "");
541   commands_ran_.clear();
542   state_.Reset();
543   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
544   EXPECT_EQ("", err);
545   EXPECT_TRUE(builder_.AlreadyUpToDate());
546
547   // implicit dep missing, expect rebuild.
548   fs_.RemoveFile("bar.h");
549   commands_ran_.clear();
550   state_.Reset();
551   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
552   EXPECT_TRUE(builder_.Build(&err));
553   ASSERT_EQ("", err);
554   ASSERT_EQ(1u, commands_ran_.size());
555 }
556
557 TEST_F(BuildTest, RebuildOrderOnlyDeps) {
558   string err;
559   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
560 "rule cc\n  command = cc $in\n"
561 "rule true\n  command = true\n"
562 "build oo.h: cc oo.h.in\n"
563 "build foo.o: cc foo.c || oo.h\n"));
564
565   fs_.Create("foo.c", now_, "");
566   fs_.Create("oo.h.in", now_, "");
567
568   // foo.o and order-only dep dirty, build both.
569   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
570   EXPECT_TRUE(builder_.Build(&err));
571   ASSERT_EQ("", err);
572   ASSERT_EQ(2u, commands_ran_.size());
573
574   // all clean, no rebuild.
575   commands_ran_.clear();
576   state_.Reset();
577   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
578   EXPECT_EQ("", err);
579   EXPECT_TRUE(builder_.AlreadyUpToDate());
580
581   // order-only dep missing, build it only.
582   fs_.RemoveFile("oo.h");
583   commands_ran_.clear();
584   state_.Reset();
585   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
586   EXPECT_TRUE(builder_.Build(&err));
587   ASSERT_EQ("", err);
588   ASSERT_EQ(1u, commands_ran_.size());
589   ASSERT_EQ("cc oo.h.in", commands_ran_[0]);
590
591   now_++;
592
593   // order-only dep dirty, build it only.
594   fs_.Create("oo.h.in", now_, "");
595   commands_ran_.clear();
596   state_.Reset();
597   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
598   EXPECT_TRUE(builder_.Build(&err));
599   ASSERT_EQ("", err);
600   ASSERT_EQ(1u, commands_ran_.size());
601   ASSERT_EQ("cc oo.h.in", commands_ran_[0]);
602 }
603
604 TEST_F(BuildTest, Phony) {
605   string err;
606   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
607 "build out: cat bar.cc\n"
608 "build all: phony out\n"));
609   fs_.Create("bar.cc", now_, "");
610
611   EXPECT_TRUE(builder_.AddTarget("all", &err));
612   ASSERT_EQ("", err);
613
614   // Only one command to run, because phony runs no command.
615   EXPECT_FALSE(builder_.AlreadyUpToDate());
616   EXPECT_TRUE(builder_.Build(&err));
617   ASSERT_EQ("", err);
618   ASSERT_EQ(1u, commands_ran_.size());
619 }
620
621 TEST_F(BuildTest, PhonyNoWork) {
622   string err;
623   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
624 "build out: cat bar.cc\n"
625 "build all: phony out\n"));
626   fs_.Create("bar.cc", now_, "");
627   fs_.Create("out", now_, "");
628
629   EXPECT_TRUE(builder_.AddTarget("all", &err));
630   ASSERT_EQ("", err);
631   EXPECT_TRUE(builder_.AlreadyUpToDate());
632 }
633
634 TEST_F(BuildTest, Fail) {
635   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
636 "rule fail\n"
637 "  command = fail\n"
638 "build out1: fail\n"));
639
640   string err;
641   EXPECT_TRUE(builder_.AddTarget("out1", &err));
642   ASSERT_EQ("", err);
643
644   EXPECT_FALSE(builder_.Build(&err));
645   ASSERT_EQ(1u, commands_ran_.size());
646   ASSERT_EQ("subcommand failed", err);
647 }
648
649 TEST_F(BuildTest, SwallowFailures) {
650   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
651 "rule fail\n"
652 "  command = fail\n"
653 "build out1: fail\n"
654 "build out2: fail\n"
655 "build out3: fail\n"
656 "build all: phony out1 out2 out3\n"));
657
658   // Swallow two failures, die on the third.
659   config_.swallow_failures = 2;
660
661   string err;
662   EXPECT_TRUE(builder_.AddTarget("all", &err));
663   ASSERT_EQ("", err);
664
665   EXPECT_FALSE(builder_.Build(&err));
666   ASSERT_EQ(3u, commands_ran_.size());
667   ASSERT_EQ("subcommands failed", err);
668 }
669
670 TEST_F(BuildTest, SwallowFailuresLimit) {
671   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
672 "rule fail\n"
673 "  command = fail\n"
674 "build out1: fail\n"
675 "build out2: fail\n"
676 "build out3: fail\n"
677 "build final: cat out1 out2 out3\n"));
678
679   // Swallow ten failures; we should stop before building final.
680   config_.swallow_failures = 10;
681
682   string err;
683   EXPECT_TRUE(builder_.AddTarget("final", &err));
684   ASSERT_EQ("", err);
685
686   EXPECT_FALSE(builder_.Build(&err));
687   ASSERT_EQ(3u, commands_ran_.size());
688   ASSERT_EQ("cannot make progress due to previous errors", err);
689 }
690
691 struct BuildWithLogTest : public BuildTest {
692   BuildWithLogTest() {
693     state_.build_log_ = builder_.log_ = &build_log_;
694   }
695
696   BuildLog build_log_;
697 };
698
699 TEST_F(BuildWithLogTest, RestatTest) {
700   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
701 "rule true\n"
702 "  command = true\n"
703 "  restat = 1\n"
704 "rule cc\n"
705 "  command = cc\n"
706 "  restat = 1\n"
707 "build out1: cc in\n"
708 "build out2: true out1\n"
709 "build out3: cat out2\n"));
710
711   fs_.Create("out1", now_, "");
712   fs_.Create("out2", now_, "");
713   fs_.Create("out3", now_, "");
714
715   now_++;
716
717   fs_.Create("in", now_, "");
718
719   // "cc" touches out1, so we should build out2.  But because "true" does not
720   // touch out2, we should cancel the build of out3.
721   string err;
722   EXPECT_TRUE(builder_.AddTarget("out3", &err));
723   ASSERT_EQ("", err);
724   EXPECT_TRUE(builder_.Build(&err));
725   ASSERT_EQ(2u, commands_ran_.size());
726
727   // If we run again, it should be a no-op, because the build log has recorded
728   // that we've already built out2 with an input timestamp of 2 (from out1).
729   commands_ran_.clear();
730   state_.Reset();
731   EXPECT_TRUE(builder_.AddTarget("out3", &err));
732   ASSERT_EQ("", err);
733   EXPECT_TRUE(builder_.AlreadyUpToDate());
734
735   now_++;
736
737   fs_.Create("in", now_, "");
738
739   // The build log entry should not, however, prevent us from rebuilding out2
740   // if out1 changes.
741   commands_ran_.clear();
742   state_.Reset();
743   EXPECT_TRUE(builder_.AddTarget("out3", &err));
744   ASSERT_EQ("", err);
745   EXPECT_TRUE(builder_.Build(&err));
746   ASSERT_EQ(2u, commands_ran_.size());
747 }
748
749 TEST_F(BuildWithLogTest, RestatMissingFile) {
750   // If a restat rule doesn't create its output, and the output didn't
751   // exist before the rule was run, consider that behavior equivalent
752   // to a rule that doesn't modify its existent output file.
753
754   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
755 "rule true\n"
756 "  command = true\n"
757 "  restat = 1\n"
758 "rule cc\n"
759 "  command = cc\n"
760 "build out1: true in\n"
761 "build out2: cc out1\n"));
762
763   fs_.Create("in", now_, "");
764   fs_.Create("out2", now_, "");
765
766   // Run a build, expect only the first command to run.
767   // It doesn't touch its output (due to being the "true" command), so
768   // we shouldn't run the dependent build.
769   string err;
770   EXPECT_TRUE(builder_.AddTarget("out2", &err));
771   ASSERT_EQ("", err);
772   EXPECT_TRUE(builder_.Build(&err));
773   ASSERT_EQ(1u, commands_ran_.size());
774 }
775
776 struct BuildDryRun : public BuildWithLogTest {
777   BuildDryRun() {
778     config_.dry_run = true;
779   }
780 };
781
782 TEST_F(BuildDryRun, AllCommandsShown) {
783   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
784 "rule true\n"
785 "  command = true\n"
786 "  restat = 1\n"
787 "rule cc\n"
788 "  command = cc\n"
789 "  restat = 1\n"
790 "build out1: cc in\n"
791 "build out2: true out1\n"
792 "build out3: cat out2\n"));
793
794   fs_.Create("out1", now_, "");
795   fs_.Create("out2", now_, "");
796   fs_.Create("out3", now_, "");
797
798   now_++;
799
800   fs_.Create("in", now_, "");
801
802   // "cc" touches out1, so we should build out2.  But because "true" does not
803   // touch out2, we should cancel the build of out3.
804   string err;
805   EXPECT_TRUE(builder_.AddTarget("out3", &err));
806   ASSERT_EQ("", err);
807   EXPECT_TRUE(builder_.Build(&err));
808   ASSERT_EQ(3u, commands_ran_.size());
809 }
810