|
Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "build.h" 00016 00017 #include "build_log.h" 00018 #include "graph.h" 00019 #include "test.h" 00020 00021 /// Fixture for tests involving Plan. 00022 // Though Plan doesn't use State, it's useful to have one around 00023 // to create Nodes and Edges. 00024 struct PlanTest : public StateTestWithBuiltinRules { 00025 Plan plan_; 00026 }; 00027 00028 TEST_F(PlanTest, Basic) { 00029 AssertParse(&state_, 00030 "build out: cat mid\n" 00031 "build mid: cat in\n"); 00032 GetNode("mid")->dirty_ = true; 00033 GetNode("out")->dirty_ = true; 00034 string err; 00035 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00036 ASSERT_EQ("", err); 00037 ASSERT_TRUE(plan_.more_to_do()); 00038 00039 Edge* edge = plan_.FindWork(); 00040 ASSERT_TRUE(edge); 00041 ASSERT_EQ("in", edge->inputs_[0]->file_->path_); 00042 ASSERT_EQ("mid", edge->outputs_[0]->file_->path_); 00043 00044 ASSERT_FALSE(plan_.FindWork()); 00045 00046 plan_.EdgeFinished(edge); 00047 00048 edge = plan_.FindWork(); 00049 ASSERT_TRUE(edge); 00050 ASSERT_EQ("mid", edge->inputs_[0]->file_->path_); 00051 ASSERT_EQ("out", edge->outputs_[0]->file_->path_); 00052 00053 plan_.EdgeFinished(edge); 00054 00055 ASSERT_FALSE(plan_.more_to_do()); 00056 edge = plan_.FindWork(); 00057 ASSERT_EQ(0, edge); 00058 } 00059 00060 // Test that two outputs from one rule can be handled as inputs to the next. 00061 TEST_F(PlanTest, DoubleOutputDirect) { 00062 AssertParse(&state_, 00063 "build out: cat mid1 mid2\n" 00064 "build mid1 mid2: cat in\n"); 00065 GetNode("mid1")->dirty_ = true; 00066 GetNode("mid2")->dirty_ = true; 00067 GetNode("out")->dirty_ = true; 00068 00069 string err; 00070 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00071 ASSERT_EQ("", err); 00072 ASSERT_TRUE(plan_.more_to_do()); 00073 00074 Edge* edge; 00075 edge = plan_.FindWork(); 00076 ASSERT_TRUE(edge); // cat in 00077 plan_.EdgeFinished(edge); 00078 00079 edge = plan_.FindWork(); 00080 ASSERT_TRUE(edge); // cat mid1 mid2 00081 plan_.EdgeFinished(edge); 00082 00083 edge = plan_.FindWork(); 00084 ASSERT_FALSE(edge); // done 00085 } 00086 00087 // Test that two outputs from one rule can eventually be routed to another. 00088 TEST_F(PlanTest, DoubleOutputIndirect) { 00089 AssertParse(&state_, 00090 "build out: cat b1 b2\n" 00091 "build b1: cat a1\n" 00092 "build b2: cat a2\n" 00093 "build a1 a2: cat in\n"); 00094 GetNode("a1")->dirty_ = true; 00095 GetNode("a2")->dirty_ = true; 00096 GetNode("b1")->dirty_ = true; 00097 GetNode("b2")->dirty_ = true; 00098 GetNode("out")->dirty_ = true; 00099 string err; 00100 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00101 ASSERT_EQ("", err); 00102 ASSERT_TRUE(plan_.more_to_do()); 00103 00104 Edge* edge; 00105 edge = plan_.FindWork(); 00106 ASSERT_TRUE(edge); // cat in 00107 plan_.EdgeFinished(edge); 00108 00109 edge = plan_.FindWork(); 00110 ASSERT_TRUE(edge); // cat a1 00111 plan_.EdgeFinished(edge); 00112 00113 edge = plan_.FindWork(); 00114 ASSERT_TRUE(edge); // cat a2 00115 plan_.EdgeFinished(edge); 00116 00117 edge = plan_.FindWork(); 00118 ASSERT_TRUE(edge); // cat b1 b2 00119 plan_.EdgeFinished(edge); 00120 00121 edge = plan_.FindWork(); 00122 ASSERT_FALSE(edge); // done 00123 } 00124 00125 // Test that two edges from one output can both execute. 00126 TEST_F(PlanTest, DoubleDependent) { 00127 AssertParse(&state_, 00128 "build out: cat a1 a2\n" 00129 "build a1: cat mid\n" 00130 "build a2: cat mid\n" 00131 "build mid: cat in\n"); 00132 GetNode("mid")->dirty_ = true; 00133 GetNode("a1")->dirty_ = true; 00134 GetNode("a2")->dirty_ = true; 00135 GetNode("out")->dirty_ = true; 00136 00137 string err; 00138 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00139 ASSERT_EQ("", err); 00140 ASSERT_TRUE(plan_.more_to_do()); 00141 00142 Edge* edge; 00143 edge = plan_.FindWork(); 00144 ASSERT_TRUE(edge); // cat in 00145 plan_.EdgeFinished(edge); 00146 00147 edge = plan_.FindWork(); 00148 ASSERT_TRUE(edge); // cat mid 00149 plan_.EdgeFinished(edge); 00150 00151 edge = plan_.FindWork(); 00152 ASSERT_TRUE(edge); // cat mid 00153 plan_.EdgeFinished(edge); 00154 00155 edge = plan_.FindWork(); 00156 ASSERT_TRUE(edge); // cat a1 a2 00157 plan_.EdgeFinished(edge); 00158 00159 edge = plan_.FindWork(); 00160 ASSERT_FALSE(edge); // done 00161 } 00162 00163 TEST_F(PlanTest, DependencyCycle) { 00164 AssertParse(&state_, 00165 "build out: cat mid\n" 00166 "build mid: cat in\n" 00167 "build in: cat pre\n" 00168 "build pre: cat out\n"); 00169 GetNode("out")->dirty_ = true; 00170 GetNode("mid")->dirty_ = true; 00171 GetNode("in")->dirty_ = true; 00172 GetNode("pre")->dirty_ = true; 00173 00174 string err; 00175 EXPECT_FALSE(plan_.AddTarget(GetNode("out"), &err)); 00176 ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err); 00177 } 00178 00179 struct BuildTest : public StateTestWithBuiltinRules, 00180 public CommandRunner { 00181 BuildTest() : config_(MakeConfig()), builder_(&state_, config_), now_(1), 00182 last_command_(NULL) { 00183 builder_.disk_interface_ = &fs_; 00184 builder_.command_runner_ = this; 00185 AssertParse(&state_, 00186 "build cat1: cat in1\n" 00187 "build cat2: cat in1 in2\n" 00188 "build cat12: cat cat1 cat2\n"); 00189 00190 fs_.Create("in1", now_, ""); 00191 fs_.Create("in2", now_, ""); 00192 } 00193 00194 // Mark a path dirty. 00195 void Dirty(const string& path); 00196 00197 // CommandRunner impl 00198 virtual bool CanRunMore(); 00199 virtual bool StartCommand(Edge* edge); 00200 virtual Edge* WaitForCommand(bool* success, string* output); 00201 00202 BuildConfig MakeConfig() { 00203 BuildConfig config; 00204 config.verbosity = BuildConfig::QUIET; 00205 return config; 00206 } 00207 00208 BuildConfig config_; 00209 Builder builder_; 00210 int now_; 00211 00212 VirtualFileSystem fs_; 00213 00214 vector<string> commands_ran_; 00215 Edge* last_command_; 00216 }; 00217 00218 void BuildTest::Dirty(const string& path) { 00219 Node* node = GetNode(path); 00220 node->dirty_ = true; 00221 00222 // If it's an input file, mark that we've already stat()ed it and 00223 // it's missing. 00224 if (!node->in_edge_) 00225 node->file_->mtime_ = 0; 00226 } 00227 00228 bool BuildTest::CanRunMore() { 00229 // Only run one at a time. 00230 return last_command_ == NULL; 00231 } 00232 00233 bool BuildTest::StartCommand(Edge* edge) { 00234 assert(!last_command_); 00235 commands_ran_.push_back(edge->EvaluateCommand()); 00236 if (edge->rule_->name_ == "cat" || edge->rule_->name_ == "cc" || 00237 edge->rule_->name_ == "touch") { 00238 for (vector<Node*>::iterator out = edge->outputs_.begin(); 00239 out != edge->outputs_.end(); ++out) { 00240 fs_.Create((*out)->file_->path_, now_, ""); 00241 } 00242 } else if (edge->rule_->name_ == "true" || 00243 edge->rule_->name_ == "fail") { 00244 // Don't do anything. 00245 } else { 00246 printf("unknown command\n"); 00247 return false; 00248 } 00249 00250 last_command_ = edge; 00251 return true; 00252 } 00253 00254 Edge* BuildTest::WaitForCommand(bool* success, string* output) { 00255 if (Edge* edge = last_command_) { 00256 if (edge->rule_->name_ == "fail") 00257 *success = false; 00258 else 00259 *success = true; 00260 last_command_ = NULL; 00261 return edge; 00262 } 00263 return NULL; 00264 } 00265 00266 TEST_F(BuildTest, NoWork) { 00267 string err; 00268 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00269 } 00270 00271 TEST_F(BuildTest, OneStep) { 00272 // Given a dirty target with one ready input, 00273 // we should rebuild the target. 00274 Dirty("cat1"); 00275 string err; 00276 EXPECT_TRUE(builder_.AddTarget("cat1", &err)); 00277 ASSERT_EQ("", err); 00278 EXPECT_TRUE(builder_.Build(&err)); 00279 ASSERT_EQ("", err); 00280 00281 ASSERT_EQ(1u, commands_ran_.size()); 00282 EXPECT_EQ("cat in1 > cat1", commands_ran_[0]); 00283 } 00284 00285 TEST_F(BuildTest, OneStep2) { 00286 // Given a target with one dirty input, 00287 // we should rebuild the target. 00288 Dirty("cat1"); 00289 string err; 00290 EXPECT_TRUE(builder_.AddTarget("cat1", &err)); 00291 ASSERT_EQ("", err); 00292 EXPECT_TRUE(builder_.Build(&err)); 00293 EXPECT_EQ("", err); 00294 00295 ASSERT_EQ(1u, commands_ran_.size()); 00296 EXPECT_EQ("cat in1 > cat1", commands_ran_[0]); 00297 } 00298 00299 TEST_F(BuildTest, TwoStep) { 00300 string err; 00301 EXPECT_TRUE(builder_.AddTarget("cat12", &err)); 00302 ASSERT_EQ("", err); 00303 EXPECT_TRUE(builder_.Build(&err)); 00304 EXPECT_EQ("", err); 00305 ASSERT_EQ(3u, commands_ran_.size()); 00306 // Depending on how the pointers work out, we could've ran 00307 // the first two commands in either order. 00308 EXPECT_TRUE((commands_ran_[0] == "cat in1 > cat1" && 00309 commands_ran_[1] == "cat in1 in2 > cat2") || 00310 (commands_ran_[1] == "cat in1 > cat1" && 00311 commands_ran_[0] == "cat in1 in2 > cat2")); 00312 00313 EXPECT_EQ("cat cat1 cat2 > cat12", commands_ran_[2]); 00314 00315 now_++; 00316 00317 // Modifying in2 requires rebuilding one intermediate file 00318 // and the final file. 00319 fs_.Create("in2", now_, ""); 00320 state_.Reset(); 00321 EXPECT_TRUE(builder_.AddTarget("cat12", &err)); 00322 ASSERT_EQ("", err); 00323 EXPECT_TRUE(builder_.Build(&err)); 00324 ASSERT_EQ("", err); 00325 ASSERT_EQ(5u, commands_ran_.size()); 00326 EXPECT_EQ("cat in1 in2 > cat2", commands_ran_[3]); 00327 EXPECT_EQ("cat cat1 cat2 > cat12", commands_ran_[4]); 00328 } 00329 00330 TEST_F(BuildTest, TwoOutputs) { 00331 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00332 "rule touch\n" 00333 " command = touch $out\n" 00334 "build out1 out2: touch in.txt\n")); 00335 00336 fs_.Create("in.txt", now_, ""); 00337 00338 string err; 00339 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00340 ASSERT_EQ("", err); 00341 EXPECT_TRUE(builder_.Build(&err)); 00342 EXPECT_EQ("", err); 00343 ASSERT_EQ(1u, commands_ran_.size()); 00344 EXPECT_EQ("touch out1 out2", commands_ran_[0]); 00345 } 00346 00347 TEST_F(BuildTest, Chain) { 00348 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00349 "build c2: cat c1\n" 00350 "build c3: cat c2\n" 00351 "build c4: cat c3\n" 00352 "build c5: cat c4\n")); 00353 00354 fs_.Create("c1", now_, ""); 00355 00356 string err; 00357 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00358 ASSERT_EQ("", err); 00359 EXPECT_TRUE(builder_.Build(&err)); 00360 EXPECT_EQ("", err); 00361 ASSERT_EQ(4u, commands_ran_.size()); 00362 00363 err.clear(); 00364 commands_ran_.clear(); 00365 state_.Reset(); 00366 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00367 ASSERT_EQ("", err); 00368 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00369 00370 now_++; 00371 00372 fs_.Create("c3", now_, ""); 00373 err.clear(); 00374 commands_ran_.clear(); 00375 state_.Reset(); 00376 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00377 ASSERT_EQ("", err); 00378 EXPECT_FALSE(builder_.AlreadyUpToDate()); 00379 EXPECT_TRUE(builder_.Build(&err)); 00380 ASSERT_EQ(2u, commands_ran_.size()); // 3->4, 4->5 00381 } 00382 00383 TEST_F(BuildTest, MissingInput) { 00384 // Input is referenced by build file, but no rule for it. 00385 string err; 00386 Dirty("in1"); 00387 EXPECT_FALSE(builder_.AddTarget("cat1", &err)); 00388 EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it", 00389 err); 00390 } 00391 00392 TEST_F(BuildTest, MissingTarget) { 00393 // Target is not referenced by build file. 00394 string err; 00395 EXPECT_FALSE(builder_.AddTarget("meow", &err)); 00396 EXPECT_EQ("unknown target: 'meow'", err); 00397 } 00398 00399 TEST_F(BuildTest, MakeDirs) { 00400 string err; 00401 00402 #ifdef WIN32 00403 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir\\dir2\\file: cat in1\n")); 00404 EXPECT_TRUE(builder_.AddTarget("subdir\\dir2\\file", &err)); 00405 #else 00406 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir/dir2/file: cat in1\n")); 00407 EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err)); 00408 #endif 00409 00410 EXPECT_EQ("", err); 00411 now_ = 0; // Make all stat()s return file not found. 00412 EXPECT_TRUE(builder_.Build(&err)); 00413 ASSERT_EQ("", err); 00414 ASSERT_EQ(2u, fs_.directories_made_.size()); 00415 EXPECT_EQ("subdir", fs_.directories_made_[0]); 00416 #ifdef WIN32 00417 EXPECT_EQ("subdir\\dir2", fs_.directories_made_[1]); 00418 #else 00419 EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]); 00420 #endif 00421 } 00422 00423 TEST_F(BuildTest, DepFileMissing) { 00424 string err; 00425 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00426 "rule cc\n command = cc $in\n depfile = $out.d\n" 00427 "build foo.o: cc foo.c\n")); 00428 fs_.Create("foo.c", now_, ""); 00429 00430 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00431 ASSERT_EQ("", err); 00432 ASSERT_EQ(1u, fs_.files_read_.size()); 00433 EXPECT_EQ("foo.o.d", fs_.files_read_[0]); 00434 } 00435 00436 TEST_F(BuildTest, DepFileOK) { 00437 string err; 00438 int orig_edges = state_.edges_.size(); 00439 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00440 "rule cc\n command = cc $in\n depfile = $out.d\n" 00441 "build foo.o: cc foo.c\n")); 00442 Edge* edge = state_.edges_.back(); 00443 00444 fs_.Create("foo.c", now_, ""); 00445 GetNode("bar.h")->dirty_ = true; // Mark bar.h as missing. 00446 fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n"); 00447 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00448 ASSERT_EQ("", err); 00449 ASSERT_EQ(1u, fs_.files_read_.size()); 00450 EXPECT_EQ("foo.o.d", fs_.files_read_[0]); 00451 00452 // Expect three new edges: one generating foo.o, and two more from 00453 // loading the depfile. 00454 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size()); 00455 // Expect our edge to now have three inputs: foo.c and two headers. 00456 ASSERT_EQ(3u, edge->inputs_.size()); 00457 00458 // Expect the command line we generate to only use the original input. 00459 ASSERT_EQ("cc foo.c", edge->EvaluateCommand()); 00460 } 00461 00462 TEST_F(BuildTest, DepFileParseError) { 00463 string err; 00464 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00465 "rule cc\n command = cc $in\n depfile = $out.d\n" 00466 "build foo.o: cc foo.c\n")); 00467 fs_.Create("foo.c", now_, ""); 00468 fs_.Create("foo.o.d", now_, "foo.o blah.h bar.h\n"); 00469 EXPECT_FALSE(builder_.AddTarget("foo.o", &err)); 00470 EXPECT_EQ("foo.o.d: line 1, col 7: expected ':', got 'blah.h'", err); 00471 } 00472 00473 TEST_F(BuildTest, OrderOnlyDeps) { 00474 string err; 00475 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00476 "rule cc\n command = cc $in\n depfile = $out.d\n" 00477 "build foo.o: cc foo.c || otherfile\n")); 00478 Edge* edge = state_.edges_.back(); 00479 00480 fs_.Create("foo.c", now_, ""); 00481 fs_.Create("otherfile", now_, ""); 00482 fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n"); 00483 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00484 ASSERT_EQ("", err); 00485 00486 // One explicit, two implicit, one order only. 00487 ASSERT_EQ(4u, edge->inputs_.size()); 00488 EXPECT_EQ(2, edge->implicit_deps_); 00489 EXPECT_EQ(1, edge->order_only_deps_); 00490 // Verify the inputs are in the order we expect 00491 // (explicit then implicit then orderonly). 00492 EXPECT_EQ("foo.c", edge->inputs_[0]->file_->path_); 00493 EXPECT_EQ("blah.h", edge->inputs_[1]->file_->path_); 00494 EXPECT_EQ("bar.h", edge->inputs_[2]->file_->path_); 00495 EXPECT_EQ("otherfile", edge->inputs_[3]->file_->path_); 00496 00497 // Expect the command line we generate to only use the original input. 00498 ASSERT_EQ("cc foo.c", edge->EvaluateCommand()); 00499 00500 // explicit dep dirty, expect a rebuild. 00501 EXPECT_TRUE(builder_.Build(&err)); 00502 ASSERT_EQ("", err); 00503 ASSERT_EQ(1u, commands_ran_.size()); 00504 00505 now_++; 00506 00507 // implicit dep dirty, expect a rebuild. 00508 fs_.Create("blah.h", now_, ""); 00509 fs_.Create("bar.h", now_, ""); 00510 commands_ran_.clear(); 00511 state_.Reset(); 00512 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00513 EXPECT_TRUE(builder_.Build(&err)); 00514 ASSERT_EQ("", err); 00515 ASSERT_EQ(1u, commands_ran_.size()); 00516 00517 now_++; 00518 00519 // order only dep dirty, no rebuild. 00520 fs_.Create("otherfile", now_, ""); 00521 commands_ran_.clear(); 00522 state_.Reset(); 00523 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00524 EXPECT_EQ("", err); 00525 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00526 00527 // implicit dep missing, expect rebuild. 00528 fs_.RemoveFile("bar.h"); 00529 commands_ran_.clear(); 00530 state_.Reset(); 00531 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00532 EXPECT_TRUE(builder_.Build(&err)); 00533 ASSERT_EQ("", err); 00534 ASSERT_EQ(1u, commands_ran_.size()); 00535 } 00536 00537 TEST_F(BuildTest, RebuildOrderOnlyDeps) { 00538 string err; 00539 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00540 "rule cc\n command = cc $in\n" 00541 "rule true\n command = true\n" 00542 "build oo.h: cc oo.h.in\n" 00543 "build foo.o: cc foo.c || oo.h\n")); 00544 00545 fs_.Create("foo.c", now_, ""); 00546 fs_.Create("oo.h.in", now_, ""); 00547 00548 // foo.o and order-only dep dirty, build both. 00549 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00550 EXPECT_TRUE(builder_.Build(&err)); 00551 ASSERT_EQ("", err); 00552 ASSERT_EQ(2u, commands_ran_.size()); 00553 00554 // all clean, no rebuild. 00555 commands_ran_.clear(); 00556 state_.Reset(); 00557 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00558 EXPECT_EQ("", err); 00559 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00560 00561 // order-only dep missing, build it only. 00562 fs_.RemoveFile("oo.h"); 00563 commands_ran_.clear(); 00564 state_.Reset(); 00565 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00566 EXPECT_TRUE(builder_.Build(&err)); 00567 ASSERT_EQ("", err); 00568 ASSERT_EQ(1u, commands_ran_.size()); 00569 ASSERT_EQ("cc oo.h.in", commands_ran_[0]); 00570 00571 now_++; 00572 00573 // order-only dep dirty, build it only. 00574 fs_.Create("oo.h.in", now_, ""); 00575 commands_ran_.clear(); 00576 state_.Reset(); 00577 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00578 EXPECT_TRUE(builder_.Build(&err)); 00579 ASSERT_EQ("", err); 00580 ASSERT_EQ(1u, commands_ran_.size()); 00581 ASSERT_EQ("cc oo.h.in", commands_ran_[0]); 00582 } 00583 00584 TEST_F(BuildTest, Phony) { 00585 string err; 00586 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00587 "build out: cat bar.cc\n" 00588 "build all: phony out\n")); 00589 fs_.Create("bar.cc", now_, ""); 00590 00591 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00592 ASSERT_EQ("", err); 00593 00594 // Only one command to run, because phony runs no command. 00595 EXPECT_FALSE(builder_.AlreadyUpToDate()); 00596 EXPECT_TRUE(builder_.Build(&err)); 00597 ASSERT_EQ("", err); 00598 ASSERT_EQ(1u, commands_ran_.size()); 00599 } 00600 00601 TEST_F(BuildTest, PhonyNoWork) { 00602 string err; 00603 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00604 "build out: cat bar.cc\n" 00605 "build all: phony out\n")); 00606 fs_.Create("bar.cc", now_, ""); 00607 fs_.Create("out", now_, ""); 00608 00609 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00610 ASSERT_EQ("", err); 00611 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00612 } 00613 00614 TEST_F(BuildTest, Fail) { 00615 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00616 "rule fail\n" 00617 " command = fail\n" 00618 "build out1: fail\n")); 00619 00620 string err; 00621 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00622 ASSERT_EQ("", err); 00623 00624 EXPECT_FALSE(builder_.Build(&err)); 00625 ASSERT_EQ(1u, commands_ran_.size()); 00626 ASSERT_EQ("subcommand failed", err); 00627 } 00628 00629 TEST_F(BuildTest, SwallowFailures) { 00630 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00631 "rule fail\n" 00632 " command = fail\n" 00633 "build out1: fail\n" 00634 "build out2: fail\n" 00635 "build out3: fail\n" 00636 "build all: phony out1 out2 out3\n")); 00637 00638 // Swallow two failures, die on the third. 00639 config_.swallow_failures = 2; 00640 00641 string err; 00642 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00643 ASSERT_EQ("", err); 00644 00645 EXPECT_FALSE(builder_.Build(&err)); 00646 ASSERT_EQ(3u, commands_ran_.size()); 00647 ASSERT_EQ("subcommands failed", err); 00648 } 00649 00650 TEST_F(BuildTest, SwallowFailuresLimit) { 00651 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00652 "rule fail\n" 00653 " command = fail\n" 00654 "build out1: fail\n" 00655 "build out2: fail\n" 00656 "build out3: fail\n" 00657 "build final: cat out1 out2 out3\n")); 00658 00659 // Swallow ten failures; we should stop before building final. 00660 config_.swallow_failures = 10; 00661 00662 string err; 00663 EXPECT_TRUE(builder_.AddTarget("final", &err)); 00664 ASSERT_EQ("", err); 00665 00666 EXPECT_FALSE(builder_.Build(&err)); 00667 ASSERT_EQ(3u, commands_ran_.size()); 00668 ASSERT_EQ("cannot make progress due to previous errors", err); 00669 } 00670 00671 struct BuildWithLogTest : public BuildTest { 00672 BuildWithLogTest() { 00673 state_.build_log_ = builder_.log_ = &build_log_; 00674 } 00675 00676 BuildLog build_log_; 00677 }; 00678 00679 TEST_F(BuildWithLogTest, RestatTest) { 00680 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00681 "rule true\n" 00682 " command = true\n" 00683 " restat = 1\n" 00684 "rule cc\n" 00685 " command = cc\n" 00686 " restat = 1\n" 00687 "build out1: cc in\n" 00688 "build out2: true out1\n" 00689 "build out3: cat out2\n")); 00690 00691 fs_.Create("out1", now_, ""); 00692 fs_.Create("out2", now_, ""); 00693 fs_.Create("out3", now_, ""); 00694 00695 now_++; 00696 00697 fs_.Create("in", now_, ""); 00698 00699 // "cc" touches out1, so we should build out2. But because "true" does not 00700 // touch out2, we should cancel the build of out3. 00701 string err; 00702 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 00703 ASSERT_EQ("", err); 00704 EXPECT_TRUE(builder_.Build(&err)); 00705 ASSERT_EQ(2u, commands_ran_.size()); 00706 00707 // If we run again, it should be a no-op, because the build log has recorded 00708 // that we've already built out2 with an input timestamp of 2 (from out1). 00709 commands_ran_.clear(); 00710 state_.Reset(); 00711 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 00712 ASSERT_EQ("", err); 00713 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00714 00715 now_++; 00716 00717 fs_.Create("in", now_, ""); 00718 00719 // The build log entry should not, however, prevent us from rebuilding out2 00720 // if out1 changes. 00721 commands_ran_.clear(); 00722 state_.Reset(); 00723 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 00724 ASSERT_EQ("", err); 00725 EXPECT_TRUE(builder_.Build(&err)); 00726 ASSERT_EQ(2u, commands_ran_.size()); 00727 }
1.7.5.1