Fix for missing "no work to do." message if all build edges are phony rules.
[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, PathWithCurrentDirectory) {
109   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
110 "rule catdep\n"
111 "  depfile = $out.d\n"
112 "  command = cat $in > $out\n"
113 "build ./out.o: catdep ./foo.cc\n"));
114   fs_.Create("foo.cc", "");
115   fs_.Create("out.o.d", "out.o: foo.cc\n");
116   fs_.Create("out.o", "");
117
118   Edge* edge = GetNode("out.o")->in_edge();
119   string err;
120   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
121   ASSERT_EQ("", err);
122
123   EXPECT_FALSE(GetNode("out.o")->dirty());
124 }
125
126 TEST_F(GraphTest, RootNodes) {
127   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
128 "build out1: cat in1\n"
129 "build mid1: cat in1\n"
130 "build out2: cat mid1\n"
131 "build out3 out4: cat mid1\n"));
132
133   string err;
134   vector<Node*> root_nodes = state_.RootNodes(&err);
135   EXPECT_EQ(4u, root_nodes.size());
136   for (size_t i = 0; i < root_nodes.size(); ++i) {
137     string name = root_nodes[i]->path();
138     EXPECT_EQ("out", name.substr(0, 3));
139   }
140 }
141
142 TEST_F(GraphTest, VarInOutQuoteSpaces) {
143   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
144 "build a$ b: cat nospace with$ space nospace2\n"));
145
146   Edge* edge = GetNode("a b")->in_edge();
147   EXPECT_EQ("cat nospace \"with space\" nospace2 > \"a b\"",
148       edge->EvaluateCommand());
149 }
150
151 // Regression test for https://github.com/martine/ninja/issues/380
152 TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
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: bar/../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 // Regression test for https://github.com/martine/ninja/issues/404
171 TEST_F(GraphTest, DepfileRemoved) {
172   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
173 "rule catdep\n"
174 "  depfile = $out.d\n"
175 "  command = cat $in > $out\n"
176 "build ./out.o: catdep ./foo.cc\n"));
177   fs_.Create("foo.h", "");
178   fs_.Create("foo.cc", "");
179   fs_.Tick();
180   fs_.Create("out.o.d", "out.o: foo.h\n");
181   fs_.Create("out.o", "");
182
183   Edge* edge = GetNode("out.o")->in_edge();
184   string err;
185   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
186   ASSERT_EQ("", err);
187   EXPECT_FALSE(GetNode("out.o")->dirty());
188
189   state_.Reset();
190   fs_.RemoveFile("out.o.d");
191   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
192   ASSERT_EQ("", err);
193   EXPECT_TRUE(GetNode("out.o")->dirty());
194 }
195
196 // Check that rule-level variables are in scope for eval.
197 TEST_F(GraphTest, RuleVariablesInScope) {
198   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
199 "rule r\n"
200 "  depfile = x\n"
201 "  command = depfile is $depfile\n"
202 "build out: r in\n"));
203   Edge* edge = GetNode("out")->in_edge();
204   EXPECT_EQ("depfile is x", edge->EvaluateCommand());
205 }
206
207 // Check that build statements can override rule builtins like depfile.
208 TEST_F(GraphTest, DepfileOverride) {
209   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
210 "rule r\n"
211 "  depfile = x\n"
212 "  command = unused\n"
213 "build out: r in\n"
214 "  depfile = y\n"));
215   Edge* edge = GetNode("out")->in_edge();
216   EXPECT_EQ("y", edge->GetBinding("depfile"));
217 }
218
219 // Check that overridden values show up in expansion of rule-level bindings.
220 TEST_F(GraphTest, DepfileOverrideParent) {
221   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
222 "rule r\n"
223 "  depfile = x\n"
224 "  command = depfile is $depfile\n"
225 "build out: r in\n"
226 "  depfile = y\n"));
227   Edge* edge = GetNode("out")->in_edge();
228   EXPECT_EQ("depfile is y", edge->GetBinding("command"));
229 }
230
231 // Verify that building a nested phony rule prints "no work to do"
232 TEST_F(GraphTest, NestedPhonyPrintsDone) {
233   AssertParse(&state_,
234 "build n1: phony \n"
235 "build n2: phony n1\n"
236   );
237   string err;
238   Edge* edge = GetNode("n2")->in_edge();
239   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
240   ASSERT_EQ("", err);
241
242   Plan plan_;
243   EXPECT_TRUE(plan_.AddTarget(GetNode("n2"), &err));
244   ASSERT_EQ("", err);
245
246   EXPECT_EQ(0, plan_.command_edge_count());
247   ASSERT_FALSE(plan_.more_to_do());
248 }