Imported Upstream version 1.7.1
[platform/upstream/ninja.git] / src / graph_test.cc
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "graph.h"
16 #include "build.h"
17
18 #include "test.h"
19
20 struct GraphTest : public StateTestWithBuiltinRules {
21   GraphTest() : scan_(&state_, NULL, NULL, &fs_) {}
22
23   VirtualFileSystem fs_;
24   DependencyScan scan_;
25 };
26
27 TEST_F(GraphTest, MissingImplicit) {
28   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
29 "build out: cat in | implicit\n"));
30   fs_.Create("in", "");
31   fs_.Create("out", "");
32
33   Edge* edge = GetNode("out")->in_edge();
34   string err;
35   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
36   ASSERT_EQ("", err);
37
38   // A missing implicit dep *should* make the output dirty.
39   // (In fact, a build will fail.)
40   // This is a change from prior semantics of ninja.
41   EXPECT_TRUE(GetNode("out")->dirty());
42 }
43
44 TEST_F(GraphTest, ModifiedImplicit) {
45   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
46 "build out: cat in | implicit\n"));
47   fs_.Create("in", "");
48   fs_.Create("out", "");
49   fs_.Tick();
50   fs_.Create("implicit", "");
51
52   Edge* edge = GetNode("out")->in_edge();
53   string err;
54   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
55   ASSERT_EQ("", err);
56
57   // A modified implicit dep should make the output dirty.
58   EXPECT_TRUE(GetNode("out")->dirty());
59 }
60
61 TEST_F(GraphTest, FunkyMakefilePath) {
62   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
63 "rule catdep\n"
64 "  depfile = $out.d\n"
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", "");
70   fs_.Tick();
71   fs_.Create("implicit.h", "");
72
73   Edge* edge = GetNode("out.o")->in_edge();
74   string err;
75   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
76   ASSERT_EQ("", err);
77
78   // implicit.h has changed, though our depfile refers to it with a
79   // non-canonical path; we should still find it.
80   EXPECT_TRUE(GetNode("out.o")->dirty());
81 }
82
83 TEST_F(GraphTest, ExplicitImplicit) {
84   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
85 "rule catdep\n"
86 "  depfile = $out.d\n"
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", "");
94   fs_.Tick();
95   fs_.Create("data", "");
96
97   Edge* edge = GetNode("out.o")->in_edge();
98   string err;
99   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
100   ASSERT_EQ("", err);
101
102   // We have both an implicit and an explicit dep on implicit.h.
103   // The implicit dep should "win" (in the sense that it should cause
104   // the output to be dirty).
105   EXPECT_TRUE(GetNode("out.o")->dirty());
106 }
107
108 TEST_F(GraphTest, ImplicitOutputParse) {
109   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
110 "build out | out.imp: cat in\n"));
111
112   Edge* edge = GetNode("out")->in_edge();
113   EXPECT_EQ(2, edge->outputs_.size());
114   EXPECT_EQ("out", edge->outputs_[0]->path());
115   EXPECT_EQ("out.imp", edge->outputs_[1]->path());
116   EXPECT_EQ(1, edge->implicit_outs_);
117   EXPECT_EQ(edge, GetNode("out.imp")->in_edge());
118 }
119
120 TEST_F(GraphTest, ImplicitOutputMissing) {
121   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
122 "build out | out.imp: cat in\n"));
123   fs_.Create("in", "");
124   fs_.Create("out", "");
125
126   Edge* edge = GetNode("out")->in_edge();
127   string err;
128   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
129   ASSERT_EQ("", err);
130
131   EXPECT_TRUE(GetNode("out")->dirty());
132   EXPECT_TRUE(GetNode("out.imp")->dirty());
133 }
134
135 TEST_F(GraphTest, ImplicitOutputOutOfDate) {
136   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
137 "build out | out.imp: cat in\n"));
138   fs_.Create("out.imp", "");
139   fs_.Tick();
140   fs_.Create("in", "");
141   fs_.Create("out", "");
142
143   Edge* edge = GetNode("out")->in_edge();
144   string err;
145   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
146   ASSERT_EQ("", err);
147
148   EXPECT_TRUE(GetNode("out")->dirty());
149   EXPECT_TRUE(GetNode("out.imp")->dirty());
150 }
151
152 TEST_F(GraphTest, PathWithCurrentDirectory) {
153   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
154 "rule catdep\n"
155 "  depfile = $out.d\n"
156 "  command = cat $in > $out\n"
157 "build ./out.o: catdep ./foo.cc\n"));
158   fs_.Create("foo.cc", "");
159   fs_.Create("out.o.d", "out.o: foo.cc\n");
160   fs_.Create("out.o", "");
161
162   Edge* edge = GetNode("out.o")->in_edge();
163   string err;
164   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
165   ASSERT_EQ("", err);
166
167   EXPECT_FALSE(GetNode("out.o")->dirty());
168 }
169
170 TEST_F(GraphTest, RootNodes) {
171   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
172 "build out1: cat in1\n"
173 "build mid1: cat in1\n"
174 "build out2: cat mid1\n"
175 "build out3 out4: cat mid1\n"));
176
177   string err;
178   vector<Node*> root_nodes = state_.RootNodes(&err);
179   EXPECT_EQ(4u, root_nodes.size());
180   for (size_t i = 0; i < root_nodes.size(); ++i) {
181     string name = root_nodes[i]->path();
182     EXPECT_EQ("out", name.substr(0, 3));
183   }
184 }
185
186 TEST_F(GraphTest, VarInOutPathEscaping) {
187   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
188 "build a$ b: cat no'space with$ space$$ no\"space2\n"));
189
190   Edge* edge = GetNode("a b")->in_edge();
191 #if _WIN32
192   EXPECT_EQ("cat no'space \"with space$\" \"no\\\"space2\" > \"a b\"",
193       edge->EvaluateCommand());
194 #else
195   EXPECT_EQ("cat 'no'\\''space' 'with space$' 'no\"space2' > 'a b'",
196       edge->EvaluateCommand());
197 #endif
198 }
199
200 // Regression test for https://github.com/ninja-build/ninja/issues/380
201 TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
202   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
203 "rule catdep\n"
204 "  depfile = $out.d\n"
205 "  command = cat $in > $out\n"
206 "build ./out.o: catdep ./foo.cc\n"));
207   fs_.Create("foo.cc", "");
208   fs_.Create("out.o.d", "out.o: bar/../foo.cc\n");
209   fs_.Create("out.o", "");
210
211   Edge* edge = GetNode("out.o")->in_edge();
212   string err;
213   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
214   ASSERT_EQ("", err);
215
216   EXPECT_FALSE(GetNode("out.o")->dirty());
217 }
218
219 // Regression test for https://github.com/ninja-build/ninja/issues/404
220 TEST_F(GraphTest, DepfileRemoved) {
221   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
222 "rule catdep\n"
223 "  depfile = $out.d\n"
224 "  command = cat $in > $out\n"
225 "build ./out.o: catdep ./foo.cc\n"));
226   fs_.Create("foo.h", "");
227   fs_.Create("foo.cc", "");
228   fs_.Tick();
229   fs_.Create("out.o.d", "out.o: foo.h\n");
230   fs_.Create("out.o", "");
231
232   Edge* edge = GetNode("out.o")->in_edge();
233   string err;
234   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
235   ASSERT_EQ("", err);
236   EXPECT_FALSE(GetNode("out.o")->dirty());
237
238   state_.Reset();
239   fs_.RemoveFile("out.o.d");
240   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
241   ASSERT_EQ("", err);
242   EXPECT_TRUE(GetNode("out.o")->dirty());
243 }
244
245 // Check that rule-level variables are in scope for eval.
246 TEST_F(GraphTest, RuleVariablesInScope) {
247   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
248 "rule r\n"
249 "  depfile = x\n"
250 "  command = depfile is $depfile\n"
251 "build out: r in\n"));
252   Edge* edge = GetNode("out")->in_edge();
253   EXPECT_EQ("depfile is x", edge->EvaluateCommand());
254 }
255
256 // Check that build statements can override rule builtins like depfile.
257 TEST_F(GraphTest, DepfileOverride) {
258   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
259 "rule r\n"
260 "  depfile = x\n"
261 "  command = unused\n"
262 "build out: r in\n"
263 "  depfile = y\n"));
264   Edge* edge = GetNode("out")->in_edge();
265   EXPECT_EQ("y", edge->GetBinding("depfile"));
266 }
267
268 // Check that overridden values show up in expansion of rule-level bindings.
269 TEST_F(GraphTest, DepfileOverrideParent) {
270   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
271 "rule r\n"
272 "  depfile = x\n"
273 "  command = depfile is $depfile\n"
274 "build out: r in\n"
275 "  depfile = y\n"));
276   Edge* edge = GetNode("out")->in_edge();
277   EXPECT_EQ("depfile is y", edge->GetBinding("command"));
278 }
279
280 // Verify that building a nested phony rule prints "no work to do"
281 TEST_F(GraphTest, NestedPhonyPrintsDone) {
282   AssertParse(&state_,
283 "build n1: phony \n"
284 "build n2: phony n1\n"
285   );
286   string err;
287   Edge* edge = GetNode("n2")->in_edge();
288   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
289   ASSERT_EQ("", err);
290
291   Plan plan_;
292   EXPECT_TRUE(plan_.AddTarget(GetNode("n2"), &err));
293   ASSERT_EQ("", err);
294
295   EXPECT_EQ(0, plan_.command_edge_count());
296   ASSERT_FALSE(plan_.more_to_do());
297 }
298
299 // Verify that cycles in graphs with multiple outputs are handled correctly
300 // in RecomputeDirty() and don't cause deps to be loaded multiple times.
301 TEST_F(GraphTest, CycleWithLengthZeroFromDepfile) {
302   AssertParse(&state_,
303 "rule deprule\n"
304 "   depfile = dep.d\n"
305 "   command = unused\n"
306 "build a b: deprule\n"
307   );
308   fs_.Create("dep.d", "a: b\n");
309
310   string err;
311   Edge* edge = GetNode("a")->in_edge();
312   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
313   ASSERT_EQ("", err);
314
315   // Despite the depfile causing edge to be a cycle (it has outputs a and b,
316   // but the depfile also adds b as an input), the deps should have been loaded
317   // only once:
318   EXPECT_EQ(1, edge->inputs_.size());
319   EXPECT_EQ("b", edge->inputs_[0]->path());
320 }
321
322 // Like CycleWithLengthZeroFromDepfile but with a higher cycle length.
323 TEST_F(GraphTest, CycleWithLengthOneFromDepfile) {
324   AssertParse(&state_,
325 "rule deprule\n"
326 "   depfile = dep.d\n"
327 "   command = unused\n"
328 "rule r\n"
329 "   command = unused\n"
330 "build a b: deprule\n"
331 "build c: r b\n"
332   );
333   fs_.Create("dep.d", "a: c\n");
334
335   string err;
336   Edge* edge = GetNode("a")->in_edge();
337   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
338   ASSERT_EQ("", err);
339
340   // Despite the depfile causing edge to be a cycle (|edge| has outputs a and b,
341   // but c's in_edge has b as input but the depfile also adds |edge| as
342   // output)), the deps should have been loaded only once:
343   EXPECT_EQ(1, edge->inputs_.size());
344   EXPECT_EQ("c", edge->inputs_[0]->path());
345 }
346
347 // Like CycleWithLengthOneFromDepfile but building a node one hop away from
348 // the cycle.
349 TEST_F(GraphTest, CycleWithLengthOneFromDepfileOneHopAway) {
350   AssertParse(&state_,
351 "rule deprule\n"
352 "   depfile = dep.d\n"
353 "   command = unused\n"
354 "rule r\n"
355 "   command = unused\n"
356 "build a b: deprule\n"
357 "build c: r b\n"
358 "build d: r a\n"
359   );
360   fs_.Create("dep.d", "a: c\n");
361
362   string err;
363   EXPECT_TRUE(scan_.RecomputeDirty(GetNode("d")->in_edge(), &err));
364   ASSERT_EQ("", err);
365
366   // Despite the depfile causing edge to be a cycle (|edge| has outputs a and b,
367   // but c's in_edge has b as input but the depfile also adds |edge| as
368   // output)), the deps should have been loaded only once:
369   Edge* edge = GetNode("a")->in_edge();
370   EXPECT_EQ(1, edge->inputs_.size());
371   EXPECT_EQ("c", edge->inputs_[0]->path());
372 }
373
374 #ifdef _WIN32
375 TEST_F(GraphTest, Decanonicalize) {
376   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
377 "build out\\out1: cat src\\in1\n"
378 "build out\\out2/out3\\out4: cat mid1\n"
379 "build out3 out4\\foo: cat mid1\n"));
380
381   string err;
382   vector<Node*> root_nodes = state_.RootNodes(&err);
383   EXPECT_EQ(4u, root_nodes.size());
384   EXPECT_EQ(root_nodes[0]->path(), "out/out1");
385   EXPECT_EQ(root_nodes[1]->path(), "out/out2/out3/out4");
386   EXPECT_EQ(root_nodes[2]->path(), "out3");
387   EXPECT_EQ(root_nodes[3]->path(), "out4/foo");
388   EXPECT_EQ(root_nodes[0]->PathDecanonicalized(), "out\\out1");
389   EXPECT_EQ(root_nodes[1]->PathDecanonicalized(), "out\\out2/out3\\out4");
390   EXPECT_EQ(root_nodes[2]->PathDecanonicalized(), "out3");
391   EXPECT_EQ(root_nodes[3]->PathDecanonicalized(), "out4\\foo");
392 }
393 #endif