42 for (
int i = 0; i < count; ++i) {
52 void TestPoolWithDepthOne(
const char *test_case);
57 "build out: cat mid\n" 58 "build mid: cat in\n"));
59 GetNode(
"mid")->MarkDirty();
60 GetNode(
"out")->MarkDirty();
66 Edge* edge = plan_.FindWork();
68 ASSERT_EQ(
"in", edge->inputs_[0]->path());
69 ASSERT_EQ(
"mid", edge->outputs_[0]->path());
76 edge = plan_.FindWork();
78 ASSERT_EQ(
"mid", edge->inputs_[0]->path());
79 ASSERT_EQ(
"out", edge->outputs_[0]->path());
85 edge = plan_.FindWork();
92 "build out: cat mid1 mid2\n" 93 "build mid1 mid2: cat in\n"));
94 GetNode(
"mid1")->MarkDirty();
95 GetNode(
"mid2")->MarkDirty();
96 GetNode(
"out")->MarkDirty();
104 edge = plan_.FindWork();
109 edge = plan_.FindWork();
114 edge = plan_.FindWork();
121 "build out: cat b1 b2\n" 124 "build a1 a2: cat in\n"));
125 GetNode(
"a1")->MarkDirty();
126 GetNode(
"a2")->MarkDirty();
127 GetNode(
"b1")->MarkDirty();
128 GetNode(
"b2")->MarkDirty();
129 GetNode(
"out")->MarkDirty();
131 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
136 edge = plan_.FindWork();
141 edge = plan_.FindWork();
146 edge = plan_.FindWork();
151 edge = plan_.FindWork();
156 edge = plan_.FindWork();
163 "build out: cat a1 a2\n" 164 "build a1: cat mid\n" 165 "build a2: cat mid\n" 166 "build mid: cat in\n"));
167 GetNode(
"mid")->MarkDirty();
168 GetNode(
"a1")->MarkDirty();
169 GetNode(
"a2")->MarkDirty();
170 GetNode(
"out")->MarkDirty();
173 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
178 edge = plan_.FindWork();
183 edge = plan_.FindWork();
188 edge = plan_.FindWork();
193 edge = plan_.FindWork();
198 edge = plan_.FindWork();
204 GetNode(
"out1")->MarkDirty();
205 GetNode(
"out2")->MarkDirty();
207 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
209 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
213 Edge* edge = plan_.FindWork();
215 ASSERT_EQ(
"in", edge->inputs_[0]->path());
216 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
224 edge = plan_.FindWork();
226 ASSERT_EQ(
"in", edge->inputs_[0]->path());
227 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
235 edge = plan_.FindWork();
240 TestPoolWithDepthOne(
244 " command = cat $in > $out\n" 246 "build out1: poolcat in\n" 247 "build out2: poolcat in\n");
251 TestPoolWithDepthOne(
253 " command = cat $in > $out\n" 255 "build out1: poolcat in\n" 256 "build out2: poolcat in\n");
266 " command = cat $in > $out\n" 269 " command = cat $in > $out\n" 271 "build out1: foocat in\n" 272 "build out2: foocat in\n" 273 "build out3: foocat in\n" 274 "build outb1: bazcat in\n" 275 "build outb2: bazcat in\n" 276 "build outb3: bazcat in\n" 278 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n" 281 for (
int i = 0; i < 3; ++i) {
282 GetNode(
"out" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
283 GetNode(
"outb" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
285 GetNode(
"allTheThings")->MarkDirty();
288 EXPECT_TRUE(plan_.AddTarget(GetNode(
"allTheThings"), &err));
292 FindWorkSorted(&edges, 5);
294 for (
int i = 0; i < 4; ++i) {
295 Edge *edge = edges[i];
297 string base_name(i < 2 ?
"out" :
"outb");
302 Edge* edge = edges[4];
313 Edge* out3 = plan_.FindWork();
325 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
330 Edge* last = plan_.FindWork();
346 " command = touch foo.cpp\n" 348 " command = touch bar.cpp\n" 350 " command = echo $out > $out\n" 351 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n" 353 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n" 355 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n" 356 "build foo.cpp: gen_foo\n" 357 "build bar.cpp: gen_bar\n" 358 "build all: phony libfoo.a\n"));
359 GetNode(
"foo.cpp")->MarkDirty();
360 GetNode(
"foo.cpp.obj")->MarkDirty();
361 GetNode(
"bar.cpp")->MarkDirty();
362 GetNode(
"bar.cpp.obj")->MarkDirty();
363 GetNode(
"libfoo.a")->MarkDirty();
364 GetNode(
"all")->MarkDirty();
366 EXPECT_TRUE(plan_.AddTarget(GetNode(
"all"), &err));
372 deque<Edge*> initial_edges;
373 FindWorkSorted(&initial_edges, 2);
375 edge = initial_edges[1];
376 ASSERT_EQ(
"foo.cpp", edge->outputs_[0]->path());
380 edge = plan_.FindWork();
383 ASSERT_EQ(
"foo.cpp", edge->inputs_[0]->path());
384 ASSERT_EQ(
"foo.cpp", edge->inputs_[1]->path());
385 ASSERT_EQ(
"foo.cpp.obj", edge->outputs_[0]->path());
389 edge = initial_edges[0];
390 ASSERT_EQ(
"bar.cpp", edge->outputs_[0]->path());
394 edge = plan_.FindWork();
397 ASSERT_EQ(
"bar.cpp", edge->inputs_[0]->path());
398 ASSERT_EQ(
"bar.cpp", edge->inputs_[1]->path());
399 ASSERT_EQ(
"bar.cpp.obj", edge->outputs_[0]->path());
403 edge = plan_.FindWork();
406 ASSERT_EQ(
"foo.cpp.obj", edge->inputs_[0]->path());
407 ASSERT_EQ(
"bar.cpp.obj", edge->inputs_[1]->path());
408 ASSERT_EQ(
"libfoo.a", edge->outputs_[0]->path());
412 edge = plan_.FindWork();
415 ASSERT_EQ(
"libfoo.a", edge->inputs_[0]->path());
416 ASSERT_EQ(
"all", edge->outputs_[0]->path());
420 edge = plan_.FindWork();
430 " command = cat $in > $out\n" 432 "build out1: poolcat in\n" 433 "build out2: poolcat in\n"));
434 GetNode(
"out1")->MarkDirty();
435 GetNode(
"out2")->MarkDirty();
437 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
439 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
443 Edge* edge = plan_.FindWork();
445 ASSERT_EQ(
"in", edge->inputs_[0]->path());
446 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
454 edge = plan_.FindWork();
456 ASSERT_EQ(
"in", edge->inputs_[0]->path());
457 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
465 edge = plan_.FindWork();
472 max_active_edges_(1), fs_(fs) {}
475 virtual bool CanRunMore()
const;
476 virtual bool StartCommand(
Edge* edge);
477 virtual bool WaitForCommand(Result* result);
478 virtual vector<Edge*> GetActiveEdges();
479 virtual void Abort();
488 BuildTest() : config_(MakeConfig()), command_runner_(&fs_),
489 builder_(&state_, config_, NULL, NULL, &fs_),
494 builder_(&state_, config_, NULL, log, &fs_),
501 builder_.command_runner_.reset(&command_runner_);
503 "build cat1: cat in1\n" 504 "build cat2: cat in1 in2\n" 505 "build cat12: cat cat1 cat2\n");
507 fs_.Create(
"in1",
"");
508 fs_.Create(
"in2",
"");
512 builder_.command_runner_.release();
520 void RebuildTarget(
const string& target,
const char* manifest,
521 const char* log_path = NULL,
const char* deps_path = NULL,
522 State* state = NULL);
525 void Dirty(
const string& path);
542 const char* log_path,
const char* deps_path,
544 State local_state, *pstate = &local_state;
551 BuildLog build_log, *pbuild_log = NULL;
556 pbuild_log = &build_log;
559 DepsLog deps_log, *pdeps_log = NULL;
564 pdeps_log = &deps_log;
567 Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_);
570 command_runner_.commands_ran_.clear();
573 bool build_res = builder.
Build(&err);
580 return active_edges_.size() < max_active_edges_;
584 assert(active_edges_.size() < max_active_edges_);
585 assert(find(active_edges_.begin(), active_edges_.end(), edge)
586 == active_edges_.end());
590 edge->
rule().
name() ==
"cat_rsp_out" ||
592 edge->
rule().
name() ==
"cp_multi_msvc" ||
593 edge->
rule().
name() ==
"cp_multi_gcc" ||
595 edge->
rule().
name() ==
"touch-interrupt" ||
596 edge->
rule().
name() ==
"touch-fail-tick2") {
597 for (vector<Node*>::iterator out = edge->
outputs_.begin();
598 out != edge->
outputs_.end(); ++out) {
599 fs_->Create((*out)->path(),
"");
601 }
else if (edge->
rule().
name() ==
"true" ||
603 edge->
rule().
name() ==
"interrupt" ||
606 }
else if (edge->
rule().
name() ==
"cp") {
607 assert(!edge->
inputs_.empty());
611 if (fs_->ReadFile(edge->
inputs_[0]->path(), &content, &err) ==
613 fs_->WriteFile(edge->
outputs_[0]->path(), content);
615 printf(
"unknown command\n");
619 active_edges_.push_back(edge);
622 sort(active_edges_.begin(), active_edges_.end(),
629 if (active_edges_.empty())
635 vector<Edge*>::iterator edge_iter = active_edges_.end() - 1;
637 Edge* edge = *edge_iter;
640 if (edge->
rule().
name() ==
"interrupt" ||
641 edge->
rule().
name() ==
"touch-interrupt") {
646 if (edge->
rule().
name() ==
"console") {
651 active_edges_.erase(edge_iter);
655 if (edge->
rule().
name() ==
"cp_multi_msvc") {
656 const std::string prefix = edge->
GetBinding(
"msvc_deps_prefix");
657 for (std::vector<Node*>::iterator in = edge->
inputs_.begin();
658 in != edge->
inputs_.end(); ++in) {
659 result->
output += prefix + (*in)->path() +
'\n';
663 if (edge->
rule().
name() ==
"fail" ||
664 (edge->
rule().
name() ==
"touch-fail-tick2" && fs_->now_ == 2))
672 const string& verify_active_edge = edge->
GetBinding(
"verify_active_edge");
673 if (!verify_active_edge.empty()) {
674 bool verify_active_edge_found =
false;
675 for (vector<Edge*>::iterator i = active_edges_.begin();
676 i != active_edges_.end(); ++i) {
677 if (!(*i)->outputs_.empty() &&
678 (*i)->outputs_[0]->path() == verify_active_edge) {
679 verify_active_edge_found =
true;
685 active_edges_.erase(edge_iter);
690 return active_edges_;
694 active_edges_.clear();
698 Node* node = GetNode(path);
722 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
723 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
736 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
737 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
746 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
749 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
750 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
751 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
752 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
754 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
760 fs_.Create(
"in2",
"");
766 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
767 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
768 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
774 " command = touch $out\n" 775 "build out1 out2: touch in.txt\n"));
777 fs_.Create(
"in.txt",
"");
784 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
785 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
791 " command = touch $out $out.imp\n" 792 "build out | out.imp: touch in.txt\n"));
793 fs_.Create(
"in.txt",
"");
800 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
801 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[0]);
809 " command = touch $out\n" 810 "build in1 otherfile: touch in\n" 811 "build out: touch in | in1\n"));
813 fs_.Create(
"in",
"");
815 fs_.Create(
"in1",
"");
829 "build c5: cat c4\n"));
831 fs_.Create(
"c1",
"");
838 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
841 command_runner_.commands_ran_.clear();
849 fs_.Create(
"c3",
"");
851 command_runner_.commands_ran_.clear();
857 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
865 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
873 EXPECT_EQ(
"unknown target: 'meow'", err);
881 "build subdir\\dir2\\file: cat in1\n"));
884 "build subdir/dir2/file: cat in1\n"));
886 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
891 ASSERT_EQ(2u, fs_.directories_made_.size());
892 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
893 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
899 "rule cc\n command = cc $in\n depfile = $out.d\n" 900 "build fo$ o.o: cc foo.c\n"));
901 fs_.Create(
"foo.c",
"");
906 EXPECT_EQ(
"fo o.o.d", fs_.files_read_[0]);
911 int orig_edges = state_.edges_.size();
913 "rule cc\n command = cc $in\n depfile = $out.d\n" 914 "build foo.o: cc foo.c\n"));
915 Edge* edge = state_.edges_.back();
917 fs_.Create(
"foo.c",
"");
918 GetNode(
"bar.h")->MarkDirty();
919 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
923 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
927 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
938 "rule cc\n command = cc $in\n depfile = $out.d\n" 939 "build foo.o: cc foo.c\n"));
940 fs_.Create(
"foo.c",
"");
941 fs_.Create(
"foo.o.d",
"randomtext\n");
943 EXPECT_EQ(
"foo.o.d: expected ':' in depfile", err);
950 " command = touch $out\n" 952 "build b: touch || c\n" 953 "build a: touch | b || c\n"));
955 vector<Edge*> c_out = GetNode(
"c")->out_edges();
957 EXPECT_EQ(
"b", c_out[0]->outputs_[0]->path());
958 EXPECT_EQ(
"a", c_out[1]->outputs_[0]->path());
966 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
972 "rule cc\n command = cc $in\n depfile = $out.d\n" 973 "build foo.o: cc foo.c || otherfile\n"));
974 Edge* edge = state_.edges_.back();
976 fs_.Create(
"foo.c",
"");
977 fs_.Create(
"otherfile",
"");
978 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
999 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1004 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1007 fs_.Create(
"blah.h",
"");
1008 fs_.Create(
"bar.h",
"");
1009 command_runner_.commands_ran_.clear();
1014 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1019 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1022 fs_.Create(
"otherfile",
"");
1023 command_runner_.commands_ran_.clear();
1030 fs_.RemoveFile(
"bar.h");
1031 command_runner_.commands_ran_.clear();
1036 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1042 "rule cc\n command = cc $in\n" 1043 "rule true\n command = true\n" 1044 "build oo.h: cc oo.h.in\n" 1045 "build foo.o: cc foo.c || oo.h\n"));
1047 fs_.Create(
"foo.c",
"");
1048 fs_.Create(
"oo.h.in",
"");
1054 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1057 command_runner_.commands_ran_.clear();
1064 fs_.RemoveFile(
"oo.h");
1065 command_runner_.commands_ran_.clear();
1070 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1071 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1076 fs_.Create(
"oo.h.in",
"");
1077 command_runner_.commands_ran_.clear();
1082 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1083 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1089 int orig_edges = state_.edges_.size();
1091 "rule cc\n command = cc $in\n depfile = $out.d\n" 1092 "build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
1093 Edge* edge = state_.edges_.back();
1095 fs_.Create(
"x/y/z/foo.c",
"");
1096 GetNode(
"bar.h")->MarkDirty();
1098 fs_.Create(
"gen/stuff\\things/foo.o.d",
1099 "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
1100 EXPECT_TRUE(builder_.AddTarget(
"gen/stuff/things/foo.o", &err));
1104 EXPECT_EQ(
"gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
1108 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
1121 "build out: cat bar.cc\n" 1122 "build all: phony out\n"));
1123 fs_.Create(
"bar.cc",
"");
1132 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1138 "build out: cat bar.cc\n" 1139 "build all: phony out\n"));
1140 fs_.Create(
"bar.cc",
"");
1141 fs_.Create(
"out",
"");
1154 "build a: phony a\n"));
1165 "build out1: fail\n"));
1172 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1180 "build out1: fail\n" 1181 "build out2: fail\n" 1182 "build out3: fail\n" 1183 "build all: phony out1 out2 out3\n"));
1186 config_.failures_allowed = 3;
1193 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1201 "build out1: fail\n" 1202 "build out2: fail\n" 1203 "build out3: fail\n" 1204 "build final: cat out1 out2 out3\n"));
1207 config_.failures_allowed = 11;
1214 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1215 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1224 " pool = failpool\n" 1225 "build out1: fail\n" 1226 "build out2: fail\n" 1227 "build out3: fail\n" 1228 "build final: cat out1 out2 out3\n"));
1231 config_.failures_allowed = 11;
1238 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1239 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1243 fs_.Create(
"x",
"");
1245 const char* manifest =
1249 " command = touch $out\n" 1250 " pool = some_pool\n" 1252 " command = touch grit\n" 1254 "build B.d.stamp: cc | x\n" 1255 "build C.stamp: touch B.d.stamp\n" 1256 "build final.stamp: touch || C.stamp\n";
1258 RebuildTarget(
"final.stamp", manifest);
1260 fs_.RemoveFile(
"B.d.stamp");
1263 RebuildTarget(
"final.stamp", manifest, NULL, NULL, &save_state);
1269 builder_.SetBuildLog(&build_log_);
1279 "build out1: cc in\n"));
1283 fs_.Create(
"in",
"");
1284 fs_.Create(
"out1",
"");
1292 command_runner_.commands_ran_.clear();
1302 "rule touch-fail-tick2\n" 1303 " command = touch-fail-tick2\n" 1304 "build out1: touch-fail-tick2 in\n"));
1308 fs_.Create(
"in",
"");
1314 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1316 command_runner_.commands_ran_.clear();
1319 builder_.plan_.Reset();
1322 fs_.Create(
"in",
"");
1328 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1330 command_runner_.commands_ran_.clear();
1333 builder_.plan_.Reset();
1341 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1348 " command = touch\n" 1349 "build out1: touch\n" 1350 "build out2: touch in\n"));
1354 fs_.Create(
"in",
"");
1360 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
1362 command_runner_.commands_ran_.clear();
1367 fs_.Create(
"in",
"");
1373 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1384 "build out1: cc in\n" 1385 "build out2: true out1\n" 1386 "build out3: cat out2\n"));
1388 fs_.Create(
"out1",
"");
1389 fs_.Create(
"out2",
"");
1390 fs_.Create(
"out3",
"");
1394 fs_.Create(
"in",
"");
1404 EXPECT_EQ(
"[3/3]", builder_.status_->FormatProgressStatus(
"[%s/%t]",
1406 command_runner_.commands_ran_.clear();
1411 fs_.Create(
"in",
"");
1417 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1421 command_runner_.commands_ran_.clear();
1429 fs_.Create(
"in",
"");
1433 command_runner_.commands_ran_.clear();
1438 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1452 "build out1: true in\n" 1453 "build out2: cc out1\n"));
1455 fs_.Create(
"in",
"");
1456 fs_.Create(
"out2",
"");
1466 command_runner_.commands_ran_.clear();
1470 fs_.Create(
"in",
"");
1471 fs_.Create(
"out2",
"");
1479 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1488 " command = touch\n" 1489 "build out1: true in\n" 1490 "build out2 out3: touch out1\n" 1491 "build out4: touch out2\n" 1495 fs_.Create(
"in",
"");
1502 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1505 fs_.Create(
"in",
"");
1506 fs_.RemoveFile(
"out3");
1513 command_runner_.commands_ran_.clear();
1519 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1528 " depfile = $out.d\n" 1532 "build out1: true in\n" 1533 "build out2: cc out1\n"));
1536 fs_.Create(
"in",
"");
1541 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1542 fs_.Create(
"will.be.deleted",
"");
1543 fs_.Create(
"restat.file",
"");
1550 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1556 ASSERT_EQ(restat_mtime, log_entry->mtime);
1560 fs_.RemoveFile(
"will.be.deleted");
1563 command_runner_.commands_ran_.clear();
1568 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1571 log_entry = build_log_.LookupByOutput(
"out1");
1573 ASSERT_EQ(restat_mtime, log_entry->mtime);
1578 config_.dry_run =
true;
1590 "build out1: cc in\n" 1591 "build out2: true out1\n" 1592 "build out3: cat out2\n"));
1594 fs_.Create(
"out1",
"");
1595 fs_.Create(
"out2",
"");
1596 fs_.Create(
"out3",
"");
1600 fs_.Create(
"in",
"");
1608 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1617 " command = cat $rspfile > $out\n" 1618 " rspfile = $rspfile\n" 1619 " rspfile_content = $long_command\n" 1620 "rule cat_rsp_out\n" 1621 " command = cat $rspfile > $out\n" 1622 " rspfile = $out.rsp\n" 1623 " rspfile_content = $long_command\n" 1624 "build out1: cat in\n" 1625 "build out2: cat_rsp in\n" 1626 " rspfile = out 2.rsp\n" 1627 " long_command = Some very long command\n" 1628 "build out$ 3: cat_rsp_out in\n" 1629 " long_command = Some very long command\n"));
1631 fs_.Create(
"out1",
"");
1632 fs_.Create(
"out2",
"");
1633 fs_.Create(
"out 3",
"");
1637 fs_.Create(
"in",
"");
1647 size_t files_created = fs_.files_created_.size();
1648 size_t files_removed = fs_.files_removed_.size();
1651 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1654 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1655 ASSERT_EQ(1u, fs_.files_created_.count(
"out 2.rsp"));
1656 ASSERT_EQ(1u, fs_.files_created_.count(
"out 3.rsp"));
1659 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1660 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 2.rsp"));
1661 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 3.rsp"));
1669 " rspfile = $rspfile\n" 1670 " rspfile_content = $long_command\n" 1671 "build out: fail in\n" 1672 " rspfile = out.rsp\n" 1673 " long_command = Another very long command\n"));
1675 fs_.Create(
"out",
"");
1677 fs_.Create(
"in",
"");
1683 size_t files_created = fs_.files_created_.size();
1684 size_t files_removed = fs_.files_removed_.size();
1688 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1691 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1692 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
1695 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1696 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
1699 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
1707 " command = cat $rspfile > $out\n" 1708 " rspfile = $rspfile\n" 1709 " rspfile_content = $long_command\n" 1710 "build out: cat_rsp in\n" 1711 " rspfile = out.rsp\n" 1712 " long_command = Original very long command\n"));
1714 fs_.Create(
"out",
"");
1716 fs_.Create(
"in",
"");
1724 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1727 command_runner_.commands_ran_.clear();
1738 "cat out.rsp > out;rspfile=Original very long command",
1739 log_entry->command_hash));
1740 log_entry->command_hash++;
1742 command_runner_.commands_ran_.clear();
1747 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1753 " command = interrupt\n" 1754 "rule touch-interrupt\n" 1755 " command = touch-interrupt\n" 1756 "build out1: interrupt in1\n" 1757 "build out2: touch-interrupt in2\n"));
1759 fs_.Create(
"out1",
"");
1760 fs_.Create(
"out2",
"");
1762 fs_.Create(
"in1",
"");
1763 fs_.Create(
"in2",
"");
1785 const string kTooLongToStat(400,
'i');
1787 (
"build " + kTooLongToStat +
": cat in\n").c_str()));
1788 fs_.Create(
"in",
"");
1791 fs_.files_[kTooLongToStat].mtime = -1;
1792 fs_.files_[kTooLongToStat].stat_error =
"stat failed";
1795 EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
1801 "build nonexistent: phony\n" 1802 "build out1: cat || nonexistent\n" 1803 "build out2: cat nonexistent\n"));
1804 fs_.Create(
"out1",
"");
1805 fs_.Create(
"out2",
"");
1816 command_runner_.commands_ran_.clear();
1822 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1830 "build out: cc\n"));
1840 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1844 status_.BuildStarted();
1847 status_.FormatProgressStatus(
"[%%/e%e]",
1853 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]",
1859 "build bad_deps.o: cat in1\n" 1861 " depfile = in1.d\n"));
1864 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
1869 fs_.Create(
"in1.d",
"AAA BBB");
1886 temp_dir_.CreateAndEnter(
"BuildWithQueryDepsLogTest");
1889 ASSERT_TRUE(log_.OpenForWrite(
"ninja_deps", &err));
1901 "rule cp_multi_msvc\n" 1902 " command = echo 'using $in' && for file in $out; do cp $in $$file; done\n" 1904 " msvc_deps_prefix = using \n" 1905 "build out1 out2: cp_multi_msvc in1\n"));
1912 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1913 EXPECT_EQ(
"echo 'using in1' && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
1915 Node* out1_node = state_.LookupNode(
"out1");
1920 Node* out2_node = state_.LookupNode(
"out2");
1929 "rule cp_multi_gcc\n" 1930 " command = echo '$out: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 1933 "build out1 out2: cp_multi_gcc in1 in2\n"));
1938 fs_.Create(
"in.d",
"out1 out2: in1 in2");
1941 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1942 EXPECT_EQ(
"echo 'out1 out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
1944 Node* out1_node = state_.LookupNode(
"out1");
1950 Node* out2_node = state_.LookupNode(
"out2");
1960 "rule cp_multi_gcc\n" 1961 " command = echo '$out: in1\\n$out: in2' > in.d && for file in $out; do cp in1 $$file; done\n" 1964 "build out1 out2: cp_multi_gcc in1 in2\n"));
1969 fs_.Create(
"in.d",
"out1 out2: in1\nout1 out2: in2");
1972 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1973 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]);
1975 Node* out1_node = state_.LookupNode(
"out1");
1981 Node* out2_node = state_.LookupNode(
"out2");
1991 "rule cp_multi_gcc\n" 1992 " command = echo 'out1: $in\\nout2: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 1995 "build out1 out2: cp_multi_gcc in1 in2\n"));
2000 fs_.Create(
"in.d",
"out1: in1 in2\nout2: in1 in2");
2003 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2004 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]);
2006 Node* out1_node = state_.LookupNode(
"out1");
2012 Node* out2_node = state_.LookupNode(
"out2");
2022 "rule cp_multi_gcc\n" 2023 " command = echo 'out1: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2026 "build out1 out2: cp_multi_gcc in1 in2\n"));
2031 fs_.Create(
"in.d",
"out1: in1 in2");
2034 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2035 EXPECT_EQ(
"echo 'out1: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2037 Node* out1_node = state_.LookupNode(
"out1");
2043 Node* out2_node = state_.LookupNode(
"out2");
2055 "rule cp_multi_gcc\n" 2056 " command = echo 'out2: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2059 "build out1 out2: cp_multi_gcc in1 in2\n"));
2064 fs_.Create(
"in.d",
"out2: in1 in2");
2067 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2068 EXPECT_EQ(
"echo 'out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2070 Node* out1_node = state_.LookupNode(
"out1");
2076 Node* out2_node = state_.LookupNode(
"out2");
2093 temp_dir_.CreateAndEnter(
"BuildWithDepsLogTest");
2097 temp_dir_.Cleanup();
2110 const char* manifest =
2111 "build out: cat in1\n" 2113 " depfile = in1.d\n";
2124 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2128 fs_.Create(
"in1.d",
"out: in2");
2135 fs_.Create(
"in1.d",
"out: in2");
2147 fs_.Create(
"in2",
"");
2154 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2155 builder.command_runner_.reset(&command_runner_);
2156 command_runner_.commands_ran_.clear();
2164 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2166 builder.command_runner_.release();
2177 const char* manifest =
2178 "build out: cat in1\n" 2180 " depfile = in1.d\n";
2183 fs_.Create(
"in1",
"");
2184 fs_.Create(
"in1.d",
"out: ");
2195 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2209 fs_.Create(
"in1",
"");
2210 fs_.Create(
"out",
"");
2224 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2225 builder.command_runner_.reset(&command_runner_);
2226 command_runner_.commands_ran_.clear();
2231 fs_.Create(
"in1.d",
"out: ");
2238 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2240 builder.command_runner_.release();
2245 const char* manifest =
2246 "build out: cat in1\n" 2248 " depfile = in1.d\n";
2250 fs_.Create(
"out",
"");
2252 fs_.Create(
"in1",
"");
2259 config_.dry_run =
true;
2260 Builder builder(&state, config_, NULL, NULL, &fs_);
2262 command_runner_.commands_ran_.clear();
2268 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2279 "build header.h: true header.in\n" 2280 "build out: cat in1\n" 2281 " depfile = in1.d\n"));
2283 fs_.Create(
"header.h",
"");
2284 fs_.Create(
"in1.d",
"out: header.h");
2286 fs_.Create(
"header.in",
"");
2300 const char* manifest =
2304 "build header.h: true header.in\n" 2305 "build out: cat in1\n" 2307 " depfile = in1.d\n";
2318 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2322 fs_.Create(
"in1.d",
"out: header.h");
2337 fs_.Create(
"header.in",
"");
2344 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2345 builder.command_runner_.reset(&command_runner_);
2346 command_runner_.commands_ran_.clear();
2354 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2356 builder.command_runner_.release();
2362 const char* manifest =
2363 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n" 2364 "build fo$ o.o: cc foo.c\n";
2366 fs_.Create(
"foo.c",
"");
2377 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2381 fs_.Create(
"fo o.o.d",
"fo\\ o.o: blah.h bar.h\n");
2398 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2424 const char* manifest =
2425 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n" 2426 "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
2428 fs_.Create(
"x/y/z/foo.c",
"");
2439 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2440 builder.command_runner_.reset(&command_runner_);
2441 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
2444 fs_.Create(
"a/b\\c\\d/e/fo o.o.d",
2445 "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
2450 builder.command_runner_.release();
2462 Builder builder(&state, config_, NULL, &deps_log, &fs_);
2463 builder.command_runner_.reset(&command_runner_);
2468 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
2482 builder.command_runner_.release();
2490 const char* manifest =
2494 "build header.h: true header.in\n" 2495 "build out: cat header.h\n" 2496 " depfile = out.d\n";
2498 fs_.Create(
"header.h",
"");
2500 fs_.Create(
"out",
"");
2501 fs_.Create(
"header.in",
"");
2507 RebuildTarget(
"out", manifest);
2508 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2515 const char* manifest =
2519 "build header.h: true header.in\n" 2520 "build out: cat header.h\n" 2522 " depfile = out.d\n";
2525 fs_.Create(
"header.in",
"");
2526 fs_.Create(
"out.d",
"out: header.h");
2527 fs_.Create(
"header.h",
"");
2529 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
2530 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2533 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
2534 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2540 fs_.Create(
"header.in",
"");
2543 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2544 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2547 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2548 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2553 fs_.Create(
"header.in",
"");
2554 fs_.Create(
"out",
"");
2555 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2556 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2559 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2560 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2565 const char* manifest =
2567 " command = cc $in\n" 2568 " depfile = $out.d\n" 2569 "build foo.o: cc foo.c\n";
2571 fs_.Create(
"foo.c",
"");
2572 fs_.Create(
"foo.o",
"");
2573 fs_.Create(
"header.h",
"");
2574 fs_.Create(
"foo.o.d",
"bar.o.d: header.h\n");
2576 RebuildTarget(
"foo.o", manifest,
"build_log",
"ninja_deps");
2577 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2583 " command = console\n" 2585 "build cons: console in.txt\n"));
2587 fs_.Create(
"in.txt",
"");
2594 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2602 " command = touch $out\n" 2603 "build out: touch || dd\n" 2609 EXPECT_EQ(
"loading 'dd': No such file or directory", err);
2618 " command = touch $out $out.imp\n" 2619 "build tmp: touch || dd\n" 2621 "build out: touch || dd\n" 2625 "ninja_dyndep_version = 1\n" 2626 "build out | out.imp: dyndep | tmp.imp\n" 2627 "build tmp | tmp.imp: dyndep\n" 2635 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2636 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[0]);
2637 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
2645 " command = touch $out\n" 2646 "build out: touch || dd\n" 2650 "build out: dyndep\n" 2655 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
2663 " command = unused\n" 2664 "build out: r in || dd\n" 2666 "build in: r circ\n" 2669 "ninja_dyndep_version = 1\n" 2670 "build out | circ: dyndep\n" 2672 fs_.Create(
"out",
"");
2676 EXPECT_EQ(
"dependency cycle: circ -> in -> circ", err);
2683 " command = touch $out\n" 2685 " command = cp $in $out\n" 2686 "build dd: cp dd-in\n" 2687 "build out: touch || dd\n" 2691 "ninja_dyndep_version = 1\n" 2692 "build out: dyndep\n" 2699 size_t files_created = fs_.files_created_.size();
2703 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2704 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2705 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[1]);
2709 ASSERT_EQ(2u + files_created, fs_.files_created_.size());
2710 EXPECT_EQ(1u, fs_.files_created_.count(
"dd"));
2711 EXPECT_EQ(1u, fs_.files_created_.count(
"out"));
2719 " command = touch $out\n" 2721 " command = cp $in $out\n" 2722 "build dd: cp dd-in\n" 2723 "build out: touch || dd\n" 2727 "build out: dyndep\n" 2735 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
2743 " command = touch $out\n" 2745 " command = cp $in $out\n" 2746 "build dd: cp dd-in\n" 2747 "build unrelated: touch || dd\n" 2748 "build out: touch unrelated || dd\n" 2752 "ninja_dyndep_version = 1\n" 2753 "build out: dyndep\n" 2756 fs_.Create(
"out",
"");
2764 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2765 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2766 EXPECT_EQ(
"touch unrelated", command_runner_.commands_ran_[1]);
2767 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
2775 " command = touch $out $out.imp\n" 2777 " command = cp $in $out\n" 2778 "build dd: cp dd-in\n" 2779 "build out: touch in || dd\n" 2782 fs_.Create(
"in",
"");
2784 "ninja_dyndep_version = 1\n" 2785 "build out | out.imp: dyndep\n" 2788 fs_.Create(
"out",
"");
2796 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2797 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2798 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
2806 " command = touch $out $out.imp\n" 2808 " command = cp $in $out\n" 2809 "build dd: cp dd-in\n" 2810 "build out1 | out-twice.imp: touch in\n" 2811 "build out2: touch in || dd\n" 2814 fs_.Create(
"in",
"");
2816 "ninja_dyndep_version = 1\n" 2817 "build out2 | out-twice.imp: dyndep\n" 2820 fs_.Create(
"out1",
"");
2821 fs_.Create(
"out2",
"");
2829 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
2838 " command = touch $out $out.imp\n" 2840 " command = cp $in $out\n" 2841 "build dd1: cp dd1-in\n" 2842 "build out1: touch || dd1\n" 2844 "build dd2: cp dd2-in || dd1\n" 2845 "build out2: touch || dd2\n" 2848 fs_.Create(
"out1",
"");
2849 fs_.Create(
"out2",
"");
2850 fs_.Create(
"dd1-in",
2851 "ninja_dyndep_version = 1\n" 2852 "build out1 | out-twice.imp: dyndep\n" 2854 fs_.Create(
"dd2-in",
"");
2856 "ninja_dyndep_version = 1\n" 2857 "build out2 | out-twice.imp: dyndep\n" 2860 fs_.Create(
"out1",
"");
2861 fs_.Create(
"out2",
"");
2869 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
2877 " command = touch $out\n" 2879 " command = cp $in $out\n" 2880 "build dd: cp dd-in\n" 2882 "build out: touch || dd\n" 2886 "ninja_dyndep_version = 1\n" 2887 "build out: dyndep | in\n" 2890 fs_.Create(
"out",
"");
2898 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2899 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2900 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
2901 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
2910 " command = touch $out $out.imp\n" 2912 " command = cp $in $out\n" 2913 "build dd: cp dd-in\n" 2914 "build tmp: touch || dd\n" 2916 "build out: touch || dd\n" 2920 "ninja_dyndep_version = 1\n" 2921 "build out | out.imp: dyndep | tmp.imp\n" 2922 "build tmp | tmp.imp: dyndep\n" 2930 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2931 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2932 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
2933 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
2941 " command = touch $out $out.imp\n" 2943 " command = cp $in $out\n" 2944 "build dd: cp dd-in\n" 2945 "build tmp: touch || dd\n" 2947 "build out: touch tmp || dd\n" 2950 fs_.Create(
"tmp",
"");
2951 fs_.Create(
"out",
"");
2953 "ninja_dyndep_version = 1\n" 2954 "build out: dyndep\n" 2955 "build tmp | tmp.imp: dyndep\n" 2963 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2964 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2965 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
2966 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
2974 " command = touch $out $out.imp\n" 2976 " command = cp $in $out\n" 2977 "build dd: cp dd-in\n" 2978 "build tmp: touch || dd\n" 2980 "build out: touch tmp\n" 2982 fs_.Create(
"tmp",
"");
2983 fs_.Create(
"out",
"");
2985 "ninja_dyndep_version = 1\n" 2986 "build tmp | tmp.imp: dyndep\n" 2994 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2995 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
2996 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
2997 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3005 " command = unused\n" 3007 " command = cp $in $out\n" 3008 "build dd: cp dd-in\n" 3009 "build out: r in || dd\n" 3010 " depfile = out.d\n" 3012 "build in: r || dd\n" 3015 fs_.Create(
"out.d",
"out: inimp\n");
3017 "ninja_dyndep_version = 1\n" 3018 "build out | circ: dyndep\n" 3019 "build in: dyndep | circ\n" 3021 fs_.Create(
"out",
"");
3030 EXPECT_TRUE(err ==
"dependency cycle: circ -> in -> circ" ||
3031 err ==
"dependency cycle: in -> circ -> in");
3041 " command = cp $in $out\n" 3042 "build dd: cp dd-in\n" 3043 "build out1: true in || dd\n" 3045 "build out2: cat out1\n"));
3047 fs_.Create(
"out1",
"");
3048 fs_.Create(
"out2",
"");
3050 "ninja_dyndep_version = 1\n" 3051 "build out1: dyndep\n" 3055 fs_.Create(
"in",
"");
3065 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3066 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3067 EXPECT_EQ(
"true", command_runner_.commands_ran_[1]);
3068 EXPECT_EQ(
"cat out1 > out2", command_runner_.commands_ran_[2]);
3070 command_runner_.commands_ran_.clear();
3073 fs_.Create(
"in",
"");
3080 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3081 EXPECT_EQ(
"true", command_runner_.commands_ran_[0]);
3090 " command = touch $out $out.imp\n" 3092 " command = cp $in $out\n" 3093 "build out1 | out1.imp: touch\n" 3094 "build zdd: cp zdd-in\n" 3095 " verify_active_edge = out1\n" 3096 "build out2: cp out1 || zdd\n" 3099 fs_.Create(
"zdd-in",
3100 "ninja_dyndep_version = 1\n" 3101 "build out2: dyndep | out1.imp\n" 3106 command_runner_.max_active_edges_ = 2;
3122 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3125 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"touch out1 out1.imp" &&
3126 command_runner_.commands_ran_[1] ==
"cp zdd-in zdd") ||
3127 (command_runner_.commands_ran_[1] ==
"touch out1 out1.imp" &&
3128 command_runner_.commands_ran_[0] ==
"cp zdd-in zdd"));
3129 EXPECT_EQ(
"cp out1 out2", command_runner_.commands_ran_[2]);
3137 " command = touch $out $out.imp\n" 3139 " command = cp $in $out\n" 3140 "build dd1: cp dd1-in\n" 3141 "build out1 | out1.imp: touch || dd1\n" 3143 "build dd2: cp dd2-in || dd1\n" 3144 "build out2: touch || dd2\n" 3147 fs_.Create(
"out1.imp",
"");
3148 fs_.Create(
"out2",
"");
3149 fs_.Create(
"out2.imp",
"");
3150 fs_.Create(
"dd1-in",
3151 "ninja_dyndep_version = 1\n" 3152 "build out1: dyndep\n" 3154 fs_.Create(
"dd2-in",
"");
3156 "ninja_dyndep_version = 1\n" 3157 "build out2 | out2.imp: dyndep | out1.imp\n" 3173 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3174 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3175 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
3176 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
3185 " command = touch $out $out.imp\n" 3187 " command = cp $in $out\n" 3188 "build dd1: cp dd1-in\n" 3189 "build out1: touch || dd1\n" 3191 "build dd2: cp dd2-in || out1\n" 3192 "build out2: touch || dd2\n" 3195 fs_.Create(
"out1.imp",
"");
3196 fs_.Create(
"out2",
"");
3197 fs_.Create(
"out2.imp",
"");
3198 fs_.Create(
"dd1-in",
3199 "ninja_dyndep_version = 1\n" 3200 "build out1 | out1.imp: dyndep\n" 3202 fs_.Create(
"dd2-in",
"");
3204 "ninja_dyndep_version = 1\n" 3205 "build out2 | out2.imp: dyndep | out1.imp\n" 3218 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3219 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3220 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
3221 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
3229 " command = touch $out\n" 3231 " command = cp $in $out\n" 3232 "build dd0: cp dd0-in\n" 3233 "build dd1: cp dd1-in\n" 3235 "build tmp: touch || dd0\n" 3237 "build out: touch || dd1\n" 3240 fs_.Create(
"dd1-in",
3241 "ninja_dyndep_version = 1\n" 3242 "build out: dyndep | tmp\n" 3244 fs_.Create(
"dd0-in",
"");
3246 "ninja_dyndep_version = 1\n" 3247 "build tmp: dyndep | in\n" 3250 fs_.Create(
"out",
"");
3258 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3259 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3260 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3261 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[2]);
3262 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[3]);
3270 " command = touch $out\n" 3272 " command = cp $in $out\n" 3273 "build dd0: cp dd0-in\n" 3274 "build dd1: cp dd1-in\n" 3276 "build tmp: touch || dd0\n" 3278 "build out: touch || dd1\n" 3281 fs_.Create(
"dd1-in",
3282 "ninja_dyndep_version = 1\n" 3283 "build out: dyndep | tmp\n" 3285 fs_.Create(
"dd0-in",
3286 "ninja_dyndep_version = 1\n" 3287 "build tmp: dyndep | in\n" 3290 fs_.Create(
"out",
"");
3298 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
3299 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3300 EXPECT_EQ(
"cp dd0-in dd0", command_runner_.commands_ran_[1]);
3301 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[2]);
3302 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[3]);
3303 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[4]);
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...
FakeCommandRunner command_runner_
bool Build(std::string *err)
Run the build.
An implementation of DiskInterface that uses an in-memory representation of disk state.
CommandRunner is an interface that wraps running the build subcommands.
std::auto_ptr< CommandRunner > command_runner_
LoadStatus Load(const std::string &path, std::string *err)
Load the on-disk log.
FakeCommandRunner(VirtualFileSystem *fs)
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
void TestPoolWithDepthOne(const char *test_case)
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute...
Node * GetNode(StringPiece path, uint64_t slash_bits)
void * builder_
Shadow parent class builder_ so we don't accidentally use it.
The result of waiting for a command.
StringPiece represents a slice of a string whose memory is managed externally.
const std::string & name() const
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
vector< Edge * > active_edges_
virtual bool IsPathDead(StringPiece s) const
Return if a given output is no longer part of the build manifest.
Fixture for tests involving Plan.
std::vector< Node * > outputs_
virtual vector< Edge * > GetActiveEdges()
An edge in the dependency graph; links between Nodes using Rules.
Store a log of every command ran for every build.
LoadStatus Load(const std::string &path, State *state, std::string *err)
A base test fixture that includes a State object with a builtin "cat" rule.
const std::string & path() const
As build commands run they can output extra dependency information (e.g.
Tests of builds involving deps logs necessarily must span multiple builds.
virtual bool WaitForCommand(Result *result)
Wait for a command to complete, or return false if interrupted.
void MarkMissing()
Mark the Node as already-stat()ed and missing.
Node * AddTarget(const std::string &name, std::string *err)
Fake implementation of CommandRunner, useful for tests.
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_).
Pool * LookupPool(const std::string &pool_name)
bool OpenForWrite(const std::string &path, std::string *err)
std::vector< Node * > inputs_
BuildWithQueryDepsLogTest()
void FindWorkSorted(deque< Edge *> *ret, int count)
Because FindWork does not return Edges in any sort of predictable order,.
static bool cmp(const Edge *a, const Edge *b)
Builder wraps the build process: starting commands, updating status.
virtual bool CanRunMore() const
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
~BuildWithQueryDepsLogTest()
Tracks the status of a build: completion fraction, printing updates.
virtual bool StartCommand(Edge *edge)
#define ASSERT_NO_FATAL_FAILURE(a)
const Rule & rule() const
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status) for a single run.
std::vector< Edge * > edges_
All the edges of the graph.
void Dirty(const string &path)
bool more_to_do() const
Returns true if there's more work to be done.
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
vector< string > commands_ran_
void AssertHash(const char *expected, uint64_t actual)
Can answer questions about the manifest for the BuildLog.