Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "graph.h" 00016 00017 #include "test.h" 00018 00019 struct GraphTest : public StateTestWithBuiltinRules { 00020 GraphTest() : scan_(&state_, NULL, NULL, &fs_) {} 00021 00022 VirtualFileSystem fs_; 00023 DependencyScan scan_; 00024 }; 00025 00026 TEST_F(GraphTest, MissingImplicit) { 00027 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00028 "build out: cat in | implicit\n")); 00029 fs_.Create("in", ""); 00030 fs_.Create("out", ""); 00031 00032 Edge* edge = GetNode("out")->in_edge(); 00033 string err; 00034 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00035 ASSERT_EQ("", err); 00036 00037 // A missing implicit dep *should* make the output dirty. 00038 // (In fact, a build will fail.) 00039 // This is a change from prior semantics of ninja. 00040 EXPECT_TRUE(GetNode("out")->dirty()); 00041 } 00042 00043 TEST_F(GraphTest, ModifiedImplicit) { 00044 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00045 "build out: cat in | implicit\n")); 00046 fs_.Create("in", ""); 00047 fs_.Create("out", ""); 00048 fs_.Tick(); 00049 fs_.Create("implicit", ""); 00050 00051 Edge* edge = GetNode("out")->in_edge(); 00052 string err; 00053 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00054 ASSERT_EQ("", err); 00055 00056 // A modified implicit dep should make the output dirty. 00057 EXPECT_TRUE(GetNode("out")->dirty()); 00058 } 00059 00060 TEST_F(GraphTest, FunkyMakefilePath) { 00061 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00062 "rule catdep\n" 00063 " depfile = $out.d\n" 00064 " command = cat $in > $out\n" 00065 "build out.o: catdep foo.cc\n")); 00066 fs_.Create("foo.cc", ""); 00067 fs_.Create("out.o.d", "out.o: ./foo/../implicit.h\n"); 00068 fs_.Create("out.o", ""); 00069 fs_.Tick(); 00070 fs_.Create("implicit.h", ""); 00071 00072 Edge* edge = GetNode("out.o")->in_edge(); 00073 string err; 00074 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00075 ASSERT_EQ("", err); 00076 00077 // implicit.h has changed, though our depfile refers to it with a 00078 // non-canonical path; we should still find it. 00079 EXPECT_TRUE(GetNode("out.o")->dirty()); 00080 } 00081 00082 TEST_F(GraphTest, ExplicitImplicit) { 00083 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00084 "rule catdep\n" 00085 " depfile = $out.d\n" 00086 " command = cat $in > $out\n" 00087 "build implicit.h: cat data\n" 00088 "build out.o: catdep foo.cc || implicit.h\n")); 00089 fs_.Create("implicit.h", ""); 00090 fs_.Create("foo.cc", ""); 00091 fs_.Create("out.o.d", "out.o: implicit.h\n"); 00092 fs_.Create("out.o", ""); 00093 fs_.Tick(); 00094 fs_.Create("data", ""); 00095 00096 Edge* edge = GetNode("out.o")->in_edge(); 00097 string err; 00098 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00099 ASSERT_EQ("", err); 00100 00101 // We have both an implicit and an explicit dep on implicit.h. 00102 // The implicit dep should "win" (in the sense that it should cause 00103 // the output to be dirty). 00104 EXPECT_TRUE(GetNode("out.o")->dirty()); 00105 } 00106 00107 TEST_F(GraphTest, PathWithCurrentDirectory) { 00108 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00109 "rule catdep\n" 00110 " depfile = $out.d\n" 00111 " command = cat $in > $out\n" 00112 "build ./out.o: catdep ./foo.cc\n")); 00113 fs_.Create("foo.cc", ""); 00114 fs_.Create("out.o.d", "out.o: foo.cc\n"); 00115 fs_.Create("out.o", ""); 00116 00117 Edge* edge = GetNode("out.o")->in_edge(); 00118 string err; 00119 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00120 ASSERT_EQ("", err); 00121 00122 EXPECT_FALSE(GetNode("out.o")->dirty()); 00123 } 00124 00125 TEST_F(GraphTest, RootNodes) { 00126 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00127 "build out1: cat in1\n" 00128 "build mid1: cat in1\n" 00129 "build out2: cat mid1\n" 00130 "build out3 out4: cat mid1\n")); 00131 00132 string err; 00133 vector<Node*> root_nodes = state_.RootNodes(&err); 00134 EXPECT_EQ(4u, root_nodes.size()); 00135 for (size_t i = 0; i < root_nodes.size(); ++i) { 00136 string name = root_nodes[i]->path(); 00137 EXPECT_EQ("out", name.substr(0, 3)); 00138 } 00139 } 00140 00141 TEST_F(GraphTest, VarInOutQuoteSpaces) { 00142 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00143 "build a$ b: cat nospace with$ space nospace2\n")); 00144 00145 Edge* edge = GetNode("a b")->in_edge(); 00146 EXPECT_EQ("cat nospace \"with space\" nospace2 > \"a b\"", 00147 edge->EvaluateCommand()); 00148 } 00149 00150 // Regression test for https://github.com/martine/ninja/issues/380 00151 TEST_F(GraphTest, DepfileWithCanonicalizablePath) { 00152 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00153 "rule catdep\n" 00154 " depfile = $out.d\n" 00155 " command = cat $in > $out\n" 00156 "build ./out.o: catdep ./foo.cc\n")); 00157 fs_.Create("foo.cc", ""); 00158 fs_.Create("out.o.d", "out.o: bar/../foo.cc\n"); 00159 fs_.Create("out.o", ""); 00160 00161 Edge* edge = GetNode("out.o")->in_edge(); 00162 string err; 00163 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00164 ASSERT_EQ("", err); 00165 00166 EXPECT_FALSE(GetNode("out.o")->dirty()); 00167 } 00168 00169 // Regression test for https://github.com/martine/ninja/issues/404 00170 TEST_F(GraphTest, DepfileRemoved) { 00171 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00172 "rule catdep\n" 00173 " depfile = $out.d\n" 00174 " command = cat $in > $out\n" 00175 "build ./out.o: catdep ./foo.cc\n")); 00176 fs_.Create("foo.h", ""); 00177 fs_.Create("foo.cc", ""); 00178 fs_.Tick(); 00179 fs_.Create("out.o.d", "out.o: foo.h\n"); 00180 fs_.Create("out.o", ""); 00181 00182 Edge* edge = GetNode("out.o")->in_edge(); 00183 string err; 00184 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00185 ASSERT_EQ("", err); 00186 EXPECT_FALSE(GetNode("out.o")->dirty()); 00187 00188 state_.Reset(); 00189 fs_.RemoveFile("out.o.d"); 00190 EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); 00191 ASSERT_EQ("", err); 00192 EXPECT_TRUE(GetNode("out.o")->dirty()); 00193 } 00194 00195 // Check that rule-level variables are in scope for eval. 00196 TEST_F(GraphTest, RuleVariablesInScope) { 00197 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00198 "rule r\n" 00199 " depfile = x\n" 00200 " command = depfile is $depfile\n" 00201 "build out: r in\n")); 00202 Edge* edge = GetNode("out")->in_edge(); 00203 EXPECT_EQ("depfile is x", edge->EvaluateCommand()); 00204 } 00205 00206 // Check that build statements can override rule builtins like depfile. 00207 TEST_F(GraphTest, DepfileOverride) { 00208 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00209 "rule r\n" 00210 " depfile = x\n" 00211 " command = unused\n" 00212 "build out: r in\n" 00213 " depfile = y\n")); 00214 Edge* edge = GetNode("out")->in_edge(); 00215 EXPECT_EQ("y", edge->GetBinding("depfile")); 00216 } 00217 00218 // Check that overridden values show up in expansion of rule-level bindings. 00219 TEST_F(GraphTest, DepfileOverrideParent) { 00220 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00221 "rule r\n" 00222 " depfile = x\n" 00223 " command = depfile is $depfile\n" 00224 "build out: r in\n" 00225 " depfile = y\n")); 00226 Edge* edge = GetNode("out")->in_edge(); 00227 EXPECT_EQ("depfile is y", edge->GetBinding("command")); 00228 }