24 GraphTest() : scan_(&state_, NULL, NULL, &fs_, NULL, NULL) {}
32 "build out: cat in | implicit\n"));
34 fs_.Create(
"out",
"");
37 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
43 EXPECT_TRUE(GetNode(
"out")->dirty());
48 "build out: cat in | implicit\n"));
50 fs_.Create(
"out",
"");
52 fs_.Create(
"implicit",
"");
55 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
59 EXPECT_TRUE(GetNode(
"out")->dirty());
66 " command = cat $in > $out\n"
67 "build out.o: catdep foo.cc\n"));
68 fs_.Create(
"foo.cc",
"");
69 fs_.Create(
"out.o.d",
"out.o: ./foo/../implicit.h\n");
70 fs_.Create(
"out.o",
"");
72 fs_.Create(
"implicit.h",
"");
75 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
80 EXPECT_TRUE(GetNode(
"out.o")->dirty());
87 " command = cat $in > $out\n"
88 "build implicit.h: cat data\n"
89 "build out.o: catdep foo.cc || implicit.h\n"));
90 fs_.Create(
"implicit.h",
"");
91 fs_.Create(
"foo.cc",
"");
92 fs_.Create(
"out.o.d",
"out.o: implicit.h\n");
93 fs_.Create(
"out.o",
"");
95 fs_.Create(
"data",
"");
98 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
104 EXPECT_TRUE(GetNode(
"out.o")->dirty());
109 "build out | out.imp: cat in\n"));
111 Edge* edge = GetNode(
"out")->in_edge();
112 EXPECT_EQ(
size_t(2), edge->
outputs_.size());
113 EXPECT_EQ(
"out", edge->
outputs_[0]->path());
114 EXPECT_EQ(
"out.imp", edge->
outputs_[1]->path());
116 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
121 "build out | out.imp: cat in\n"));
122 fs_.Create(
"in",
"");
123 fs_.Create(
"out",
"");
126 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
129 EXPECT_TRUE(GetNode(
"out")->dirty());
130 EXPECT_TRUE(GetNode(
"out.imp")->dirty());
135 "build out | out.imp: cat in\n"));
136 fs_.Create(
"out.imp",
"");
138 fs_.Create(
"in",
"");
139 fs_.Create(
"out",
"");
142 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
145 EXPECT_TRUE(GetNode(
"out")->dirty());
146 EXPECT_TRUE(GetNode(
"out.imp")->dirty());
151 "build | out.imp: cat in\n"));
153 Edge* edge = GetNode(
"out.imp")->in_edge();
154 EXPECT_EQ(
size_t(1), edge->
outputs_.size());
155 EXPECT_EQ(
"out.imp", edge->
outputs_[0]->path());
157 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
162 "build | out.imp: cat in\n"));
163 fs_.Create(
"in",
"");
166 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), NULL, &err));
169 EXPECT_TRUE(GetNode(
"out.imp")->dirty());
174 "build | out.imp: cat in\n"));
175 fs_.Create(
"out.imp",
"");
177 fs_.Create(
"in",
"");
180 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), NULL, &err));
183 EXPECT_TRUE(GetNode(
"out.imp")->dirty());
189 " depfile = $out.d\n"
190 " command = cat $in > $out\n"
191 "build ./out.o: catdep ./foo.cc\n"));
192 fs_.Create(
"foo.cc",
"");
193 fs_.Create(
"out.o.d",
"out.o: foo.cc\n");
194 fs_.Create(
"out.o",
"");
197 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
200 EXPECT_FALSE(GetNode(
"out.o")->dirty());
205 "build out1: cat in1\n"
206 "build mid1: cat in1\n"
207 "build out2: cat mid1\n"
208 "build out3 out4: cat mid1\n"));
211 vector<Node*> root_nodes = state_.RootNodes(&err);
212 EXPECT_EQ(4u, root_nodes.size());
213 for (
size_t i = 0; i < root_nodes.size(); ++i) {
214 string name = root_nodes[i]->path();
215 EXPECT_EQ(
"out", name.substr(0, 3));
239 "build out1: cat in1\n"
240 "build mid1: cat in1\n"
241 "build out2: cat mid1\n"
242 "build out3 out4: cat mid1\n"
243 "build all: phony out1 out2 out3\n"));
251 ASSERT_EQ(1u, inputs.size());
252 EXPECT_EQ(
"in1", inputs[0]);
257 ASSERT_EQ(2u, inputs.size());
258 EXPECT_EQ(
"in1", inputs[0]);
259 EXPECT_EQ(
"mid1", inputs[1]);
265 ASSERT_EQ(5u, inputs.size());
266 EXPECT_EQ(
"in1", inputs[0]);
267 EXPECT_EQ(
"mid1", inputs[1]);
268 EXPECT_EQ(
"out1", inputs[2]);
269 EXPECT_EQ(
"out2", inputs[3]);
270 EXPECT_EQ(
"out3", inputs[4]);
278 ASSERT_EQ(5u, inputs.size());
279 EXPECT_EQ(
"in1", inputs[0]);
280 EXPECT_EQ(
"out1", inputs[1]);
281 EXPECT_EQ(
"mid1", inputs[2]);
282 EXPECT_EQ(
"out2", inputs[3]);
283 EXPECT_EQ(
"out3", inputs[4]);
289 "build out$ 1: cat in1 in2 in$ with$ space | implicit || order_only\n"));
294 ASSERT_EQ(5u, inputs.size());
295 EXPECT_EQ(
"in1", inputs[0]);
296 EXPECT_EQ(
"in2", inputs[1]);
297 EXPECT_EQ(
"in with space", inputs[2]);
298 EXPECT_EQ(
"implicit", inputs[3]);
299 EXPECT_EQ(
"order_only", inputs[4]);
302 ASSERT_EQ(5u, inputs.size());
303 EXPECT_EQ(
"in1", inputs[0]);
304 EXPECT_EQ(
"in2", inputs[1]);
306 EXPECT_EQ(
"\"in with space\"", inputs[2]);
308 EXPECT_EQ(
"'in with space'", inputs[2]);
310 EXPECT_EQ(
"implicit", inputs[3]);
311 EXPECT_EQ(
"order_only", inputs[4]);
316 "build out1: cat in1\n"
317 "build mid1: cat in1\n"
318 "build out2: cat mid1\n"
319 "build out3 out4: cat mid1\n"
320 "build all: phony out1 out2 out3\n"));
328 ASSERT_EQ(2u, edges.size());
329 EXPECT_EQ(
"cat in1 > mid1", edges[0]->EvaluateCommand());
330 EXPECT_EQ(
"cat mid1 > out2", edges[1]->EvaluateCommand());
334 ASSERT_EQ(3u, edges.size());
335 EXPECT_EQ(
"cat in1 > out1", edges[2]->EvaluateCommand());
340 ASSERT_EQ(4u, edges.size());
341 EXPECT_EQ(
"cat in1 > mid1", edges[0]->EvaluateCommand());
342 EXPECT_EQ(
"cat mid1 > out2", edges[1]->EvaluateCommand());
343 EXPECT_EQ(
"cat in1 > out1", edges[2]->EvaluateCommand());
344 EXPECT_EQ(
"cat mid1 > out3 out4", edges[3]->EvaluateCommand());
354 ASSERT_EQ(4u, edges.size());
355 EXPECT_EQ(
"cat in1 > out1", edges[0]->EvaluateCommand());
356 EXPECT_EQ(
"cat in1 > mid1", edges[1]->EvaluateCommand());
357 EXPECT_EQ(
"cat mid1 > out2", edges[2]->EvaluateCommand());
358 EXPECT_EQ(
"cat mid1 > out3 out4", edges[3]->EvaluateCommand());
364 "build a$ b: cat no'space with$ space$$ no\"space2\n"));
366 Edge* edge = GetNode(
"a b")->in_edge();
368 EXPECT_EQ(
"cat no'space \"with space$\" \"no\\\"space2\" > \"a b\"",
371 EXPECT_EQ(
"cat 'no'\\''space' 'with space$' 'no\"space2' > 'a b'",
380 " depfile = $out.d\n"
381 " command = cat $in > $out\n"
382 "build ./out.o: catdep ./foo.cc\n"));
383 fs_.Create(
"foo.cc",
"");
384 fs_.Create(
"out.o.d",
"out.o: bar/../foo.cc\n");
385 fs_.Create(
"out.o",
"");
388 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
391 EXPECT_FALSE(GetNode(
"out.o")->dirty());
398 " depfile = $out.d\n"
399 " command = cat $in > $out\n"
400 "build ./out.o: catdep ./foo.cc\n"));
401 fs_.Create(
"foo.h",
"");
402 fs_.Create(
"foo.cc",
"");
404 fs_.Create(
"out.o.d",
"out.o: foo.h\n");
405 fs_.Create(
"out.o",
"");
408 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
410 EXPECT_FALSE(GetNode(
"out.o")->dirty());
413 fs_.RemoveFile(
"out.o.d");
414 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), NULL, &err));
416 EXPECT_TRUE(GetNode(
"out.o")->dirty());
424 " command = depfile is $depfile\n"
425 "build out: r in\n"));
426 Edge* edge = GetNode(
"out")->in_edge();
435 " command = unused\n"
438 Edge* edge = GetNode(
"out")->in_edge();
447 " command = depfile is $depfile\n"
450 Edge* edge = GetNode(
"out")->in_edge();
451 EXPECT_EQ(
"depfile is y", edge->
GetBinding(
"command"));
458 "build n2: phony n1\n"
461 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"n2"), NULL, &err));
465 EXPECT_TRUE(plan_.
AddTarget(GetNode(
"n2"), &err));
476 "build a: phony a\n",
480 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"a"), NULL, &err));
481 ASSERT_EQ(
"dependency cycle: a -> a [-w phonycycle=err]", err);
486 "build out: cat mid\n"
487 "build mid: cat in\n"
488 "build in: cat pre\n"
489 "build pre: cat out\n");
492 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
493 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
499 "build a b: cat a\n");
500 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"b"), NULL, &err));
501 ASSERT_EQ(
"dependency cycle: a -> a", err);
507 "build b a: cat a\n"));
508 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"b"), NULL, &err));
509 ASSERT_EQ(
"dependency cycle: a -> a", err);
516 "build c: cat a\n"));
517 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"b"), NULL, &err));
518 ASSERT_EQ(
"dependency cycle: a -> c -> a", err);
528 "build f: cat e\n"));
529 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"f"), NULL, &err));
530 ASSERT_EQ(
"dependency cycle: a -> d -> c -> b -> a", err);
539 " command = unused\n"
540 "build a b: deprule\n"
542 fs_.Create(
"dep.d",
"a: b\n");
545 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"a"), NULL, &err));
546 ASSERT_EQ(
"dependency cycle: b -> b", err);
551 Edge* edge = GetNode(
"a")->in_edge();
552 EXPECT_EQ(
size_t(1), edge->
inputs_.size());
553 EXPECT_EQ(
"b", edge->
inputs_[0]->path());
561 " command = unused\n"
563 " command = unused\n"
564 "build a b: deprule\n"
567 fs_.Create(
"dep.d",
"a: c\n");
570 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"a"), NULL, &err));
571 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
576 Edge* edge = GetNode(
"a")->in_edge();
577 EXPECT_EQ(
size_t(1), edge->
inputs_.size());
578 EXPECT_EQ(
"c", edge->
inputs_[0]->path());
587 " command = unused\n"
589 " command = unused\n"
590 "build a b: deprule\n"
594 fs_.Create(
"dep.d",
"a: c\n");
597 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"d"), NULL, &err));
598 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
603 Edge* edge = GetNode(
"a")->in_edge();
604 EXPECT_EQ(
size_t(1), edge->
inputs_.size());
605 EXPECT_EQ(
"c", edge->
inputs_[0]->path());
611 "build out\\out1: cat src\\in1\n"
612 "build out\\out2/out3\\out4: cat mid1\n"
613 "build out3 out4\\foo: cat mid1\n"));
616 vector<Node*> root_nodes = state_.RootNodes(&err);
617 EXPECT_EQ(4u, root_nodes.size());
618 EXPECT_EQ(root_nodes[0]->path(),
"out/out1");
619 EXPECT_EQ(root_nodes[1]->path(),
"out/out2/out3/out4");
620 EXPECT_EQ(root_nodes[2]->path(),
"out3");
621 EXPECT_EQ(root_nodes[3]->path(),
"out4/foo");
622 EXPECT_EQ(root_nodes[0]->PathDecanonicalized(),
"out\\out1");
623 EXPECT_EQ(root_nodes[1]->PathDecanonicalized(),
"out\\out2/out3\\out4");
624 EXPECT_EQ(root_nodes[2]->PathDecanonicalized(),
"out3");
625 EXPECT_EQ(root_nodes[3]->PathDecanonicalized(),
"out4\\foo");
632 " command = unused\n"
633 "build out: r in || dd\n"
637 "ninja_dyndep_version = 1\n"
638 "build out: dyndep\n"
642 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
643 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
645 EXPECT_FALSE(GetNode(
"dd")->dyndep_pending());
647 Edge* edge = GetNode(
"out")->in_edge();
648 ASSERT_EQ(
size_t(1), edge->
outputs_.size());
649 EXPECT_EQ(
"out", edge->
outputs_[0]->path());
650 ASSERT_EQ(
size_t(2), edge->
inputs_.size());
651 EXPECT_EQ(
"in", edge->
inputs_[0]->path());
652 EXPECT_EQ(
"dd", edge->
inputs_[1]->path());
661 " command = unused\n"
662 "build out1: r in || dd\n"
667 "ninja_dyndep_version = 1\n"
668 "build out1: dyndep | out2\n"
672 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
673 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
675 EXPECT_FALSE(GetNode(
"dd")->dyndep_pending());
677 Edge* edge = GetNode(
"out1")->in_edge();
678 ASSERT_EQ(
size_t(1), edge->
outputs_.size());
679 EXPECT_EQ(
"out1", edge->
outputs_[0]->path());
680 ASSERT_EQ(
size_t(3), edge->
inputs_.size());
681 EXPECT_EQ(
"in", edge->
inputs_[0]->path());
682 EXPECT_EQ(
"out2", edge->
inputs_[1]->path());
683 EXPECT_EQ(
"dd", edge->
inputs_[2]->path());
692 " command = unused\n"
693 "build out: r in || dd\n"
698 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
699 EXPECT_FALSE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
700 EXPECT_EQ(
"loading 'dd': No such file or directory", err);
706 " command = unused\n"
707 "build out: r in || dd\n"
711 "ninja_dyndep_version = 1\n"
715 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
716 EXPECT_FALSE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
717 EXPECT_EQ(
"'out' not mentioned in its dyndep file 'dd'", err);
723 " command = unused\n"
724 "build out: r in || dd\n"
726 "build out2: r in || dd\n"
729 "ninja_dyndep_version = 1\n"
730 "build out: dyndep\n"
731 "build out2: dyndep\n"
735 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
736 EXPECT_FALSE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
737 EXPECT_EQ(
"dyndep file 'dd' mentions output 'out2' whose build statement "
738 "does not have a dyndep binding for the file", err);
744 " command = unused\n"
745 "build out1 | out-twice.imp: r in1\n"
746 "build out2: r in2 || dd\n"
750 "ninja_dyndep_version = 1\n"
751 "build out2 | out-twice.imp: dyndep\n"
755 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
756 EXPECT_FALSE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
757 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
763 " command = unused\n"
764 "build out1: r in1 || dd1\n"
766 "build out2: r in2 || dd2\n"
770 "ninja_dyndep_version = 1\n"
771 "build out1 | out-twice.imp: dyndep\n"
774 "ninja_dyndep_version = 1\n"
775 "build out2 | out-twice.imp: dyndep\n"
779 ASSERT_TRUE(GetNode(
"dd1")->dyndep_pending());
780 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd1"), &err));
782 ASSERT_TRUE(GetNode(
"dd2")->dyndep_pending());
783 EXPECT_FALSE(scan_.LoadDyndeps(GetNode(
"dd2"), &err));
784 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
790 " command = unused\n"
791 "build out1: r in1 || dd\n"
793 "build out2: r in2 || dd\n"
795 "build outNot: r in3 || dd\n"
798 "ninja_dyndep_version = 1\n"
799 "build out1 | out1imp: dyndep | in1imp\n"
800 "build out2: dyndep | in2imp\n"
805 ASSERT_TRUE(GetNode(
"dd")->dyndep_pending());
806 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
808 EXPECT_FALSE(GetNode(
"dd")->dyndep_pending());
810 Edge* edge1 = GetNode(
"out1")->in_edge();
811 ASSERT_EQ(
size_t(2), edge1->
outputs_.size());
812 EXPECT_EQ(
"out1", edge1->
outputs_[0]->path());
813 EXPECT_EQ(
"out1imp", edge1->
outputs_[1]->path());
815 ASSERT_EQ(
size_t(3), edge1->
inputs_.size());
816 EXPECT_EQ(
"in1", edge1->
inputs_[0]->path());
817 EXPECT_EQ(
"in1imp", edge1->
inputs_[1]->path());
818 EXPECT_EQ(
"dd", edge1->
inputs_[2]->path());
822 EXPECT_EQ(edge1, GetNode(
"out1imp")->in_edge());
823 Node* in1imp = GetNode(
"in1imp");
824 ASSERT_EQ(
size_t(1), in1imp->
out_edges().size());
825 EXPECT_EQ(edge1, in1imp->
out_edges()[0]);
827 Edge* edge2 = GetNode(
"out2")->in_edge();
828 ASSERT_EQ(
size_t(1), edge2->
outputs_.size());
829 EXPECT_EQ(
"out2", edge2->
outputs_[0]->path());
831 ASSERT_EQ(
size_t(3), edge2->
inputs_.size());
832 EXPECT_EQ(
"in2", edge2->
inputs_[0]->path());
833 EXPECT_EQ(
"in2imp", edge2->
inputs_[1]->path());
834 EXPECT_EQ(
"dd", edge2->
inputs_[2]->path());
838 Node* in2imp = GetNode(
"in2imp");
839 ASSERT_EQ(
size_t(1), in2imp->
out_edges().size());
840 EXPECT_EQ(edge2, in2imp->
out_edges()[0]);
846 " command = unused\n"
847 "build out: r || dd\n"
852 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
853 ASSERT_EQ(
"loading 'dd': No such file or directory", err);
859 " command = unused\n"
860 "build out: r || dd\n"
864 "ninja_dyndep_version = 1\n"
868 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
869 ASSERT_EQ(
"'out' not mentioned in its dyndep file 'dd'", err);
875 " command = unused\n"
876 "build out: r || dd\n"
880 "ninja_dyndep_version = 1\n"
881 "build out: dyndep | in\n"
883 fs_.Create(
"out",
"");
885 fs_.Create(
"in",
"");
888 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
891 EXPECT_FALSE(GetNode(
"in")->dirty());
892 EXPECT_FALSE(GetNode(
"dd")->dirty());
895 EXPECT_TRUE(GetNode(
"out")->dirty());
901 " command = unused\n"
902 "build dd: r dd-in\n"
903 "build out: r || dd\n"
906 fs_.Create(
"dd-in",
"");
908 "ninja_dyndep_version = 1\n"
909 "build out: dyndep | in\n"
911 fs_.Create(
"out",
"");
913 fs_.Create(
"in",
"");
916 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
919 EXPECT_FALSE(GetNode(
"in")->dirty());
920 EXPECT_FALSE(GetNode(
"dd")->dirty());
921 EXPECT_TRUE(GetNode(
"dd")->in_edge()->outputs_ready());
924 EXPECT_TRUE(GetNode(
"out")->dirty());
930 " command = unused\n"
931 "build dd: r dd-in\n"
932 "build out: r || dd\n"
935 fs_.Create(
"dd",
"this-should-not-be-loaded");
937 fs_.Create(
"dd-in",
"");
938 fs_.Create(
"out",
"");
941 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
944 EXPECT_TRUE(GetNode(
"dd")->dirty());
945 EXPECT_FALSE(GetNode(
"dd")->in_edge()->outputs_ready());
948 EXPECT_FALSE(GetNode(
"out")->dirty());
949 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
955 " command = unused\n"
957 "build dd: r dd-in || tmp\n"
958 "build out: r || dd\n"
961 fs_.Create(
"dd",
"this-should-not-be-loaded");
962 fs_.Create(
"dd-in",
"");
964 fs_.Create(
"out",
"");
967 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
970 EXPECT_FALSE(GetNode(
"dd")->dirty());
971 EXPECT_FALSE(GetNode(
"dd")->in_edge()->outputs_ready());
972 EXPECT_FALSE(GetNode(
"out")->dirty());
973 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
979 " command = unused\n"
980 "build dd1: r dd1-in\n"
981 "build dd2-in: r || dd1\n"
983 "build dd2: r dd2-in\n"
984 "build out: r || dd2\n"
987 fs_.Create(
"dd1",
"");
988 fs_.Create(
"dd2",
"");
989 fs_.Create(
"dd2-in",
"");
991 fs_.Create(
"dd1-in",
"");
992 fs_.Create(
"out",
"");
995 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
998 EXPECT_TRUE(GetNode(
"dd1")->dirty());
999 EXPECT_FALSE(GetNode(
"dd1")->in_edge()->outputs_ready());
1000 EXPECT_FALSE(GetNode(
"dd2")->dirty());
1001 EXPECT_FALSE(GetNode(
"dd2")->in_edge()->outputs_ready());
1002 EXPECT_FALSE(GetNode(
"out")->dirty());
1003 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
1009 " command = unused\n"
1010 "build out: r in || dd\n"
1011 " depfile = out.d\n"
1013 "build in: r circ\n"
1015 fs_.Create(
"out.d",
"out: inimp\n");
1017 "ninja_dyndep_version = 1\n"
1018 "build out | circ: dyndep\n"
1020 fs_.Create(
"out",
"");
1022 Edge* edge = GetNode(
"out")->in_edge();
1024 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), NULL, &err));
1025 EXPECT_EQ(
"dependency cycle: circ -> in -> circ", err);
1029 ASSERT_EQ(
size_t(3), edge->
inputs_.size());
1030 EXPECT_EQ(
"in", edge->
inputs_[0]->path());
1031 EXPECT_EQ(
"inimp", edge->
inputs_[1]->path());
1032 EXPECT_EQ(
"dd", edge->
inputs_[2]->path());
1039 "build out: cat in |@ validate\n"
1040 "build validate: cat in\n"));
1042 fs_.Create(
"in",
"");
1044 std::vector<Node*> validation_nodes;
1045 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &validation_nodes, &err));
1048 ASSERT_EQ(validation_nodes.size(),
size_t(1));
1049 EXPECT_EQ(validation_nodes[0]->path(),
"validate");
1051 EXPECT_TRUE(GetNode(
"out")->dirty());
1052 EXPECT_TRUE(GetNode(
"validate")->dirty());
1060 " command = touch $out\n"
1061 "build in_ph: phony in1\n"
1062 "build out1: touch in_ph\n"
1064 fs_.Create(
"in1",
"");
1065 fs_.Create(
"out1",
"");
1066 Node* out1 = GetNode(
"out1");
1067 Node* in1 = GetNode(
"in1");
1069 EXPECT_TRUE(scan_.RecomputeDirty(out1, NULL, &err));
1070 EXPECT_TRUE(!out1->
dirty());
1073 ASSERT_TRUE(in1->
Stat(&fs_, &err));
1074 ASSERT_TRUE(out1->
Stat(&fs_, &err));
1081 fs_.Create(
"in1",
"");
1083 ASSERT_TRUE(in1->
Stat(&fs_, &err));
1084 EXPECT_GT(in1->
mtime(), in1Mtime1);
1086 EXPECT_TRUE(scan_.RecomputeDirty(out1, NULL, &err));
1087 EXPECT_GT(in1->
mtime(), in1Mtime1);
1088 EXPECT_EQ(out1->
mtime(), out1Mtime1);
1089 EXPECT_TRUE(out1->
dirty());
1097 " command = unused\n"
1098 "build out1: r in1\n"
1099 "build out2: r in2\n"
1100 "build out3: r in3\n"
1103 const int n_edges = 3;
1104 Edge *(edges)[n_edges] = {
1105 GetNode(
"out1")->in_edge(),
1106 GetNode(
"out2")->in_edge(),
1107 GetNode(
"out3")->in_edge(),
1111 for (
int i = 0; i < n_edges; ++i) {
1116 for (
int i = 0; i < n_edges; ++i) {
1117 queue.push(edges[i]);
1120 EXPECT_EQ(queue.size(),
static_cast<size_t>(n_edges));
1121 for (
int i = 0; i < n_edges; ++i) {
1122 EXPECT_EQ(queue.top(), edges[n_edges - 1 - i]);
1125 EXPECT_TRUE(queue.empty());
1128 for (
int i = 0; i < n_edges; ++i) {
1129 edges[i]->set_critical_path_weight(0);
1132 queue.push(edges[1]);
1133 queue.push(edges[2]);
1134 queue.push(edges[0]);
1136 for (
int i = 0; i < n_edges; ++i) {
1137 EXPECT_EQ(queue.top(), edges[i]);
1140 EXPECT_TRUE(queue.empty());
TEST_F(GraphTest, MissingImplicit)
Collects the transitive set of edges that lead into a given set of starting nodes.
std::vector< Edge * > in_edges
we use a vector to preserve order from requisites to their dependents.
void CollectFrom(const Node *node)
DependencyScan manages the process of scanning the files in a graph and updating the dirty/outputs_re...
An edge in the dependency graph; links between Nodes using Rules.
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
std::vector< Node * > outputs_
void set_critical_path_weight(int64_t critical_path_weight)
bool GetBindingBool(const std::string &key) const
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
std::vector< Node * > inputs_
PhonyCycleAction phony_cycle_action_
Information about a node in the dependency graph: the file, whether it's dirty, mtime,...
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
const std::vector< Edge * > & out_edges() const
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute.
int command_edge_count() const
Number of edges with commands to run.
bool AddTarget(const Node *target, std::string *err)
Add a target to our plan (including all its dependencies).
bool more_to_do() const
Returns true if there's more work to be done.
A base test fixture that includes a State object with a builtin "cat" rule.
An implementation of DiskInterface that uses an in-memory representation of disk state.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)