23 GraphTest() : scan_(&state_, NULL, NULL, &fs_, NULL) {}
31 "build out: cat in | implicit\n"));
33 fs_.Create(
"out",
"");
36 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
47 "build out: cat in | implicit\n"));
49 fs_.Create(
"out",
"");
51 fs_.Create(
"implicit",
"");
54 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
65 " command = cat $in > $out\n" 66 "build out.o: catdep foo.cc\n"));
67 fs_.Create(
"foo.cc",
"");
68 fs_.Create(
"out.o.d",
"out.o: ./foo/../implicit.h\n");
69 fs_.Create(
"out.o",
"");
71 fs_.Create(
"implicit.h",
"");
74 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
86 " command = cat $in > $out\n" 87 "build implicit.h: cat data\n" 88 "build out.o: catdep foo.cc || implicit.h\n"));
89 fs_.Create(
"implicit.h",
"");
90 fs_.Create(
"foo.cc",
"");
91 fs_.Create(
"out.o.d",
"out.o: implicit.h\n");
92 fs_.Create(
"out.o",
"");
94 fs_.Create(
"data",
"");
97 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
108 "build out | out.imp: cat in\n"));
110 Edge* edge = GetNode(
"out")->in_edge();
115 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
120 "build out | out.imp: cat in\n"));
121 fs_.Create(
"in",
"");
122 fs_.Create(
"out",
"");
125 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
134 "build out | out.imp: cat in\n"));
135 fs_.Create(
"out.imp",
"");
137 fs_.Create(
"in",
"");
138 fs_.Create(
"out",
"");
141 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
150 "build | out.imp: cat in\n"));
152 Edge* edge = GetNode(
"out.imp")->in_edge();
156 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
161 "build | out.imp: cat in\n"));
162 fs_.Create(
"in",
"");
165 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), &err));
173 "build | out.imp: cat in\n"));
174 fs_.Create(
"out.imp",
"");
176 fs_.Create(
"in",
"");
179 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), &err));
188 " depfile = $out.d\n" 189 " command = cat $in > $out\n" 190 "build ./out.o: catdep ./foo.cc\n"));
191 fs_.Create(
"foo.cc",
"");
192 fs_.Create(
"out.o.d",
"out.o: foo.cc\n");
193 fs_.Create(
"out.o",
"");
196 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
204 "build out1: cat in1\n" 205 "build mid1: cat in1\n" 206 "build out2: cat mid1\n" 207 "build out3 out4: cat mid1\n"));
210 vector<Node*> root_nodes = state_.RootNodes(&err);
212 for (
size_t i = 0; i < root_nodes.size(); ++i) {
213 string name = root_nodes[i]->path();
220 "build a$ b: cat no'space with$ space$$ no\"space2\n"));
222 Edge* edge = GetNode(
"a b")->in_edge();
224 EXPECT_EQ(
"cat no'space \"with space$\" \"no\\\"space2\" > \"a b\"",
227 EXPECT_EQ(
"cat 'no'\\''space' 'with space$' 'no\"space2' > 'a b'",
236 " depfile = $out.d\n" 237 " command = cat $in > $out\n" 238 "build ./out.o: catdep ./foo.cc\n"));
239 fs_.Create(
"foo.cc",
"");
240 fs_.Create(
"out.o.d",
"out.o: bar/../foo.cc\n");
241 fs_.Create(
"out.o",
"");
244 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
254 " depfile = $out.d\n" 255 " command = cat $in > $out\n" 256 "build ./out.o: catdep ./foo.cc\n"));
257 fs_.Create(
"foo.h",
"");
258 fs_.Create(
"foo.cc",
"");
260 fs_.Create(
"out.o.d",
"out.o: foo.h\n");
261 fs_.Create(
"out.o",
"");
264 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
269 fs_.RemoveFile(
"out.o.d");
270 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
280 " command = depfile is $depfile\n" 281 "build out: r in\n"));
282 Edge* edge = GetNode(
"out")->in_edge();
291 " command = unused\n" 294 Edge* edge = GetNode(
"out")->in_edge();
303 " command = depfile is $depfile\n" 306 Edge* edge = GetNode(
"out")->in_edge();
314 "build n2: phony n1\n" 317 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"n2"), &err));
332 "build a: phony a\n",
337 ASSERT_EQ(
"dependency cycle: a -> a [-w phonycycle=err]", err);
342 "build out: cat mid\n" 343 "build mid: cat in\n" 344 "build in: cat pre\n" 345 "build pre: cat out\n");
348 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), &err));
349 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
355 "build a b: cat a\n");
357 ASSERT_EQ(
"dependency cycle: a -> a", err);
363 "build b a: cat a\n"));
365 ASSERT_EQ(
"dependency cycle: a -> a", err);
372 "build c: cat a\n"));
374 ASSERT_EQ(
"dependency cycle: a -> c -> a", err);
384 "build f: cat e\n"));
386 ASSERT_EQ(
"dependency cycle: a -> d -> c -> b -> a", err);
395 " command = unused\n" 396 "build a b: deprule\n" 398 fs_.Create(
"dep.d",
"a: b\n");
402 ASSERT_EQ(
"dependency cycle: b -> b", err);
407 Edge* edge = GetNode(
"a")->in_edge();
417 " command = unused\n" 419 " command = unused\n" 420 "build a b: deprule\n" 423 fs_.Create(
"dep.d",
"a: c\n");
427 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
432 Edge* edge = GetNode(
"a")->in_edge();
443 " command = unused\n" 445 " command = unused\n" 446 "build a b: deprule\n" 450 fs_.Create(
"dep.d",
"a: c\n");
454 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
459 Edge* edge = GetNode(
"a")->in_edge();
467 "build out\\out1: cat src\\in1\n" 468 "build out\\out2/out3\\out4: cat mid1\n" 469 "build out3 out4\\foo: cat mid1\n"));
472 vector<Node*> root_nodes = state_.RootNodes(&err);
474 EXPECT_EQ(root_nodes[0]->path(),
"out/out1");
475 EXPECT_EQ(root_nodes[1]->path(),
"out/out2/out3/out4");
476 EXPECT_EQ(root_nodes[2]->path(),
"out3");
477 EXPECT_EQ(root_nodes[3]->path(),
"out4/foo");
478 EXPECT_EQ(root_nodes[0]->PathDecanonicalized(),
"out\\out1");
479 EXPECT_EQ(root_nodes[1]->PathDecanonicalized(),
"out\\out2/out3\\out4");
480 EXPECT_EQ(root_nodes[2]->PathDecanonicalized(),
"out3");
481 EXPECT_EQ(root_nodes[3]->PathDecanonicalized(),
"out4\\foo");
488 " command = unused\n" 489 "build out: r in || dd\n" 493 "ninja_dyndep_version = 1\n" 494 "build out: dyndep\n" 499 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
503 Edge* edge = GetNode(
"out")->in_edge();
517 " command = unused\n" 518 "build out: r in || dd\n" 525 EXPECT_EQ(
"loading 'dd': No such file or directory", err);
531 " command = unused\n" 532 "build out: r in || dd\n" 536 "ninja_dyndep_version = 1\n" 542 EXPECT_EQ(
"'out' not mentioned in its dyndep file 'dd'", err);
548 " command = unused\n" 549 "build out: r in || dd\n" 551 "build out2: r in || dd\n" 554 "ninja_dyndep_version = 1\n" 555 "build out: dyndep\n" 556 "build out2: dyndep\n" 562 EXPECT_EQ(
"dyndep file 'dd' mentions output 'out2' whose build statement " 563 "does not have a dyndep binding for the file", err);
569 " command = unused\n" 570 "build out1 | out-twice.imp: r in1\n" 571 "build out2: r in2 || dd\n" 575 "ninja_dyndep_version = 1\n" 576 "build out2 | out-twice.imp: dyndep\n" 582 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
588 " command = unused\n" 589 "build out1: r in1 || dd1\n" 591 "build out2: r in2 || dd2\n" 595 "ninja_dyndep_version = 1\n" 596 "build out1 | out-twice.imp: dyndep\n" 599 "ninja_dyndep_version = 1\n" 600 "build out2 | out-twice.imp: dyndep\n" 605 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd1"), &err));
609 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
615 " command = unused\n" 616 "build out1: r in1 || dd\n" 618 "build out2: r in2 || dd\n" 620 "build outNot: r in3 || dd\n" 623 "ninja_dyndep_version = 1\n" 624 "build out1 | out1imp: dyndep | in1imp\n" 625 "build out2: dyndep | in2imp\n" 631 EXPECT_TRUE(scan_.LoadDyndeps(GetNode(
"dd"), &err));
635 Edge* edge1 = GetNode(
"out1")->in_edge();
647 EXPECT_EQ(edge1, GetNode(
"out1imp")->in_edge());
648 Node* in1imp = GetNode(
"in1imp");
652 Edge* edge2 = GetNode(
"out2")->in_edge();
654 EXPECT_EQ(
"out2", edge2->outputs_[0]->path());
657 EXPECT_EQ(
"in2", edge2->inputs_[0]->path());
658 EXPECT_EQ(
"in2imp", edge2->inputs_[1]->path());
659 EXPECT_EQ(
"dd", edge2->inputs_[2]->path());
663 Node* in2imp = GetNode(
"in2imp");
664 ASSERT_EQ(1u, in2imp->out_edges().size());
665 EXPECT_EQ(edge2, in2imp->out_edges()[0]);
671 " command = unused\n" 672 "build out: r || dd\n" 677 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), &err));
678 ASSERT_EQ(
"loading 'dd': No such file or directory", err);
684 " command = unused\n" 685 "build out: r || dd\n" 689 "ninja_dyndep_version = 1\n" 693 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), &err));
694 ASSERT_EQ(
"'out' not mentioned in its dyndep file 'dd'", err);
700 " command = unused\n" 701 "build out: r || dd\n" 705 "ninja_dyndep_version = 1\n" 706 "build out: dyndep | in\n" 708 fs_.Create(
"out",
"");
710 fs_.Create(
"in",
"");
713 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
726 " command = unused\n" 727 "build dd: r dd-in\n" 728 "build out: r || dd\n" 731 fs_.Create(
"dd-in",
"");
733 "ninja_dyndep_version = 1\n" 734 "build out: dyndep | in\n" 736 fs_.Create(
"out",
"");
738 fs_.Create(
"in",
"");
741 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
746 EXPECT_TRUE(GetNode(
"dd")->in_edge()->outputs_ready());
755 " command = unused\n" 756 "build dd: r dd-in\n" 757 "build out: r || dd\n" 760 fs_.Create(
"dd",
"this-should-not-be-loaded");
762 fs_.Create(
"dd-in",
"");
763 fs_.Create(
"out",
"");
766 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
770 EXPECT_FALSE(GetNode(
"dd")->in_edge()->outputs_ready());
774 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
780 " command = unused\n" 782 "build dd: r dd-in || tmp\n" 783 "build out: r || dd\n" 786 fs_.Create(
"dd",
"this-should-not-be-loaded");
787 fs_.Create(
"dd-in",
"");
789 fs_.Create(
"out",
"");
792 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
796 EXPECT_FALSE(GetNode(
"dd")->in_edge()->outputs_ready());
798 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
804 " command = unused\n" 805 "build dd1: r dd1-in\n" 806 "build dd2-in: r || dd1\n" 808 "build dd2: r dd2-in\n" 809 "build out: r || dd2\n" 812 fs_.Create(
"dd1",
"");
813 fs_.Create(
"dd2",
"");
814 fs_.Create(
"dd2-in",
"");
816 fs_.Create(
"dd1-in",
"");
817 fs_.Create(
"out",
"");
820 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
824 EXPECT_FALSE(GetNode(
"dd1")->in_edge()->outputs_ready());
826 EXPECT_FALSE(GetNode(
"dd2")->in_edge()->outputs_ready());
828 EXPECT_FALSE(GetNode(
"out")->in_edge()->outputs_ready());
834 " command = unused\n" 835 "build out: r in || dd\n" 840 fs_.Create(
"out.d",
"out: inimp\n");
842 "ninja_dyndep_version = 1\n" 843 "build out | circ: dyndep\n" 845 fs_.Create(
"out",
"");
847 Edge* edge = GetNode(
"out")->in_edge();
849 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), &err));
850 EXPECT_EQ(
"dependency cycle: circ -> in -> circ", err);
An implementation of DiskInterface that uses an in-memory representation of disk state.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute...
PhonyCycleAction phony_cycle_action_
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
std::vector< Node * > outputs_
int command_edge_count() const
Number of edges with commands to run.
An edge in the dependency graph; links between Nodes using Rules.
A base test fixture that includes a State object with a builtin "cat" rule.
bool AddTarget(const Node *node, std::string *err)
Add a target to our plan (including all its dependencies).
std::vector< Node * > inputs_
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
DependencyScan manages the process of scanning the files in a graph and updating the dirty/outputs_re...
#define ASSERT_NO_FATAL_FAILURE(a)
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
const std::vector< Edge * > & out_edges() const
bool more_to_do() const
Returns true if there's more work to be done.
bool GetBindingBool(const std::string &key) const
TEST_F(GraphTest, MissingImplicit)