move test virtual time "now_" into VirtualFileSystem
[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
17 #include "test.h"
18
19 struct GraphTest : public StateTestWithBuiltinRules {
20   GraphTest() : scan_(&state_, NULL, &fs_) {}
21
22   VirtualFileSystem fs_;
23   DependencyScan scan_;
24 };
25
26 TEST_F(GraphTest, MissingImplicit) {
27   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
28 "build out: cat in | implicit\n"));
29   fs_.Create("in", "");
30   fs_.Create("out", "");
31
32   Edge* edge = GetNode("out")->in_edge();
33   string err;
34   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
35   ASSERT_EQ("", err);
36
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());
41 }
42
43 TEST_F(GraphTest, ModifiedImplicit) {
44   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
45 "build out: cat in | implicit\n"));
46   fs_.Create("in", "");
47   fs_.Create("out", "");
48   fs_.Tick();
49   fs_.Create("implicit", "");
50
51   Edge* edge = GetNode("out")->in_edge();
52   string err;
53   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
54   ASSERT_EQ("", err);
55
56   // A modified implicit dep should make the output dirty.
57   EXPECT_TRUE(GetNode("out")->dirty());
58 }
59
60 TEST_F(GraphTest, FunkyMakefilePath) {
61   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
62 "rule catdep\n"
63 "  depfile = $out.d\n"
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", "");
69   fs_.Tick();
70   fs_.Create("implicit.h", "");
71
72   Edge* edge = GetNode("out.o")->in_edge();
73   string err;
74   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
75   ASSERT_EQ("", err);
76
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());
80 }
81
82 TEST_F(GraphTest, ExplicitImplicit) {
83   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
84 "rule catdep\n"
85 "  depfile = $out.d\n"
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", "");
93   fs_.Tick();
94   fs_.Create("data", "");
95
96   Edge* edge = GetNode("out.o")->in_edge();
97   string err;
98   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
99   ASSERT_EQ("", err);
100
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());
105 }
106
107 TEST_F(GraphTest, PathWithCurrentDirectory) {
108   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
109 "rule catdep\n"
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", "");
116
117   Edge* edge = GetNode("out.o")->in_edge();
118   string err;
119   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
120   ASSERT_EQ("", err);
121
122   EXPECT_FALSE(GetNode("out.o")->dirty());
123 }
124
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"));
131
132   string err;
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));
138   }
139 }
140
141 TEST_F(GraphTest, VarInOutQuoteSpaces) {
142   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
143 "build a$ b: cat nospace with$ space nospace2\n"));
144
145   Edge* edge = GetNode("a b")->in_edge();
146   EXPECT_EQ("cat nospace \"with space\" nospace2 > \"a b\"",
147       edge->EvaluateCommand());
148 }
149
150 // Regression test for https://github.com/martine/ninja/issues/380
151 TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
152   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
153 "rule catdep\n"
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", "");
160
161   Edge* edge = GetNode("out.o")->in_edge();
162   string err;
163   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
164   ASSERT_EQ("", err);
165
166   EXPECT_FALSE(GetNode("out.o")->dirty());
167 }
168
169 // Regression test for https://github.com/martine/ninja/issues/404
170 TEST_F(GraphTest, DepfileRemoved) {
171   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
172 "rule catdep\n"
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", "");
178   fs_.Tick();
179   fs_.Create("out.o.d", "out.o: foo.h\n");
180   fs_.Create("out.o", "");
181
182   Edge* edge = GetNode("out.o")->in_edge();
183   string err;
184   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
185   ASSERT_EQ("", err);
186   EXPECT_FALSE(GetNode("out.o")->dirty());
187
188   state_.Reset();
189   fs_.RemoveFile("out.o.d");
190   EXPECT_TRUE(scan_.RecomputeDirty(edge, &err));
191   ASSERT_EQ("", err);
192   EXPECT_TRUE(GetNode("out.o")->dirty());
193 }
194
195 // Check that rule-level variables are in scope for eval.
196 TEST_F(GraphTest, RuleVariablesInScope) {
197   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
198 "rule r\n"
199 "  depfile = x\n"
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());
204 }
205
206 // Check that build statements can override rule builtins like depfile.
207 TEST_F(GraphTest, DepfileOverride) {
208   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
209 "rule r\n"
210 "  depfile = x\n"
211 "  command = unused\n"
212 "build out: r in\n"
213 "  depfile = y\n"));
214   Edge* edge = GetNode("out")->in_edge();
215   EXPECT_EQ("y", edge->GetBinding("depfile"));
216 }
217
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_,
221 "rule r\n"
222 "  depfile = x\n"
223 "  command = depfile is $depfile\n"
224 "build out: r in\n"
225 "  depfile = y\n"));
226   Edge* edge = GetNode("out")->in_edge();
227   EXPECT_EQ("depfile is y", edge->GetBinding("command"));
228 }