1 // Copyright 2011 Google Inc. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 struct GraphTest : public StateTestWithBuiltinRules {
20 GraphTest() : scan_(&state_, NULL, NULL, &fs_) {}
22 VirtualFileSystem fs_;
26 TEST_F(GraphTest, MissingImplicit) {
27 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
28 "build out: cat in | implicit\n"));
30 fs_.Create("out", "");
32 Edge* edge = GetNode("out")->in_edge();
34 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
37 // A missing implicit dep *should* make the output dirty.
38 // (In fact, a build will fail.)
39 // This is a change from prior semantics of ninja.
40 EXPECT_TRUE(GetNode("out")->dirty());
43 TEST_F(GraphTest, ModifiedImplicit) {
44 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
45 "build out: cat in | implicit\n"));
47 fs_.Create("out", "");
49 fs_.Create("implicit", "");
51 Edge* edge = GetNode("out")->in_edge();
53 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
56 // A modified implicit dep should make the output dirty.
57 EXPECT_TRUE(GetNode("out")->dirty());
60 TEST_F(GraphTest, FunkyMakefilePath) {
61 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
64 " command = cat $in > $out\n"
65 "build out.o: catdep foo.cc\n"));
66 fs_.Create("foo.cc", "");
67 fs_.Create("out.o.d", "out.o: ./foo/../implicit.h\n");
68 fs_.Create("out.o", "");
70 fs_.Create("implicit.h", "");
72 Edge* edge = GetNode("out.o")->in_edge();
74 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
77 // implicit.h has changed, though our depfile refers to it with a
78 // non-canonical path; we should still find it.
79 EXPECT_TRUE(GetNode("out.o")->dirty());
82 TEST_F(GraphTest, ExplicitImplicit) {
83 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
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", "");
96 Edge* edge = GetNode("out.o")->in_edge();
98 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
101 // We have both an implicit and an explicit dep on implicit.h.
102 // The implicit dep should "win" (in the sense that it should cause
103 // the output to be dirty).
104 EXPECT_TRUE(GetNode("out.o")->dirty());
107 TEST_F(GraphTest, PathWithCurrentDirectory) {
108 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
110 " depfile = $out.d\n"
111 " command = cat $in > $out\n"
112 "build ./out.o: catdep ./foo.cc\n"));
113 fs_.Create("foo.cc", "");
114 fs_.Create("out.o.d", "out.o: foo.cc\n");
115 fs_.Create("out.o", "");
117 Edge* edge = GetNode("out.o")->in_edge();
119 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
122 EXPECT_FALSE(GetNode("out.o")->dirty());
125 TEST_F(GraphTest, RootNodes) {
126 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
127 "build out1: cat in1\n"
128 "build mid1: cat in1\n"
129 "build out2: cat mid1\n"
130 "build out3 out4: cat mid1\n"));
133 vector<Node*> root_nodes = state_.RootNodes(&err);
134 EXPECT_EQ(4u, root_nodes.size());
135 for (size_t i = 0; i < root_nodes.size(); ++i) {
136 string name = root_nodes[i]->path();
137 EXPECT_EQ("out", name.substr(0, 3));
141 TEST_F(GraphTest, VarInOutQuoteSpaces) {
142 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
143 "build a$ b: cat nospace with$ space nospace2\n"));
145 Edge* edge = GetNode("a b")->in_edge();
146 EXPECT_EQ("cat nospace \"with space\" nospace2 > \"a b\"",
147 edge->EvaluateCommand());
150 // Regression test for https://github.com/martine/ninja/issues/380
151 TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
152 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
154 " depfile = $out.d\n"
155 " command = cat $in > $out\n"
156 "build ./out.o: catdep ./foo.cc\n"));
157 fs_.Create("foo.cc", "");
158 fs_.Create("out.o.d", "out.o: bar/../foo.cc\n");
159 fs_.Create("out.o", "");
161 Edge* edge = GetNode("out.o")->in_edge();
163 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
166 EXPECT_FALSE(GetNode("out.o")->dirty());
169 // Regression test for https://github.com/martine/ninja/issues/404
170 TEST_F(GraphTest, DepfileRemoved) {
171 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
173 " depfile = $out.d\n"
174 " command = cat $in > $out\n"
175 "build ./out.o: catdep ./foo.cc\n"));
176 fs_.Create("foo.h", "");
177 fs_.Create("foo.cc", "");
179 fs_.Create("out.o.d", "out.o: foo.h\n");
180 fs_.Create("out.o", "");
182 Edge* edge = GetNode("out.o")->in_edge();
184 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
186 EXPECT_FALSE(GetNode("out.o")->dirty());
189 fs_.RemoveFile("out.o.d");
190 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
192 EXPECT_TRUE(GetNode("out.o")->dirty());
195 // Check that rule-level variables are in scope for eval.
196 TEST_F(GraphTest, RuleVariablesInScope) {
197 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
200 " command = depfile is $depfile\n"
201 "build out: r in\n"));
202 Edge* edge = GetNode("out")->in_edge();
203 EXPECT_EQ("depfile is x", edge->EvaluateCommand());
206 // Check that build statements can override rule builtins like depfile.
207 TEST_F(GraphTest, DepfileOverride) {
208 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
211 " command = unused\n"
214 Edge* edge = GetNode("out")->in_edge();
215 EXPECT_EQ("y", edge->GetBinding("depfile"));
218 // Check that overridden values show up in expansion of rule-level bindings.
219 TEST_F(GraphTest, DepfileOverrideParent) {
220 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
223 " command = depfile is $depfile\n"
226 Edge* edge = GetNode("out")->in_edge();
227 EXPECT_EQ("depfile is y", edge->GetBinding("command"));