32 struct CompareEdgesByOutput {
33 static bool cmp(
const Edge* a,
const Edge* b) {
38 for (
int i = 0; i < count; ++i) {
45 sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp);
53 "build out: cat mid\n" 54 "build mid: cat in\n");
64 ASSERT_EQ(
"in", edge->inputs_[0]->path());
65 ASSERT_EQ(
"mid", edge->outputs_[0]->path());
73 ASSERT_EQ(
"mid", edge->inputs_[0]->path());
74 ASSERT_EQ(
"out", edge->outputs_[0]->path());
86 "build out: cat mid1 mid2\n" 87 "build mid1 mid2: cat in\n");
113 "build out: cat b1 b2\n" 116 "build a1 a2: cat in\n");
151 "build out: cat a1 a2\n" 152 "build a1: cat mid\n" 153 "build a2: cat mid\n" 154 "build mid: cat in\n");
188 "build out: cat mid\n" 189 "build mid: cat in\n" 190 "build in: cat pre\n" 191 "build pre: cat out\n");
199 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
215 ASSERT_EQ(
"in", edge->inputs_[0]->path());
216 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
225 ASSERT_EQ(
"in", edge->inputs_[0]->path());
226 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
242 " command = cat $in > $out\n" 244 "build out1: poolcat in\n" 245 "build out2: poolcat in\n");
251 " command = cat $in > $out\n" 253 "build out1: poolcat in\n" 254 "build out2: poolcat in\n");
264 " command = cat $in > $out\n" 267 " command = cat $in > $out\n" 269 "build out1: foocat in\n" 270 "build out2: foocat in\n" 271 "build out3: foocat in\n" 272 "build outb1: bazcat in\n" 273 "build outb2: bazcat in\n" 274 "build outb3: bazcat in\n" 276 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n" 279 for (
int i = 0; i < 3; ++i) {
292 for (
int i = 0; i < 4; ++i) {
293 Edge *edge = edges[i];
294 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
295 string base_name(i < 2 ?
"out" :
"outb");
296 ASSERT_EQ(base_name +
string(1,
'1' + (i % 2)), edge->
outputs_[0]->path());
300 Edge* edge = edges[4];
302 ASSERT_EQ(
"in", edge->inputs_[0]->path());
303 ASSERT_EQ(
"outb3", edge->outputs_[0]->path());
312 ASSERT_EQ(
"in", out3->
inputs_[0]->path());
313 ASSERT_EQ(
"out3", out3->
outputs_[0]->path());
321 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
327 ASSERT_EQ(
"allTheThings", last->
outputs_[0]->path());
340 " command = touch foo.cpp\n" 342 " command = touch bar.cpp\n" 344 " command = echo $out > $out\n" 345 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n" 347 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n" 349 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n" 350 "build foo.cpp: gen_foo\n" 351 "build bar.cpp: gen_bar\n" 352 "build all: phony libfoo.a\n"));
366 deque<Edge*> initial_edges;
369 edge = initial_edges[1];
370 ASSERT_EQ(
"foo.cpp", edge->outputs_[0]->path());
376 ASSERT_EQ(
"foo.cpp", edge->inputs_[0]->path());
377 ASSERT_EQ(
"foo.cpp", edge->inputs_[1]->path());
378 ASSERT_EQ(
"foo.cpp.obj", edge->outputs_[0]->path());
381 edge = initial_edges[0];
382 ASSERT_EQ(
"bar.cpp", edge->outputs_[0]->path());
388 ASSERT_EQ(
"bar.cpp", edge->inputs_[0]->path());
389 ASSERT_EQ(
"bar.cpp", edge->inputs_[1]->path());
390 ASSERT_EQ(
"bar.cpp.obj", edge->outputs_[0]->path());
396 ASSERT_EQ(
"foo.cpp.obj", edge->inputs_[0]->path());
397 ASSERT_EQ(
"bar.cpp.obj", edge->inputs_[1]->path());
398 ASSERT_EQ(
"libfoo.a", edge->outputs_[0]->path());
404 ASSERT_EQ(
"libfoo.a", edge->inputs_[0]->path());
405 ASSERT_EQ(
"all", edge->outputs_[0]->path());
416 last_command_(NULL), fs_(fs) {}
419 virtual bool CanRunMore();
420 virtual bool StartCommand(
Edge* edge);
421 virtual bool WaitForCommand(
Result* result);
422 virtual vector<Edge*> GetActiveEdges();
423 virtual void Abort();
431 BuildTest() : config_(MakeConfig()), command_runner_(&fs_),
432 builder_(&
state_, config_, NULL, NULL, &fs_),
437 StateTestWithBuiltinRules::SetUp();
439 builder_.command_runner_.reset(&command_runner_);
441 "build cat1: cat in1\n" 442 "build cat2: cat in1 in2\n" 443 "build cat12: cat cat1 cat2\n");
445 fs_.Create(
"in1",
"");
446 fs_.Create(
"in2",
"");
450 builder_.command_runner_.release();
458 void RebuildTarget(
const string& target,
const char* manifest,
459 const char* log_path = NULL,
460 const char* deps_path = NULL);
463 void Dirty(
const string& path);
480 const char* log_path,
const char* deps_path) {
486 BuildLog build_log, *pbuild_log = NULL;
488 ASSERT_TRUE(build_log.
Load(log_path, &err));
489 ASSERT_TRUE(build_log.
OpenForWrite(log_path, *
this, &err));
491 pbuild_log = &build_log;
494 DepsLog deps_log, *pdeps_log = NULL;
496 ASSERT_TRUE(deps_log.
Load(deps_path, &state, &err));
499 pdeps_log = &deps_log;
502 Builder builder(&state, config_, pbuild_log, pdeps_log, &fs_);
503 EXPECT_TRUE(builder.
AddTarget(target, &err));
505 command_runner_.commands_ran_.clear();
508 bool build_res = builder.
Build(&err);
509 EXPECT_TRUE(build_res) <<
"builder.Build(&err)";
516 return last_command_ == NULL;
520 assert(!last_command_);
524 edge->
rule().
name() ==
"cat_rsp_out" ||
527 edge->
rule().
name() ==
"touch-interrupt") {
528 for (vector<Node*>::iterator out = edge->
outputs_.begin();
529 out != edge->
outputs_.end(); ++out) {
530 fs_->Create((*out)->path(),
"");
532 }
else if (edge->
rule().
name() ==
"true" ||
534 edge->
rule().
name() ==
"interrupt" ||
538 printf(
"unknown command\n");
542 last_command_ = edge;
550 Edge* edge = last_command_;
553 if (edge->
rule().
name() ==
"interrupt" ||
554 edge->
rule().
name() ==
"touch-interrupt") {
559 if (edge->
rule().
name() ==
"console") {
564 last_command_ = NULL;
572 last_command_ = NULL;
579 edges.push_back(last_command_);
584 last_command_ = NULL;
599 EXPECT_TRUE(builder_.AlreadyUpToDate());
607 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
609 EXPECT_TRUE(builder_.Build(&err));
612 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
613 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
621 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
623 EXPECT_TRUE(builder_.Build(&err));
626 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
627 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
632 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
634 EXPECT_TRUE(builder_.Build(&err));
636 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
639 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
640 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
641 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
642 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
644 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
650 fs_.Create(
"in2",
"");
652 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
654 EXPECT_TRUE(builder_.Build(&err));
656 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
657 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
658 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
664 " command = touch $out\n" 665 "build out1 out2: touch in.txt\n"));
667 fs_.Create(
"in.txt",
"");
670 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
672 EXPECT_TRUE(builder_.Build(&err));
674 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
675 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
683 " command = touch $out\n" 684 "build in1 otherfile: touch in\n" 685 "build out: touch in | in1\n"));
687 fs_.Create(
"in",
"");
689 fs_.Create(
"in1",
"");
692 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
694 EXPECT_TRUE(builder_.Build(&err));
703 "build c5: cat c4\n"));
705 fs_.Create(
"c1",
"");
708 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
710 EXPECT_TRUE(builder_.Build(&err));
712 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
715 command_runner_.commands_ran_.clear();
717 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
719 EXPECT_TRUE(builder_.AlreadyUpToDate());
723 fs_.Create(
"c3",
"");
725 command_runner_.commands_ran_.clear();
727 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
729 EXPECT_FALSE(builder_.AlreadyUpToDate());
730 EXPECT_TRUE(builder_.Build(&err));
731 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
738 EXPECT_FALSE(builder_.AddTarget(
"cat1", &err));
739 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
746 EXPECT_FALSE(builder_.AddTarget(
"meow", &err));
747 EXPECT_EQ(
"unknown target: 'meow'", err);
755 "build subdir\\dir2\\file: cat in1\n"));
756 EXPECT_TRUE(builder_.AddTarget(
"subdir\\dir2\\file", &err));
759 "build subdir/dir2/file: cat in1\n"));
760 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
764 EXPECT_TRUE(builder_.Build(&err));
766 ASSERT_EQ(2u, fs_.directories_made_.size());
767 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
769 EXPECT_EQ(
"subdir\\dir2", fs_.directories_made_[1]);
771 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
778 "rule cc\n command = cc $in\n depfile = $out.d\n" 779 "build fo$ o.o: cc foo.c\n"));
780 fs_.Create(
"foo.c",
"");
782 EXPECT_TRUE(builder_.AddTarget(
"fo o.o", &err));
784 ASSERT_EQ(1u, fs_.files_read_.size());
785 EXPECT_EQ(
"fo o.o.d", fs_.files_read_[0]);
792 "rule cc\n command = cc $in\n depfile = $out.d\n" 793 "build foo.o: cc foo.c\n"));
796 fs_.Create(
"foo.c",
"");
798 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
799 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
801 ASSERT_EQ(1u, fs_.files_read_.size());
802 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
808 ASSERT_EQ(3u, edge->
inputs_.size());
817 "rule cc\n command = cc $in\n depfile = $out.d\n" 818 "build foo.o: cc foo.c\n"));
819 fs_.Create(
"foo.c",
"");
820 fs_.Create(
"foo.o.d",
"randomtext\n");
821 EXPECT_FALSE(builder_.AddTarget(
"foo.o", &err));
822 EXPECT_EQ(
"expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
829 "rule cc\n command = cc $in\n depfile = $out.d\n" 830 "build foo.o: cc foo.c || otherfile\n"));
833 fs_.Create(
"foo.c",
"");
834 fs_.Create(
"otherfile",
"");
835 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
836 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
840 ASSERT_EQ(4u, edge->
inputs_.size());
845 EXPECT_EQ(
"foo.c", edge->
inputs_[0]->path());
846 EXPECT_EQ(
"blah.h", edge->
inputs_[1]->path());
847 EXPECT_EQ(
"bar.h", edge->
inputs_[2]->path());
848 EXPECT_EQ(
"otherfile", edge->
inputs_[3]->path());
854 EXPECT_TRUE(builder_.Build(&err));
856 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
861 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
864 fs_.Create(
"blah.h",
"");
865 fs_.Create(
"bar.h",
"");
866 command_runner_.commands_ran_.clear();
868 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
869 EXPECT_TRUE(builder_.Build(&err));
871 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
876 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
879 fs_.Create(
"otherfile",
"");
880 command_runner_.commands_ran_.clear();
882 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
884 EXPECT_TRUE(builder_.AlreadyUpToDate());
887 fs_.RemoveFile(
"bar.h");
888 command_runner_.commands_ran_.clear();
890 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
891 EXPECT_TRUE(builder_.Build(&err));
893 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
899 "rule cc\n command = cc $in\n" 900 "rule true\n command = true\n" 901 "build oo.h: cc oo.h.in\n" 902 "build foo.o: cc foo.c || oo.h\n"));
904 fs_.Create(
"foo.c",
"");
905 fs_.Create(
"oo.h.in",
"");
908 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
909 EXPECT_TRUE(builder_.Build(&err));
911 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
914 command_runner_.commands_ran_.clear();
916 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
918 EXPECT_TRUE(builder_.AlreadyUpToDate());
921 fs_.RemoveFile(
"oo.h");
922 command_runner_.commands_ran_.clear();
924 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
925 EXPECT_TRUE(builder_.Build(&err));
927 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
928 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
933 fs_.Create(
"oo.h.in",
"");
934 command_runner_.commands_ran_.clear();
936 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
937 EXPECT_TRUE(builder_.Build(&err));
939 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
940 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
946 "build out: cat bar.cc\n" 947 "build all: phony out\n"));
948 fs_.Create(
"bar.cc",
"");
950 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
954 EXPECT_FALSE(builder_.AlreadyUpToDate());
955 EXPECT_TRUE(builder_.Build(&err));
957 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
963 "build out: cat bar.cc\n" 964 "build all: phony out\n"));
965 fs_.Create(
"bar.cc",
"");
966 fs_.Create(
"out",
"");
968 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
970 EXPECT_TRUE(builder_.AlreadyUpToDate());
977 "build out1: fail\n"));
980 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
983 EXPECT_FALSE(builder_.Build(&err));
984 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
985 ASSERT_EQ(
"subcommand failed", err);
995 "build all: phony out1 out2 out3\n"));
998 config_.failures_allowed = 3;
1001 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
1004 EXPECT_FALSE(builder_.Build(&err));
1005 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1006 ASSERT_EQ(
"subcommands failed", err);
1013 "build out1: fail\n" 1014 "build out2: fail\n" 1015 "build out3: fail\n" 1016 "build final: cat out1 out2 out3\n"));
1019 config_.failures_allowed = 11;
1022 EXPECT_TRUE(builder_.AddTarget(
"final", &err));
1025 EXPECT_FALSE(builder_.Build(&err));
1026 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1027 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1032 builder_.SetBuildLog(&build_log_);
1042 "build out1: cc in\n"));
1046 fs_.Create(
"in",
"");
1047 fs_.Create(
"out1",
"");
1052 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1053 EXPECT_FALSE(builder_.AlreadyUpToDate());
1055 command_runner_.commands_ran_.clear();
1058 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1059 EXPECT_TRUE(builder_.Build(&err));
1060 EXPECT_TRUE(builder_.AlreadyUpToDate());
1071 "build out1: cc in\n" 1072 "build out2: true out1\n" 1073 "build out3: cat out2\n"));
1075 fs_.Create(
"out1",
"");
1076 fs_.Create(
"out2",
"");
1077 fs_.Create(
"out3",
"");
1081 fs_.Create(
"in",
"");
1087 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1089 EXPECT_TRUE(builder_.Build(&err));
1091 EXPECT_EQ(
"[3/3]", builder_.status_->FormatProgressStatus(
"[%s/%t]"));
1092 command_runner_.commands_ran_.clear();
1097 fs_.Create(
"in",
"");
1100 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1102 EXPECT_TRUE(builder_.Build(&err));
1103 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1107 command_runner_.commands_ran_.clear();
1109 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1111 EXPECT_TRUE(builder_.AlreadyUpToDate());
1115 fs_.Create(
"in",
"");
1119 command_runner_.commands_ran_.clear();
1121 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1123 EXPECT_TRUE(builder_.Build(&err));
1124 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1138 "build out1: true in\n" 1139 "build out2: cc out1\n"));
1141 fs_.Create(
"in",
"");
1142 fs_.Create(
"out2",
"");
1148 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1150 EXPECT_TRUE(builder_.Build(&err));
1152 command_runner_.commands_ran_.clear();
1156 fs_.Create(
"in",
"");
1157 fs_.Create(
"out2",
"");
1162 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1164 EXPECT_TRUE(builder_.Build(&err));
1165 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1174 " command = touch\n" 1175 "build out1: true in\n" 1176 "build out2 out3: touch out1\n" 1177 "build out4: touch out2\n" 1181 fs_.Create(
"in",
"");
1184 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1186 EXPECT_TRUE(builder_.Build(&err));
1188 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1191 fs_.Create(
"in",
"");
1192 fs_.RemoveFile(
"out3");
1199 command_runner_.commands_ran_.clear();
1201 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1203 EXPECT_TRUE(builder_.Build(&err));
1205 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1214 " depfile = $out.d\n" 1218 "build out1: true in\n" 1219 "build out2: cc out1\n"));
1222 fs_.Create(
"in",
"");
1227 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1228 fs_.Create(
"will.be.deleted",
"");
1229 fs_.Create(
"restat.file",
"");
1233 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1235 EXPECT_TRUE(builder_.Build(&err));
1236 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1241 ASSERT_TRUE(NULL != log_entry);
1242 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1246 fs_.RemoveFile(
"will.be.deleted");
1249 command_runner_.commands_ran_.clear();
1251 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1253 EXPECT_TRUE(builder_.Build(&err));
1254 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1257 log_entry = build_log_.LookupByOutput(
"out1");
1258 ASSERT_TRUE(NULL != log_entry);
1259 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1264 config_.dry_run =
true;
1276 "build out1: cc in\n" 1277 "build out2: true out1\n" 1278 "build out3: cat out2\n"));
1280 fs_.Create(
"out1",
"");
1281 fs_.Create(
"out2",
"");
1282 fs_.Create(
"out3",
"");
1286 fs_.Create(
"in",
"");
1291 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1293 EXPECT_TRUE(builder_.Build(&err));
1294 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1303 " command = cat $rspfile > $out\n" 1304 " rspfile = $rspfile\n" 1305 " rspfile_content = $long_command\n" 1306 "rule cat_rsp_out\n" 1307 " command = cat $rspfile > $out\n" 1308 " rspfile = $out.rsp\n" 1309 " rspfile_content = $long_command\n" 1310 "build out1: cat in\n" 1311 "build out2: cat_rsp in\n" 1312 " rspfile = out 2.rsp\n" 1313 " long_command = Some very long command\n" 1314 "build out$ 3: cat_rsp_out in\n" 1315 " long_command = Some very long command\n"));
1317 fs_.Create(
"out1",
"");
1318 fs_.Create(
"out2",
"");
1319 fs_.Create(
"out 3",
"");
1323 fs_.Create(
"in",
"");
1326 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1328 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1330 EXPECT_TRUE(builder_.AddTarget(
"out 3", &err));
1333 size_t files_created = fs_.files_created_.size();
1334 size_t files_removed = fs_.files_removed_.size();
1336 EXPECT_TRUE(builder_.Build(&err));
1337 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1340 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1341 ASSERT_EQ(1u, fs_.files_created_.count(
"out 2.rsp"));
1342 ASSERT_EQ(1u, fs_.files_created_.count(
"out 3.rsp"));
1345 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1346 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 2.rsp"));
1347 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 3.rsp"));
1355 " rspfile = $rspfile\n" 1356 " rspfile_content = $long_command\n" 1357 "build out: fail in\n" 1358 " rspfile = out.rsp\n" 1359 " long_command = Another very long command\n"));
1361 fs_.Create(
"out",
"");
1363 fs_.Create(
"in",
"");
1366 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1369 size_t files_created = fs_.files_created_.size();
1370 size_t files_removed = fs_.files_removed_.size();
1372 EXPECT_FALSE(builder_.Build(&err));
1373 ASSERT_EQ(
"subcommand failed", err);
1374 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1377 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1378 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
1381 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1382 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
1385 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
1393 " command = cat $rspfile > $out\n" 1394 " rspfile = $rspfile\n" 1395 " rspfile_content = $long_command\n" 1396 "build out: cat_rsp in\n" 1397 " rspfile = out.rsp\n" 1398 " long_command = Original very long command\n"));
1400 fs_.Create(
"out",
"");
1402 fs_.Create(
"in",
"");
1405 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1409 EXPECT_TRUE(builder_.Build(&err));
1410 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1413 command_runner_.commands_ran_.clear();
1415 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1417 ASSERT_TRUE(builder_.AlreadyUpToDate());
1422 ASSERT_TRUE(NULL != log_entry);
1424 "cat out.rsp > out;rspfile=Original very long command",
1425 log_entry->command_hash));
1426 log_entry->command_hash++;
1428 command_runner_.commands_ran_.clear();
1430 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1432 EXPECT_TRUE(builder_.Build(&err));
1433 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1439 " command = interrupt\n" 1440 "rule touch-interrupt\n" 1441 " command = touch-interrupt\n" 1442 "build out1: interrupt in1\n" 1443 "build out2: touch-interrupt in2\n"));
1445 fs_.Create(
"out1",
"");
1446 fs_.Create(
"out2",
"");
1448 fs_.Create(
"in1",
"");
1449 fs_.Create(
"in2",
"");
1453 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1455 EXPECT_FALSE(builder_.Build(&err));
1456 EXPECT_EQ(
"interrupted by user", err);
1458 EXPECT_GT(fs_.Stat(
"out1"), 0);
1462 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1464 EXPECT_FALSE(builder_.Build(&err));
1465 EXPECT_EQ(
"interrupted by user", err);
1467 EXPECT_EQ(0, fs_.Stat(
"out2"));
1472 "build nonexistent: phony\n" 1473 "build out1: cat || nonexistent\n" 1474 "build out2: cat nonexistent\n"));
1475 fs_.Create(
"out1",
"");
1476 fs_.Create(
"out2",
"");
1481 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1483 EXPECT_TRUE(builder_.AlreadyUpToDate());
1487 command_runner_.commands_ran_.clear();
1489 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1491 EXPECT_TRUE(builder_.Build(&err));
1493 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1501 "build out: cc\n"));
1505 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1507 EXPECT_FALSE(builder_.AlreadyUpToDate());
1509 EXPECT_FALSE(builder_.Build(&err));
1510 ASSERT_EQ(
"subcommand failed", err);
1511 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1515 EXPECT_EQ(
"[%/s0/t0/r0/u0/f0]",
1516 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]"));
1521 "build bad_deps.o: cat in1\n" 1523 " depfile = in1.d\n"));
1526 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
1531 fs_.Create(
"in1.d",
"AAA BBB");
1533 EXPECT_FALSE(builder_.Build(&err));
1534 EXPECT_EQ(
"subcommand failed", err);
1547 temp_dir_.CreateAndEnter(
"BuildWithDepsLogTest");
1551 temp_dir_.Cleanup();
1564 const char* manifest =
1565 "build out: cat in1\n" 1567 " depfile = in1.d\n";
1571 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1575 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1578 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1580 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1582 fs_.Create(
"in1.d",
"out: in2");
1583 EXPECT_TRUE(builder.
Build(&err));
1587 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1589 fs_.Create(
"in1.d",
"out: in2");
1597 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1601 fs_.Create(
"in2",
"");
1605 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1606 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1608 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1609 builder.command_runner_.reset(&command_runner_);
1610 command_runner_.commands_ran_.clear();
1611 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1613 EXPECT_TRUE(builder.Build(&err));
1618 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1620 builder.command_runner_.release();
1631 const char* manifest =
1632 "build out: cat in1\n" 1634 " depfile = in1.d\n";
1637 fs_.Create(
"in1",
"");
1638 fs_.Create(
"in1.d",
"out: ");
1642 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1646 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1649 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1651 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1653 EXPECT_TRUE(builder.
Build(&err));
1663 fs_.Create(
"in1",
"");
1664 fs_.Create(
"out",
"");
1667 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1672 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1675 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1676 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1678 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1679 builder.command_runner_.reset(&command_runner_);
1680 command_runner_.commands_ran_.clear();
1681 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1685 fs_.Create(
"in1.d",
"out: ");
1687 EXPECT_TRUE(builder.Build(&err));
1692 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1694 builder.command_runner_.release();
1699 const char* manifest =
1700 "build out: cat in1\n" 1702 " depfile = in1.d\n";
1704 fs_.Create(
"out",
"");
1706 fs_.Create(
"in1",
"");
1710 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1713 config_.dry_run =
true;
1714 Builder builder(&state, config_, NULL, NULL, &fs_);
1716 command_runner_.commands_ran_.clear();
1719 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1721 EXPECT_TRUE(builder.
Build(&err));
1722 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1733 "build header.h: true header.in\n" 1734 "build out: cat in1\n" 1735 " depfile = in1.d\n"));
1737 fs_.Create(
"header.h",
"");
1738 fs_.Create(
"in1.d",
"out: header.h");
1740 fs_.Create(
"header.in",
"");
1743 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1745 EXPECT_TRUE(builder_.Build(&err));
1754 const char* manifest =
1758 "build header.h: true header.in\n" 1759 "build out: cat in1\n" 1761 " depfile = in1.d\n";
1765 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1769 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1772 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1774 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1776 fs_.Create(
"in1.d",
"out: header.h");
1777 EXPECT_TRUE(builder.
Build(&err));
1787 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1791 fs_.Create(
"header.in",
"");
1795 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1796 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1798 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1799 builder.command_runner_.reset(&command_runner_);
1800 command_runner_.commands_ran_.clear();
1801 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1803 EXPECT_TRUE(builder.Build(&err));
1808 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1810 builder.command_runner_.release();
1816 const char* manifest =
1817 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n" 1818 "build fo$ o.o: cc foo.c\n";
1820 fs_.Create(
"foo.c",
"");
1824 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1828 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1831 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1833 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
1835 fs_.Create(
"fo o.o.d",
"fo\\ o.o: blah.h bar.h\n");
1836 EXPECT_TRUE(builder.
Build(&err));
1845 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1848 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1849 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1852 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1858 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
1863 ASSERT_EQ(3u, state.
edges_.size());
1865 ASSERT_EQ(3u, edge->
inputs_.size());
1878 const char* manifest =
1882 "build header.h: true header.in\n" 1883 "build out: cat header.h\n" 1884 " depfile = out.d\n";
1886 fs_.Create(
"header.h",
"");
1888 fs_.Create(
"out",
"");
1889 fs_.Create(
"header.in",
"");
1895 RebuildTarget(
"out", manifest);
1896 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1903 const char* manifest =
1907 "build header.h: true header.in\n" 1908 "build out: cat header.h\n" 1910 " depfile = out.d\n";
1913 fs_.Create(
"header.in",
"");
1914 fs_.Create(
"out.d",
"out: header.h");
1915 fs_.Create(
"header.h",
"");
1917 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
1918 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1921 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
1922 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1928 fs_.Create(
"header.in",
"");
1931 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1932 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1935 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1936 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1941 fs_.Create(
"header.in",
"");
1942 fs_.Create(
"out",
"");
1943 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1944 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1947 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1948 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1954 " command = console\n" 1956 "build cons: console in.txt\n"));
1958 fs_.Create(
"in.txt",
"");
1961 EXPECT_TRUE(builder_.AddTarget(
"cons", &err));
1963 EXPECT_TRUE(builder_.Build(&err));
1965 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
FakeCommandRunner command_runner_
An implementation of DiskInterface that uses an in-memory representation of disk state.
CommandRunner is an interface that wraps running the build subcommands.
FakeCommandRunner(VirtualFileSystem *fs)
vector< Edge * > edges_
All the edges of the graph.
Node * GetNode(const string &path)
Short way to get a Node by its path from state_.
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...
bool more_to_do() const
Returns true if there's more work to be done.
Node * GetNode(StringPiece path)
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.
bool AddTarget(Node *node, string *err)
Add a target to our plan (including all its dependencies).
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
Fixture for tests involving Plan.
virtual vector< Edge * > GetActiveEdges()
void AssertParse(State *state, const char *input)
An edge in the dependency graph; links between Nodes using Rules.
Store a log of every command ran for every build.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
A base test fixture that includes a State object with a builtin "cat" rule.
void RebuildTarget(const string &target, const char *manifest, const char *log_path=NULL, const char *deps_path=NULL)
Rebuild target in the 'working tree' (fs_).
void EdgeFinished(Edge *edge)
Mark an edge as done building.
void AddCatRule(State *state)
Add a "cat" rule to state.
As build commands run they can output extra dependency information (e.g.
void FindWorkSorted(deque< Edge * > *ret, int count)
Because FindWork does not return Edges in any sort of predictable order,.
virtual bool IsPathDead(StringPiece s) const
Return if a given output no longer part of the build manifest.
bool OpenForWrite(const string &path, const BuildLogUser &user, string *err)
bool OpenForWrite(const string &path, string *err)
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.
bool Load(const string &path, State *state, string *err)
Fake implementation of CommandRunner, useful for tests.
virtual bool CanRunMore()
auto_ptr< CommandRunner > command_runner_
Builder wraps the build process: starting commands, updating status.
Tracks the status of a build: completion fraction, printing updates.
virtual bool StartCommand(Edge *edge)
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status, loaded rules) for a single run.
const string & name() const
void Dirty(const string &path)
bool Load(const string &path, string *err)
Load the on-disk log.
bool Build(string *err)
Run the build.
const Rule & rule() const
vector< string > commands_ran_
void AssertHash(const char *expected, uint64_t actual)
Node * AddTarget(const string &name, string *err)
Can answer questions about the manifest for the BuildLog.
vector< Node * > outputs_