43 for (
int i = 0; i < count; ++i) {
53 void TestPoolWithDepthOne(
const char *test_case);
58 "build out: cat mid\n" 59 "build mid: cat in\n"));
60 GetNode(
"mid")->MarkDirty();
61 GetNode(
"out")->MarkDirty();
67 Edge* edge = plan_.FindWork();
69 ASSERT_EQ(
"in", edge->inputs_[0]->path());
70 ASSERT_EQ(
"mid", edge->outputs_[0]->path());
77 edge = plan_.FindWork();
79 ASSERT_EQ(
"mid", edge->inputs_[0]->path());
80 ASSERT_EQ(
"out", edge->outputs_[0]->path());
86 edge = plan_.FindWork();
93 "build out: cat mid1 mid2\n" 94 "build mid1 mid2: cat in\n"));
95 GetNode(
"mid1")->MarkDirty();
96 GetNode(
"mid2")->MarkDirty();
97 GetNode(
"out")->MarkDirty();
100 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
105 edge = plan_.FindWork();
110 edge = plan_.FindWork();
115 edge = plan_.FindWork();
122 "build out: cat b1 b2\n" 125 "build a1 a2: cat in\n"));
126 GetNode(
"a1")->MarkDirty();
127 GetNode(
"a2")->MarkDirty();
128 GetNode(
"b1")->MarkDirty();
129 GetNode(
"b2")->MarkDirty();
130 GetNode(
"out")->MarkDirty();
132 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
137 edge = plan_.FindWork();
142 edge = plan_.FindWork();
147 edge = plan_.FindWork();
152 edge = plan_.FindWork();
157 edge = plan_.FindWork();
164 "build out: cat a1 a2\n" 165 "build a1: cat mid\n" 166 "build a2: cat mid\n" 167 "build mid: cat in\n"));
168 GetNode(
"mid")->MarkDirty();
169 GetNode(
"a1")->MarkDirty();
170 GetNode(
"a2")->MarkDirty();
171 GetNode(
"out")->MarkDirty();
174 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
179 edge = plan_.FindWork();
184 edge = plan_.FindWork();
189 edge = plan_.FindWork();
194 edge = plan_.FindWork();
199 edge = plan_.FindWork();
205 GetNode(
"out1")->MarkDirty();
206 GetNode(
"out2")->MarkDirty();
208 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
210 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
214 Edge* edge = plan_.FindWork();
216 ASSERT_EQ(
"in", edge->inputs_[0]->path());
217 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
225 edge = plan_.FindWork();
227 ASSERT_EQ(
"in", edge->inputs_[0]->path());
228 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
236 edge = plan_.FindWork();
241 TestPoolWithDepthOne(
245 " command = cat $in > $out\n" 247 "build out1: poolcat in\n" 248 "build out2: poolcat in\n");
252 TestPoolWithDepthOne(
254 " command = cat $in > $out\n" 256 "build out1: poolcat in\n" 257 "build out2: poolcat in\n");
267 " command = cat $in > $out\n" 270 " command = cat $in > $out\n" 272 "build out1: foocat in\n" 273 "build out2: foocat in\n" 274 "build out3: foocat in\n" 275 "build outb1: bazcat in\n" 276 "build outb2: bazcat in\n" 277 "build outb3: bazcat in\n" 279 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n" 282 for (
int i = 0; i < 3; ++i) {
283 GetNode(
"out" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
284 GetNode(
"outb" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
286 GetNode(
"allTheThings")->MarkDirty();
289 EXPECT_TRUE(plan_.AddTarget(GetNode(
"allTheThings"), &err));
293 FindWorkSorted(&edges, 5);
295 for (
int i = 0; i < 4; ++i) {
296 Edge *edge = edges[i];
298 string base_name(i < 2 ?
"out" :
"outb");
303 Edge* edge = edges[4];
314 Edge* out3 = plan_.FindWork();
326 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
331 Edge* last = plan_.FindWork();
347 " command = touch foo.cpp\n" 349 " command = touch bar.cpp\n" 351 " command = echo $out > $out\n" 352 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n" 354 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n" 356 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n" 357 "build foo.cpp: gen_foo\n" 358 "build bar.cpp: gen_bar\n" 359 "build all: phony libfoo.a\n"));
360 GetNode(
"foo.cpp")->MarkDirty();
361 GetNode(
"foo.cpp.obj")->MarkDirty();
362 GetNode(
"bar.cpp")->MarkDirty();
363 GetNode(
"bar.cpp.obj")->MarkDirty();
364 GetNode(
"libfoo.a")->MarkDirty();
365 GetNode(
"all")->MarkDirty();
367 EXPECT_TRUE(plan_.AddTarget(GetNode(
"all"), &err));
373 deque<Edge*> initial_edges;
374 FindWorkSorted(&initial_edges, 2);
376 edge = initial_edges[1];
377 ASSERT_EQ(
"foo.cpp", edge->outputs_[0]->path());
381 edge = plan_.FindWork();
384 ASSERT_EQ(
"foo.cpp", edge->inputs_[0]->path());
385 ASSERT_EQ(
"foo.cpp", edge->inputs_[1]->path());
386 ASSERT_EQ(
"foo.cpp.obj", edge->outputs_[0]->path());
390 edge = initial_edges[0];
391 ASSERT_EQ(
"bar.cpp", edge->outputs_[0]->path());
395 edge = plan_.FindWork();
398 ASSERT_EQ(
"bar.cpp", edge->inputs_[0]->path());
399 ASSERT_EQ(
"bar.cpp", edge->inputs_[1]->path());
400 ASSERT_EQ(
"bar.cpp.obj", edge->outputs_[0]->path());
404 edge = plan_.FindWork();
407 ASSERT_EQ(
"foo.cpp.obj", edge->inputs_[0]->path());
408 ASSERT_EQ(
"bar.cpp.obj", edge->inputs_[1]->path());
409 ASSERT_EQ(
"libfoo.a", edge->outputs_[0]->path());
413 edge = plan_.FindWork();
416 ASSERT_EQ(
"libfoo.a", edge->inputs_[0]->path());
417 ASSERT_EQ(
"all", edge->outputs_[0]->path());
421 edge = plan_.FindWork();
431 " command = cat $in > $out\n" 433 "build out1: poolcat in\n" 434 "build out2: poolcat in\n"));
435 GetNode(
"out1")->MarkDirty();
436 GetNode(
"out2")->MarkDirty();
438 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
440 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
444 Edge* edge = plan_.FindWork();
446 ASSERT_EQ(
"in", edge->inputs_[0]->path());
447 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
455 edge = plan_.FindWork();
457 ASSERT_EQ(
"in", edge->inputs_[0]->path());
458 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
466 edge = plan_.FindWork();
473 max_active_edges_(1), fs_(fs) {}
476 virtual bool CanRunMore()
const;
477 virtual bool StartCommand(
Edge* edge);
478 virtual bool WaitForCommand(Result* result);
479 virtual vector<Edge*> GetActiveEdges();
480 virtual void Abort();
489 BuildTest() : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
490 builder_(&state_, config_, NULL, NULL, &fs_, &status_, 0) {
494 : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
495 builder_(&state_, config_, NULL, log, &fs_, &status_, 0) {}
500 builder_.command_runner_.reset(&command_runner_);
502 "build cat1: cat in1\n" 503 "build cat2: cat in1 in2\n" 504 "build cat12: cat cat1 cat2\n");
506 fs_.Create(
"in1",
"");
507 fs_.Create(
"in2",
"");
511 builder_.command_runner_.release();
519 void RebuildTarget(
const string& target,
const char* manifest,
520 const char* log_path = NULL,
const char* deps_path = NULL,
521 State* state = NULL);
524 void Dirty(
const string& path);
540 const char* log_path,
const char* deps_path,
542 State local_state, *pstate = &local_state;
549 BuildLog build_log, *pbuild_log = NULL;
554 pbuild_log = &build_log;
557 DepsLog deps_log, *pdeps_log = NULL;
562 pdeps_log = &deps_log;
565 Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_, &status_, 0);
568 command_runner_.commands_ran_.clear();
571 bool build_res = builder.
Build(&err);
578 return active_edges_.size() < max_active_edges_;
582 assert(active_edges_.size() < max_active_edges_);
583 assert(find(active_edges_.begin(), active_edges_.end(), edge)
584 == active_edges_.end());
588 edge->
rule().
name() ==
"cat_rsp_out" ||
590 edge->
rule().
name() ==
"cp_multi_msvc" ||
591 edge->
rule().
name() ==
"cp_multi_gcc" ||
593 edge->
rule().
name() ==
"touch-interrupt" ||
594 edge->
rule().
name() ==
"touch-fail-tick2") {
595 for (vector<Node*>::iterator out = edge->
outputs_.begin();
596 out != edge->
outputs_.end(); ++out) {
597 fs_->Create((*out)->path(),
"");
599 }
else if (edge->
rule().
name() ==
"true" ||
601 edge->
rule().
name() ==
"interrupt" ||
604 }
else if (edge->
rule().
name() ==
"cp") {
605 assert(!edge->
inputs_.empty());
609 if (fs_->ReadFile(edge->
inputs_[0]->path(), &content, &err) ==
611 fs_->WriteFile(edge->
outputs_[0]->path(), content);
612 }
else if (edge->
rule().
name() ==
"touch-implicit-dep-out") {
613 string dep = edge->
GetBinding(
"test_dependency");
614 fs_->Create(dep,
"");
616 for (vector<Node*>::iterator out = edge->
outputs_.begin();
617 out != edge->
outputs_.end(); ++out) {
618 fs_->Create((*out)->path(),
"");
620 }
else if (edge->
rule().
name() ==
"touch-out-implicit-dep") {
621 string dep = edge->
GetBinding(
"test_dependency");
622 for (vector<Node*>::iterator out = edge->
outputs_.begin();
623 out != edge->
outputs_.end(); ++out) {
624 fs_->Create((*out)->path(),
"");
627 fs_->Create(dep,
"");
628 }
else if (edge->
rule().
name() ==
"generate-depfile") {
629 string dep = edge->
GetBinding(
"test_dependency");
632 for (vector<Node*>::iterator out = edge->
outputs_.begin();
633 out != edge->
outputs_.end(); ++out) {
634 contents += (*out)->path() +
": " + dep +
"\n";
635 fs_->Create((*out)->path(),
"");
637 fs_->Create(depfile, contents);
639 printf(
"unknown command\n");
643 active_edges_.push_back(edge);
646 sort(active_edges_.begin(), active_edges_.end(),
653 if (active_edges_.empty())
659 vector<Edge*>::iterator edge_iter = active_edges_.end() - 1;
661 Edge* edge = *edge_iter;
664 if (edge->
rule().
name() ==
"interrupt" ||
665 edge->
rule().
name() ==
"touch-interrupt") {
670 if (edge->
rule().
name() ==
"console") {
675 active_edges_.erase(edge_iter);
679 if (edge->
rule().
name() ==
"cp_multi_msvc") {
680 const std::string prefix = edge->
GetBinding(
"msvc_deps_prefix");
681 for (std::vector<Node*>::iterator in = edge->
inputs_.begin();
682 in != edge->
inputs_.end(); ++in) {
683 result->
output += prefix + (*in)->path() +
'\n';
687 if (edge->
rule().
name() ==
"fail" ||
688 (edge->
rule().
name() ==
"touch-fail-tick2" && fs_->now_ == 2))
696 const string& verify_active_edge = edge->
GetBinding(
"verify_active_edge");
697 if (!verify_active_edge.empty()) {
698 bool verify_active_edge_found =
false;
699 for (vector<Edge*>::iterator i = active_edges_.begin();
700 i != active_edges_.end(); ++i) {
701 if (!(*i)->outputs_.empty() &&
702 (*i)->outputs_[0]->path() == verify_active_edge) {
703 verify_active_edge_found =
true;
709 active_edges_.erase(edge_iter);
714 return active_edges_;
718 active_edges_.clear();
722 Node* node = GetNode(path);
746 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
747 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
760 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
761 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
770 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
773 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
774 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
775 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
776 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
778 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
784 fs_.Create(
"in2",
"");
790 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
791 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
792 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
798 " command = touch $out\n" 799 "build out1 out2: touch in.txt\n"));
801 fs_.Create(
"in.txt",
"");
808 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
809 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
815 " command = touch $out $out.imp\n" 816 "build out | out.imp: touch in.txt\n"));
817 fs_.Create(
"in.txt",
"");
824 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
825 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[0]);
833 " command = touch $out\n" 834 "build in1 otherfile: touch in\n" 835 "build out: touch in | in1\n"));
837 fs_.Create(
"in",
"");
839 fs_.Create(
"in1",
"");
853 "build c5: cat c4\n"));
855 fs_.Create(
"c1",
"");
862 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
865 command_runner_.commands_ran_.clear();
873 fs_.Create(
"c3",
"");
875 command_runner_.commands_ran_.clear();
881 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
889 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
897 EXPECT_EQ(
"unknown target: 'meow'", err);
905 EXPECT_EQ(
"'in1' missing and no known rule to make it", err);
913 "build subdir\\dir2\\file: cat in1\n"));
916 "build subdir/dir2/file: cat in1\n"));
918 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
923 ASSERT_EQ(2u, fs_.directories_made_.size());
924 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
925 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
931 "rule cc\n command = cc $in\n depfile = $out.d\n" 932 "build fo$ o.o: cc foo.c\n"));
933 fs_.Create(
"foo.c",
"");
938 EXPECT_EQ(
"fo o.o.d", fs_.files_read_[0]);
943 int orig_edges = state_.edges_.size();
945 "rule cc\n command = cc $in\n depfile = $out.d\n" 946 "build foo.o: cc foo.c\n"));
947 Edge* edge = state_.edges_.back();
949 fs_.Create(
"foo.c",
"");
950 GetNode(
"bar.h")->MarkDirty();
951 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
955 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
959 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
970 "rule cc\n command = cc $in\n depfile = $out.d\n" 971 "build foo.o: cc foo.c\n"));
972 fs_.Create(
"foo.c",
"");
973 fs_.Create(
"foo.o.d",
"randomtext\n");
975 EXPECT_EQ(
"foo.o.d: expected ':' in depfile", err);
982 " command = touch $out\n" 984 "build b: touch || c\n" 985 "build a: touch | b || c\n"));
987 vector<Edge*> c_out = GetNode(
"c")->out_edges();
989 EXPECT_EQ(
"b", c_out[0]->outputs_[0]->path());
990 EXPECT_EQ(
"a", c_out[1]->outputs_[0]->path());
998 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1004 "rule cc\n command = cc $in\n depfile = $out.d\n" 1005 "build foo.o: cc foo.c || otherfile\n"));
1006 Edge* edge = state_.edges_.back();
1008 fs_.Create(
"foo.c",
"");
1009 fs_.Create(
"otherfile",
"");
1010 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1031 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1036 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1039 fs_.Create(
"blah.h",
"");
1040 fs_.Create(
"bar.h",
"");
1041 command_runner_.commands_ran_.clear();
1046 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1051 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1054 fs_.Create(
"otherfile",
"");
1055 command_runner_.commands_ran_.clear();
1062 fs_.RemoveFile(
"bar.h");
1063 command_runner_.commands_ran_.clear();
1068 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1074 "rule cc\n command = cc $in\n" 1075 "rule true\n command = true\n" 1076 "build oo.h: cc oo.h.in\n" 1077 "build foo.o: cc foo.c || oo.h\n"));
1079 fs_.Create(
"foo.c",
"");
1080 fs_.Create(
"oo.h.in",
"");
1086 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1089 command_runner_.commands_ran_.clear();
1096 fs_.RemoveFile(
"oo.h");
1097 command_runner_.commands_ran_.clear();
1102 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1103 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1108 fs_.Create(
"oo.h.in",
"");
1109 command_runner_.commands_ran_.clear();
1114 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1115 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1121 int orig_edges = state_.edges_.size();
1123 "rule cc\n command = cc $in\n depfile = $out.d\n" 1124 "build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
1125 Edge* edge = state_.edges_.back();
1127 fs_.Create(
"x/y/z/foo.c",
"");
1128 GetNode(
"bar.h")->MarkDirty();
1130 fs_.Create(
"gen/stuff\\things/foo.o.d",
1131 "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
1132 EXPECT_TRUE(builder_.AddTarget(
"gen/stuff/things/foo.o", &err));
1136 EXPECT_EQ(
"gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
1140 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
1153 "build out: cat bar.cc\n" 1154 "build all: phony out\n"));
1155 fs_.Create(
"bar.cc",
"");
1164 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1170 "build out: cat bar.cc\n" 1171 "build all: phony out\n"));
1172 fs_.Create(
"bar.cc",
"");
1173 fs_.Create(
"out",
"");
1186 "build a: phony a\n"));
1222 " command = touch $out\n" 1223 "build notreal: phony blank\n" 1224 "build phony1: phony notreal\n" 1225 "build phony2: phony\n" 1226 "build phony3: phony blank\n" 1227 "build phony4: phony notreal\n" 1228 "build phony5: phony\n" 1229 "build phony6: phony blank\n" 1231 "build test1: touch phony1\n" 1232 "build test2: touch phony2\n" 1233 "build test3: touch phony3\n" 1234 "build test4: touch phony4\n" 1235 "build test5: touch phony5\n" 1236 "build test6: touch phony6\n" 1260 ci +=
static_cast<char>(
'0' + i);
1263 if (i != 2 && i != 5) {
1343 "build out1: fail\n"));
1350 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1358 "build out1: fail\n" 1359 "build out2: fail\n" 1360 "build out3: fail\n" 1361 "build all: phony out1 out2 out3\n"));
1364 config_.failures_allowed = 3;
1371 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1379 "build out1: fail\n" 1380 "build out2: fail\n" 1381 "build out3: fail\n" 1382 "build final: cat out1 out2 out3\n"));
1385 config_.failures_allowed = 11;
1392 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1393 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1402 " pool = failpool\n" 1403 "build out1: fail\n" 1404 "build out2: fail\n" 1405 "build out3: fail\n" 1406 "build final: cat out1 out2 out3\n"));
1409 config_.failures_allowed = 11;
1416 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1417 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1421 fs_.Create(
"x",
"");
1423 const char* manifest =
1427 " command = touch $out\n" 1428 " pool = some_pool\n" 1430 " command = touch grit\n" 1432 "build B.d.stamp: cc | x\n" 1433 "build C.stamp: touch B.d.stamp\n" 1434 "build final.stamp: touch || C.stamp\n";
1436 RebuildTarget(
"final.stamp", manifest);
1438 fs_.RemoveFile(
"B.d.stamp");
1441 RebuildTarget(
"final.stamp", manifest, NULL, NULL, &save_state);
1447 builder_.SetBuildLog(&build_log_);
1456 " command = touch $out\n" 1458 "build out.imp: touch | in\n"));
1459 fs_.Create(
"out.imp",
"");
1461 fs_.Create(
"in",
"");
1473 "rule touch-implicit-dep-out\n" 1474 " command = touch $test_dependency ; sleep 1 ; touch $out\n" 1476 "build out.imp: touch-implicit-dep-out | inimp inimp2\n" 1477 " test_dependency = inimp\n"));
1478 fs_.Create(
"inimp",
"");
1479 fs_.Create(
"out.imp",
"");
1481 fs_.Create(
"inimp2",
"");
1492 command_runner_.commands_ran_.clear();
1495 builder_.plan_.Reset();
1506 "build out1: cc in\n"));
1510 fs_.Create(
"in",
"");
1511 fs_.Create(
"out1",
"");
1519 command_runner_.commands_ran_.clear();
1529 "rule touch-fail-tick2\n" 1530 " command = touch-fail-tick2\n" 1531 "build out1: touch-fail-tick2 in\n"));
1535 fs_.Create(
"in",
"");
1541 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1543 command_runner_.commands_ran_.clear();
1546 builder_.plan_.Reset();
1549 fs_.Create(
"in",
"");
1555 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1557 command_runner_.commands_ran_.clear();
1560 builder_.plan_.Reset();
1568 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1575 " command = touch\n" 1576 "build out1: touch\n" 1577 "build out2: touch in\n"));
1581 fs_.Create(
"in",
"");
1587 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
1589 command_runner_.commands_ran_.clear();
1594 fs_.Create(
"in",
"");
1600 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1611 "build out1: cc in\n" 1612 "build out2: true out1\n" 1613 "build out3: cat out2\n"));
1615 fs_.Create(
"out1",
"");
1616 fs_.Create(
"out2",
"");
1617 fs_.Create(
"out3",
"");
1621 fs_.Create(
"in",
"");
1631 EXPECT_EQ(3u, command_runner_.commands_ran_.size());
1632 EXPECT_EQ(3u, builder_.plan_.command_edge_count());
1633 command_runner_.commands_ran_.clear();
1638 fs_.Create(
"in",
"");
1644 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1648 command_runner_.commands_ran_.clear();
1656 fs_.Create(
"in",
"");
1660 command_runner_.commands_ran_.clear();
1665 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1679 "build out1: true in\n" 1680 "build out2: cc out1\n"));
1682 fs_.Create(
"in",
"");
1683 fs_.Create(
"out2",
"");
1693 command_runner_.commands_ran_.clear();
1697 fs_.Create(
"in",
"");
1698 fs_.Create(
"out2",
"");
1706 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1715 " command = touch\n" 1716 "build out1: true in\n" 1717 "build out2 out3: touch out1\n" 1718 "build out4: touch out2\n" 1722 fs_.Create(
"in",
"");
1729 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1732 fs_.Create(
"in",
"");
1733 fs_.RemoveFile(
"out3");
1740 command_runner_.commands_ran_.clear();
1746 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1755 " depfile = $out.d\n" 1759 "build out1: true in\n" 1760 "build out2: cc out1\n"));
1763 fs_.Create(
"in",
"");
1768 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1769 fs_.Create(
"will.be.deleted",
"");
1770 fs_.Create(
"restat.file",
"");
1777 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1783 ASSERT_EQ(restat_mtime, log_entry->mtime);
1787 fs_.RemoveFile(
"will.be.deleted");
1790 command_runner_.commands_ran_.clear();
1795 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1798 log_entry = build_log_.LookupByOutput(
"out1");
1800 ASSERT_EQ(restat_mtime, log_entry->mtime);
1805 "rule generate-depfile\n" 1806 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n" 1807 "build out: generate-depfile\n" 1808 " test_dependency = inimp\n" 1809 " depfile = out.d\n"));
1810 fs_.Create(
"inimp",
"");
1821 command_runner_.commands_ran_.clear();
1824 builder_.plan_.Reset();
1832 config_.dry_run =
true;
1844 "build out1: cc in\n" 1845 "build out2: true out1\n" 1846 "build out3: cat out2\n"));
1848 fs_.Create(
"out1",
"");
1849 fs_.Create(
"out2",
"");
1850 fs_.Create(
"out3",
"");
1854 fs_.Create(
"in",
"");
1862 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1871 " command = cat $rspfile > $out\n" 1872 " rspfile = $rspfile\n" 1873 " rspfile_content = $long_command\n" 1874 "rule cat_rsp_out\n" 1875 " command = cat $rspfile > $out\n" 1876 " rspfile = $out.rsp\n" 1877 " rspfile_content = $long_command\n" 1878 "build out1: cat in\n" 1879 "build out2: cat_rsp in\n" 1880 " rspfile = out 2.rsp\n" 1881 " long_command = Some very long command\n" 1882 "build out$ 3: cat_rsp_out in\n" 1883 " long_command = Some very long command\n"));
1885 fs_.Create(
"out1",
"");
1886 fs_.Create(
"out2",
"");
1887 fs_.Create(
"out 3",
"");
1891 fs_.Create(
"in",
"");
1901 size_t files_created = fs_.files_created_.size();
1902 size_t files_removed = fs_.files_removed_.size();
1905 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1908 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1909 ASSERT_EQ(1u, fs_.files_created_.count(
"out 2.rsp"));
1910 ASSERT_EQ(1u, fs_.files_created_.count(
"out 3.rsp"));
1913 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1914 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 2.rsp"));
1915 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 3.rsp"));
1923 " rspfile = $rspfile\n" 1924 " rspfile_content = $long_command\n" 1925 "build out: fail in\n" 1926 " rspfile = out.rsp\n" 1927 " long_command = Another very long command\n"));
1929 fs_.Create(
"out",
"");
1931 fs_.Create(
"in",
"");
1937 size_t files_created = fs_.files_created_.size();
1938 size_t files_removed = fs_.files_removed_.size();
1942 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1945 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1946 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
1949 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1950 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
1953 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
1961 " command = cat $rspfile > $out\n" 1962 " rspfile = $rspfile\n" 1963 " rspfile_content = $long_command\n" 1964 "build out: cat_rsp in\n" 1965 " rspfile = out.rsp\n" 1966 " long_command = Original very long command\n"));
1968 fs_.Create(
"out",
"");
1970 fs_.Create(
"in",
"");
1978 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1981 command_runner_.commands_ran_.clear();
1992 "cat out.rsp > out;rspfile=Original very long command",
1993 log_entry->command_hash));
1994 log_entry->command_hash++;
1996 command_runner_.commands_ran_.clear();
2001 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2007 " command = interrupt\n" 2008 "rule touch-interrupt\n" 2009 " command = touch-interrupt\n" 2010 "build out1: interrupt in1\n" 2011 "build out2: touch-interrupt in2\n"));
2013 fs_.Create(
"out1",
"");
2014 fs_.Create(
"out2",
"");
2016 fs_.Create(
"in1",
"");
2017 fs_.Create(
"in2",
"");
2039 const string kTooLongToStat(400,
'i');
2041 (
"build " + kTooLongToStat +
": cat in\n").c_str()));
2042 fs_.Create(
"in",
"");
2045 fs_.files_[kTooLongToStat].mtime = -1;
2046 fs_.files_[kTooLongToStat].stat_error =
"stat failed";
2049 EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
2055 "build nonexistent: phony\n" 2056 "build out1: cat || nonexistent\n" 2057 "build out2: cat nonexistent\n"));
2058 fs_.Create(
"out1",
"");
2059 fs_.Create(
"out2",
"");
2070 command_runner_.commands_ran_.clear();
2076 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2084 "build out: cc\n"));
2094 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2098 status_.BuildStarted();
2101 status_.FormatProgressStatus(
"[%%/e%e]", 0));
2106 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]", 0));
2111 "build bad_deps.o: cat in1\n" 2113 " depfile = in1.d\n"));
2116 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
2121 fs_.Create(
"in1.d",
"AAA BBB");
2138 temp_dir_.CreateAndEnter(
"BuildWithQueryDepsLogTest");
2141 ASSERT_TRUE(log_.OpenForWrite(
"ninja_deps", &err));
2153 "rule cp_multi_msvc\n" 2154 " command = echo 'using $in' && for file in $out; do cp $in $$file; done\n" 2156 " msvc_deps_prefix = using \n" 2157 "build out1 out2: cp_multi_msvc in1\n"));
2164 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2165 EXPECT_EQ(
"echo 'using in1' && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2167 Node* out1_node = state_.LookupNode(
"out1");
2172 Node* out2_node = state_.LookupNode(
"out2");
2181 "rule cp_multi_gcc\n" 2182 " command = echo '$out: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2185 "build out1 out2: cp_multi_gcc in1 in2\n"));
2190 fs_.Create(
"in.d",
"out1 out2: in1 in2");
2193 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2194 EXPECT_EQ(
"echo 'out1 out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2196 Node* out1_node = state_.LookupNode(
"out1");
2202 Node* out2_node = state_.LookupNode(
"out2");
2212 "rule cp_multi_gcc\n" 2213 " command = echo '$out: in1\\n$out: in2' > in.d && for file in $out; do cp in1 $$file; done\n" 2216 "build out1 out2: cp_multi_gcc in1 in2\n"));
2221 fs_.Create(
"in.d",
"out1 out2: in1\nout1 out2: in2");
2224 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2225 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]);
2227 Node* out1_node = state_.LookupNode(
"out1");
2233 Node* out2_node = state_.LookupNode(
"out2");
2243 "rule cp_multi_gcc\n" 2244 " command = echo 'out1: $in\\nout2: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2247 "build out1 out2: cp_multi_gcc in1 in2\n"));
2252 fs_.Create(
"in.d",
"out1: in1 in2\nout2: in1 in2");
2255 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2256 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]);
2258 Node* out1_node = state_.LookupNode(
"out1");
2264 Node* out2_node = state_.LookupNode(
"out2");
2274 "rule cp_multi_gcc\n" 2275 " command = echo 'out1: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2278 "build out1 out2: cp_multi_gcc in1 in2\n"));
2283 fs_.Create(
"in.d",
"out1: in1 in2");
2286 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2287 EXPECT_EQ(
"echo 'out1: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2289 Node* out1_node = state_.LookupNode(
"out1");
2295 Node* out2_node = state_.LookupNode(
"out2");
2307 "rule cp_multi_gcc\n" 2308 " command = echo 'out2: $in' > in.d && for file in $out; do cp in1 $$file; done\n" 2311 "build out1 out2: cp_multi_gcc in1 in2\n"));
2316 fs_.Create(
"in.d",
"out2: in1 in2");
2319 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2320 EXPECT_EQ(
"echo 'out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2322 Node* out1_node = state_.LookupNode(
"out1");
2328 Node* out2_node = state_.LookupNode(
"out2");
2345 temp_dir_.CreateAndEnter(
"BuildWithDepsLogTest");
2349 temp_dir_.Cleanup();
2362 const char* manifest =
2363 "build out: cat in1\n" 2365 " depfile = in1.d\n";
2376 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2380 fs_.Create(
"in1.d",
"out: in2");
2387 fs_.Create(
"in1.d",
"out: in2");
2399 fs_.Create(
"in2",
"");
2406 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2407 builder.command_runner_.reset(&command_runner_);
2408 command_runner_.commands_ran_.clear();
2416 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2418 builder.command_runner_.release();
2429 const char* manifest =
2430 "build out: cat in1\n" 2432 " depfile = in1.d\n";
2435 fs_.Create(
"in1",
"");
2436 fs_.Create(
"in1.d",
"out: ");
2447 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2461 fs_.Create(
"in1",
"");
2462 fs_.Create(
"out",
"");
2476 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2477 builder.command_runner_.reset(&command_runner_);
2478 command_runner_.commands_ran_.clear();
2483 fs_.Create(
"in1.d",
"out: ");
2490 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2492 builder.command_runner_.release();
2497 const char* manifest =
2498 "build out: cat in1\n" 2500 " depfile = in1.d\n";
2502 fs_.Create(
"out",
"");
2504 fs_.Create(
"in1",
"");
2511 config_.dry_run =
true;
2512 Builder builder(&state, config_, NULL, NULL, &fs_, &status_, 0);
2514 command_runner_.commands_ran_.clear();
2520 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2531 "build header.h: true header.in\n" 2532 "build out: cat in1\n" 2533 " depfile = in1.d\n"));
2535 fs_.Create(
"header.h",
"");
2536 fs_.Create(
"in1.d",
"out: header.h");
2538 fs_.Create(
"header.in",
"");
2552 const char* manifest =
2556 "build header.h: true header.in\n" 2557 "build out: cat in1\n" 2559 " depfile = in1.d\n";
2570 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2574 fs_.Create(
"in1.d",
"out: header.h");
2589 fs_.Create(
"header.in",
"");
2596 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2597 builder.command_runner_.reset(&command_runner_);
2598 command_runner_.commands_ran_.clear();
2606 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2608 builder.command_runner_.release();
2614 const char* manifest =
2615 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n" 2616 "build fo$ o.o: cc foo.c\n";
2618 fs_.Create(
"foo.c",
"");
2629 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2633 fs_.Create(
"fo o.o.d",
"fo\\ o.o: blah.h bar.h\n");
2650 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2675 const char* manifest =
2676 "rule touch-out-implicit-dep\n" 2677 " command = touch $out ; sleep 1 ; touch $test_dependency\n" 2678 "rule generate-depfile\n" 2679 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n" 2680 "build out1: touch-out-implicit-dep in1\n" 2681 " test_dependency = inimp\n" 2682 "build out2: generate-depfile in1 || out1\n" 2683 " test_dependency = inimp\n" 2684 " depfile = out2.d\n" 2687 fs_.Create(
"in1",
"");
2700 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2713 fs_.Create(
"in1",
"");
2724 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2747 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2760 const char* manifest =
2761 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n" 2762 "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
2764 fs_.Create(
"x/y/z/foo.c",
"");
2775 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2776 builder.command_runner_.reset(&command_runner_);
2777 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
2780 fs_.Create(
"a/b\\c\\d/e/fo o.o.d",
2781 "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
2786 builder.command_runner_.release();
2798 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2799 builder.command_runner_.reset(&command_runner_);
2804 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
2818 builder.command_runner_.release();
2826 const char* manifest =
2830 "build header.h: true header.in\n" 2831 "build out: cat header.h\n" 2832 " depfile = out.d\n";
2834 fs_.Create(
"header.h",
"");
2836 fs_.Create(
"out",
"");
2837 fs_.Create(
"header.in",
"");
2843 RebuildTarget(
"out", manifest);
2844 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2851 const char* manifest =
2855 "build header.h: true header.in\n" 2856 "build out: cat header.h\n" 2858 " depfile = out.d\n";
2861 fs_.Create(
"header.in",
"");
2862 fs_.Create(
"out.d",
"out: header.h");
2863 fs_.Create(
"header.h",
"");
2865 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
2866 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2869 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
2870 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2876 fs_.Create(
"header.in",
"");
2879 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2880 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2883 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2884 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2889 fs_.Create(
"header.in",
"");
2890 fs_.Create(
"out",
"");
2891 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2892 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2895 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
2896 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
2901 const char* manifest =
2903 " command = cc $in\n" 2904 " depfile = $out.d\n" 2905 "build foo.o: cc foo.c\n";
2907 fs_.Create(
"foo.c",
"");
2908 fs_.Create(
"foo.o",
"");
2909 fs_.Create(
"header.h",
"");
2910 fs_.Create(
"foo.o.d",
"bar.o.d: header.h\n");
2912 RebuildTarget(
"foo.o", manifest,
"build_log",
"ninja_deps");
2913 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2919 " command = console\n" 2921 "build cons: console in.txt\n"));
2923 fs_.Create(
"in.txt",
"");
2930 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2938 " command = touch $out\n" 2939 "build out: touch || dd\n" 2945 EXPECT_EQ(
"loading 'dd': No such file or directory", err);
2954 " command = touch $out $out.imp\n" 2955 "build tmp: touch || dd\n" 2957 "build out: touch || dd\n" 2961 "ninja_dyndep_version = 1\n" 2962 "build out | out.imp: dyndep | tmp.imp\n" 2963 "build tmp | tmp.imp: dyndep\n" 2971 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2972 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[0]);
2973 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
2981 " command = touch $out\n" 2982 "build out: touch || dd\n" 2986 "build out: dyndep\n" 2991 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
2999 " command = unused\n" 3000 "build out: r in || dd\n" 3002 "build in: r circ\n" 3005 "ninja_dyndep_version = 1\n" 3006 "build out | circ: dyndep\n" 3008 fs_.Create(
"out",
"");
3012 EXPECT_EQ(
"dependency cycle: circ -> in -> circ", err);
3019 " command = touch $out\n" 3021 " command = cp $in $out\n" 3022 "build dd: cp dd-in\n" 3023 "build out: touch || dd\n" 3027 "ninja_dyndep_version = 1\n" 3028 "build out: dyndep\n" 3035 size_t files_created = fs_.files_created_.size();
3039 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3040 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3041 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[1]);
3045 ASSERT_EQ(2u + files_created, fs_.files_created_.size());
3046 EXPECT_EQ(1u, fs_.files_created_.count(
"dd"));
3047 EXPECT_EQ(1u, fs_.files_created_.count(
"out"));
3055 " command = touch $out\n" 3057 " command = cp $in $out\n" 3058 "build dd: cp dd-in\n" 3059 "build out: touch || dd\n" 3063 "build out: dyndep\n" 3071 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
3079 " command = touch $out\n" 3081 " command = cp $in $out\n" 3082 "build dd: cp dd-in\n" 3083 "build unrelated: touch || dd\n" 3084 "build out: touch unrelated || dd\n" 3088 "ninja_dyndep_version = 1\n" 3089 "build out: dyndep\n" 3092 fs_.Create(
"out",
"");
3100 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3101 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3102 EXPECT_EQ(
"touch unrelated", command_runner_.commands_ran_[1]);
3103 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3111 " command = touch $out $out.imp\n" 3113 " command = cp $in $out\n" 3114 "build dd: cp dd-in\n" 3115 "build out: touch in || dd\n" 3118 fs_.Create(
"in",
"");
3120 "ninja_dyndep_version = 1\n" 3121 "build out | out.imp: dyndep\n" 3124 fs_.Create(
"out",
"");
3132 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3133 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3134 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
3142 " command = touch $out $out.imp\n" 3144 " command = cp $in $out\n" 3145 "build dd: cp dd-in\n" 3146 "build out1 | out-twice.imp: touch in\n" 3147 "build out2: touch in || dd\n" 3150 fs_.Create(
"in",
"");
3152 "ninja_dyndep_version = 1\n" 3153 "build out2 | out-twice.imp: dyndep\n" 3156 fs_.Create(
"out1",
"");
3157 fs_.Create(
"out2",
"");
3165 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
3174 " command = touch $out $out.imp\n" 3176 " command = cp $in $out\n" 3177 "build dd1: cp dd1-in\n" 3178 "build out1: touch || dd1\n" 3180 "build dd2: cp dd2-in || dd1\n" 3181 "build out2: touch || dd2\n" 3184 fs_.Create(
"out1",
"");
3185 fs_.Create(
"out2",
"");
3186 fs_.Create(
"dd1-in",
3187 "ninja_dyndep_version = 1\n" 3188 "build out1 | out-twice.imp: dyndep\n" 3190 fs_.Create(
"dd2-in",
"");
3192 "ninja_dyndep_version = 1\n" 3193 "build out2 | out-twice.imp: dyndep\n" 3196 fs_.Create(
"out1",
"");
3197 fs_.Create(
"out2",
"");
3205 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
3213 " command = touch $out\n" 3215 " command = cp $in $out\n" 3216 "build dd: cp dd-in\n" 3218 "build out: touch || dd\n" 3222 "ninja_dyndep_version = 1\n" 3223 "build out: dyndep | in\n" 3226 fs_.Create(
"out",
"");
3234 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3235 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3236 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3237 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3245 " command = touch $out\n" 3247 " command = cp $in $out\n" 3248 "build dd: cp dd-in\n" 3249 "build out: touch || dd\n" 3253 "ninja_dyndep_version = 1\n" 3254 "build out: dyndep |@ validation\n" 3263 string err_first_line = err.substr(0, err.find(
"\n"));
3264 EXPECT_EQ(
"dd:2: expected newline, got '|@'", err_first_line);
3272 " command = touch $out\n" 3274 " command = cp $in $out\n" 3275 "build dd: cp dd-in\n" 3276 "build in: touch |@ validation\n" 3277 "build validation: touch in out\n" 3278 "build out: touch || dd\n" 3282 "ninja_dyndep_version = 1\n" 3283 "build out: dyndep | in\n" 3286 fs_.Create(
"out",
"");
3294 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3295 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3296 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3297 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3298 EXPECT_EQ(
"touch validation", command_runner_.commands_ran_[3]);
3307 " command = touch $out $out.imp\n" 3309 " command = cp $in $out\n" 3310 "build dd: cp dd-in\n" 3311 "build tmp: touch || dd\n" 3313 "build out: touch || dd\n" 3317 "ninja_dyndep_version = 1\n" 3318 "build out | out.imp: dyndep | tmp.imp\n" 3319 "build tmp | tmp.imp: dyndep\n" 3327 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3328 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3329 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3330 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3339 " command = touch $out $out.imp\n" 3341 " command = cp $in $out\n" 3342 "build dd: cp dd-in\n" 3343 "build tmp: touch || dd\n" 3345 "build out: cp tmp\n" 3346 " depfile = out.d\n" 3348 fs_.Create(
"out.d",
"out: tmp.imp\n");
3350 "ninja_dyndep_version = 1\n" 3351 "build tmp | tmp.imp: dyndep\n" 3359 ASSERT_TRUE(GetNode(
"tmp.imp")->in_edge()->is_phony());
3365 ASSERT_FALSE(GetNode(
"tmp.imp")->in_edge()->is_phony());
3367 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3368 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3369 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3370 EXPECT_EQ(
"cp tmp out", command_runner_.commands_ran_[2]);
3371 EXPECT_EQ(1u, fs_.files_created_.count(
"tmp.imp"));
3380 " command = touch $out $out.imp\n" 3382 " command = cp $in $out\n" 3383 "build dd: cp dd-in\n" 3384 "build tmp: touch || dd\n" 3386 "build out: touch tmp || dd\n" 3389 fs_.Create(
"tmp",
"");
3390 fs_.Create(
"out",
"");
3392 "ninja_dyndep_version = 1\n" 3393 "build out: dyndep\n" 3394 "build tmp | tmp.imp: dyndep\n" 3402 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3403 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3404 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3405 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3413 " command = touch $out $out.imp\n" 3415 " command = cp $in $out\n" 3416 "build dd: cp dd-in\n" 3417 "build tmp: touch || dd\n" 3419 "build out: touch tmp\n" 3421 fs_.Create(
"tmp",
"");
3422 fs_.Create(
"out",
"");
3424 "ninja_dyndep_version = 1\n" 3425 "build tmp | tmp.imp: dyndep\n" 3433 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3434 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3435 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3436 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3444 " command = unused\n" 3446 " command = cp $in $out\n" 3447 "build dd: cp dd-in\n" 3448 "build out: r in || dd\n" 3449 " depfile = out.d\n" 3451 "build in: r || dd\n" 3454 fs_.Create(
"out.d",
"out: inimp\n");
3456 "ninja_dyndep_version = 1\n" 3457 "build out | circ: dyndep\n" 3458 "build in: dyndep | circ\n" 3460 fs_.Create(
"out",
"");
3469 EXPECT_TRUE(err ==
"dependency cycle: circ -> in -> circ" ||
3470 err ==
"dependency cycle: in -> circ -> in");
3480 " command = cp $in $out\n" 3481 "build dd: cp dd-in\n" 3482 "build out1: true in || dd\n" 3484 "build out2: cat out1\n"));
3486 fs_.Create(
"out1",
"");
3487 fs_.Create(
"out2",
"");
3489 "ninja_dyndep_version = 1\n" 3490 "build out1: dyndep\n" 3494 fs_.Create(
"in",
"");
3504 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3505 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3506 EXPECT_EQ(
"true", command_runner_.commands_ran_[1]);
3507 EXPECT_EQ(
"cat out1 > out2", command_runner_.commands_ran_[2]);
3509 command_runner_.commands_ran_.clear();
3512 fs_.Create(
"in",
"");
3519 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3520 EXPECT_EQ(
"true", command_runner_.commands_ran_[0]);
3529 " command = touch $out $out.imp\n" 3531 " command = cp $in $out\n" 3532 "build out1 | out1.imp: touch\n" 3533 "build zdd: cp zdd-in\n" 3534 " verify_active_edge = out1\n" 3535 "build out2: cp out1 || zdd\n" 3538 fs_.Create(
"zdd-in",
3539 "ninja_dyndep_version = 1\n" 3540 "build out2: dyndep | out1.imp\n" 3545 command_runner_.max_active_edges_ = 2;
3561 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3564 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"touch out1 out1.imp" &&
3565 command_runner_.commands_ran_[1] ==
"cp zdd-in zdd") ||
3566 (command_runner_.commands_ran_[1] ==
"touch out1 out1.imp" &&
3567 command_runner_.commands_ran_[0] ==
"cp zdd-in zdd"));
3568 EXPECT_EQ(
"cp out1 out2", command_runner_.commands_ran_[2]);
3576 " command = touch $out $out.imp\n" 3578 " command = cp $in $out\n" 3579 "build dd1: cp dd1-in\n" 3580 "build out1 | out1.imp: touch || dd1\n" 3582 "build dd2: cp dd2-in || dd1\n" 3583 "build out2: touch || dd2\n" 3586 fs_.Create(
"out1.imp",
"");
3587 fs_.Create(
"out2",
"");
3588 fs_.Create(
"out2.imp",
"");
3589 fs_.Create(
"dd1-in",
3590 "ninja_dyndep_version = 1\n" 3591 "build out1: dyndep\n" 3593 fs_.Create(
"dd2-in",
"");
3595 "ninja_dyndep_version = 1\n" 3596 "build out2 | out2.imp: dyndep | out1.imp\n" 3612 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3613 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3614 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
3615 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
3624 " command = touch $out $out.imp\n" 3626 " command = cp $in $out\n" 3627 "build dd1: cp dd1-in\n" 3628 "build out1: touch || dd1\n" 3630 "build dd2: cp dd2-in || out1\n" 3631 "build out2: touch || dd2\n" 3634 fs_.Create(
"out1.imp",
"");
3635 fs_.Create(
"out2",
"");
3636 fs_.Create(
"out2.imp",
"");
3637 fs_.Create(
"dd1-in",
3638 "ninja_dyndep_version = 1\n" 3639 "build out1 | out1.imp: dyndep\n" 3641 fs_.Create(
"dd2-in",
"");
3643 "ninja_dyndep_version = 1\n" 3644 "build out2 | out2.imp: dyndep | out1.imp\n" 3657 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3658 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3659 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
3660 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
3668 " command = touch $out\n" 3670 " command = cp $in $out\n" 3671 "build dd0: cp dd0-in\n" 3672 "build dd1: cp dd1-in\n" 3674 "build tmp: touch || dd0\n" 3676 "build out: touch || dd1\n" 3679 fs_.Create(
"dd1-in",
3680 "ninja_dyndep_version = 1\n" 3681 "build out: dyndep | tmp\n" 3683 fs_.Create(
"dd0-in",
"");
3685 "ninja_dyndep_version = 1\n" 3686 "build tmp: dyndep | in\n" 3689 fs_.Create(
"out",
"");
3697 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3698 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3699 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3700 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[2]);
3701 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[3]);
3709 " command = touch $out\n" 3711 " command = cp $in $out\n" 3712 "build dd0: cp dd0-in\n" 3713 "build dd1: cp dd1-in\n" 3715 "build tmp: touch || dd0\n" 3717 "build out: touch || dd1\n" 3720 fs_.Create(
"dd1-in",
3721 "ninja_dyndep_version = 1\n" 3722 "build out: dyndep | tmp\n" 3724 fs_.Create(
"dd0-in",
3725 "ninja_dyndep_version = 1\n" 3726 "build tmp: dyndep | in\n" 3729 fs_.Create(
"out",
"");
3737 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
3738 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
3739 EXPECT_EQ(
"cp dd0-in dd0", command_runner_.commands_ran_[1]);
3740 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[2]);
3741 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[3]);
3742 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[4]);
3747 "build out: cat in |@ validate\n" 3748 "build validate: cat in2\n"));
3750 fs_.Create(
"in",
"");
3751 fs_.Create(
"in2",
"");
3760 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3765 fs_.Create(
"in",
"");
3768 command_runner_.commands_ran_.clear();
3776 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3777 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
3782 fs_.Create(
"in2",
"");
3785 command_runner_.commands_ran_.clear();
3793 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3794 EXPECT_EQ(
"cat in2 > validate", command_runner_.commands_ran_[0]);
3799 "build out: cat in |@ validate\n" 3800 "build validate: cat in2 | out\n"));
3802 fs_.Create(
"in",
"");
3803 fs_.Create(
"in2",
"");
3812 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3816 fs_.Create(
"in",
"");
3819 command_runner_.commands_ran_.clear();
3827 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3832 fs_.Create(
"in2",
"");
3835 command_runner_.commands_ran_.clear();
3843 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3844 EXPECT_EQ(
"cat in2 > validate", command_runner_.commands_ran_[0]);
3848 const char* manifest =
3849 "build out: cat in |@ validate\n" 3850 "build validate: cat in2 | out\n" 3851 "build out2: cat in3\n" 3853 " depfile = out2.d\n";
3858 fs_.Create(
"in",
"");
3859 fs_.Create(
"in2",
"");
3860 fs_.Create(
"in3",
"");
3861 fs_.Create(
"out2.d",
"out: out");
3871 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3881 ASSERT_EQ(command_runner_.commands_ran_.size(), 1);
3882 EXPECT_EQ(
"cat in3 > out2", command_runner_.commands_ran_[0]);
3892 command_runner_.commands_ran_.clear();
3895 fs_.Create(
"in2",
"");
3896 fs_.Create(
"in3",
"");
3907 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3917 ASSERT_EQ(command_runner_.commands_ran_.size(), 3);
3919 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
3928 "build out: cat in |@ out2\n" 3929 "build out2: cat in2 |@ out\n"));
3931 fs_.Create(
"in",
"");
3932 fs_.Create(
"in2",
"");
3941 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3945 fs_.Create(
"in",
"");
3948 command_runner_.commands_ran_.clear();
3956 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3957 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
3961 fs_.Create(
"in2",
"");
3964 command_runner_.commands_ran_.clear();
3972 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3973 EXPECT_EQ(
"cat in2 > out2", command_runner_.commands_ran_[0]);
3978 "build out: cat in |@ validate\n" 3979 "build validate: cat validate_in | out\n" 3980 "build validate_in: cat validate\n"));
3982 fs_.Create(
"in",
"");
3986 EXPECT_EQ(
"dependency cycle: validate -> validate_in -> validate", err);
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.
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
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)
int Tick()
Tick "time" forwards; subsequent file operations will be newer than previous ones.
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_
void Create(const std::string &path, const std::string &contents)
"Create" a file with contents.
virtual bool IsPathDead(StringPiece s) const
Return if a given output is no longer part of the build manifest.
Fixture for tests involving Plan.
int now_
A simple fake timestamp for file operations.
std::vector< Node * > outputs_
Node * GetNode(const std::string &path)
Short way to get a Node by its path from state_.
virtual vector< Edge * > GetActiveEdges()
Implementation of the Status interface that prints the status as human-readable strings to stdout...
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.
void TestPhonyUseCase(BuildTest *t, int i)
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_
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
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()
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.