Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1227)

Side by Side Diff: tools/gn/header_checker_unittest.cc

Issue 584683002: Improve GN header checker, make //ui pass. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/header_checker.cc ('k') | ui/accelerometer/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "tools/gn/config.h" 8 #include "tools/gn/config.h"
9 #include "tools/gn/header_checker.h" 9 #include "tools/gn/header_checker.h"
10 #include "tools/gn/scheduler.h" 10 #include "tools/gn/scheduler.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 targets_.push_back(&b_); 49 targets_.push_back(&b_);
50 targets_.push_back(&c_); 50 targets_.push_back(&c_);
51 targets_.push_back(&d_); 51 targets_.push_back(&d_);
52 } 52 }
53 53
54 protected: 54 protected:
55 Scheduler scheduler_; 55 Scheduler scheduler_;
56 56
57 TestWithScope setup_; 57 TestWithScope setup_;
58 58
59 // Some headers that are automatically set up with a dependency chain. 59 // Some headers that are automatically set up with a public dependency chain.
60 // a -> b -> c 60 // a -> b -> c. D is unconnected.
61 Target a_; 61 Target a_;
62 Target b_; 62 Target b_;
63 Target c_; 63 Target c_;
64 Target d_; 64 Target d_;
65 65
66 std::vector<const Target*> targets_; 66 std::vector<const Target*> targets_;
67 }; 67 };
68 68
69 } // namespace 69 } // namespace
70 70
71 TEST_F(HeaderCheckerTest, IsDependencyOf) { 71 TEST_F(HeaderCheckerTest, IsDependencyOf) {
72 scoped_refptr<HeaderChecker> checker( 72 scoped_refptr<HeaderChecker> checker(
73 new HeaderChecker(setup_.build_settings(), targets_)); 73 new HeaderChecker(setup_.build_settings(), targets_));
74 74
75 // Add a target P ("private") that privately depends on C, and hook up the 75 // Add a target P ("private") that privately depends on C, and hook up the
76 // chain so that A -> P -> C. A will depend on C via two different paths. 76 // chain so that A -> P -> C. A will depend on C via two different paths.
77 Err err; 77 Err err;
78 Target p(setup_.settings(), Label(SourceDir("//p/"), "p")); 78 Target p(setup_.settings(), Label(SourceDir("//p/"), "p"));
79 p.set_output_type(Target::SOURCE_SET); 79 p.set_output_type(Target::SOURCE_SET);
80 p.SetToolchain(setup_.toolchain(), &err); 80 p.SetToolchain(setup_.toolchain(), &err);
81 EXPECT_FALSE(err.has_error()); 81 EXPECT_FALSE(err.has_error());
82 p.private_deps().push_back(LabelTargetPair(&c_)); 82 p.private_deps().push_back(LabelTargetPair(&c_));
83 p.visibility().SetPublic(); 83 p.visibility().SetPublic();
84 p.OnResolved(&err); 84 p.OnResolved(&err);
85 85
86 a_.public_deps().push_back(LabelTargetPair(&p)); 86 a_.public_deps().push_back(LabelTargetPair(&p));
87 87
88 // A does not depend on itself. 88 // A does not depend on itself.
89 bool is_public = false; 89 bool is_permitted = false;
90 std::vector<const Target*> chain; 90 HeaderChecker::Chain chain;
91 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_public)); 91 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_permitted));
92 92
93 // A depends on B. 93 // A depends publicly on B.
94 chain.clear(); 94 chain.clear();
95 is_public = false; 95 is_permitted = false;
96 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_public)); 96 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_permitted));
97 ASSERT_EQ(2u, chain.size()); 97 ASSERT_EQ(2u, chain.size());
98 EXPECT_EQ(&b_, chain[0]); 98 EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[0]);
99 EXPECT_EQ(&a_, chain[1]); 99 EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[1]);
100 EXPECT_TRUE(is_public); 100 EXPECT_TRUE(is_permitted);
101 101
102 // A indirectly depends on C. The "public" dependency path through B should 102 // A indirectly depends on C. The "public" dependency path through B should
103 // be identified. 103 // be identified.
104 chain.clear(); 104 chain.clear();
105 is_public = false; 105 is_permitted = false;
106 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); 106 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
107 ASSERT_EQ(3u, chain.size()); 107 ASSERT_EQ(3u, chain.size());
108 EXPECT_EQ(&c_, chain[0]); 108 EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[0]);
109 EXPECT_EQ(&b_, chain[1]); 109 EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[1]);
110 EXPECT_EQ(&a_, chain[2]); 110 EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
111 EXPECT_TRUE(is_public); 111 EXPECT_TRUE(is_permitted);
112 112
113 // C does not depend on A. 113 // C does not depend on A.
114 chain.clear(); 114 chain.clear();
115 is_public = false; 115 is_permitted = false;
116 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_public)); 116 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_permitted));
117 EXPECT_TRUE(chain.empty()); 117 EXPECT_TRUE(chain.empty());
118 EXPECT_FALSE(is_public); 118 EXPECT_FALSE(is_permitted);
119 119
120 // Add a private A -> C dependency. This should not be detected since it's 120 // Remove the B -> C public dependency, leaving P's private dep on C the only
121 // private, even though it's shorter than the A -> B -> C one. 121 // path from A to C. This should now be found.
122 chain.clear(); 122 chain.clear();
123 is_public = false; 123 EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one.
124 a_.private_deps().push_back(LabelTargetPair(&c_)); 124 b_.public_deps().erase(b_.public_deps().begin());
125 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); 125 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
126 EXPECT_EQ(&c_, chain[0]); 126 EXPECT_EQ(3u, chain.size());
127 EXPECT_EQ(&b_, chain[1]); 127 EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
128 EXPECT_EQ(&a_, chain[2]); 128 EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
129 EXPECT_TRUE(is_public); 129 EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
130 EXPECT_FALSE(is_permitted);
130 131
131 // Remove the B -> C public dependency, leaving A's private dep on C the only 132 // P privately depends on C. That dependency should be OK since it's only
132 // path. This should now be found. 133 // one hop.
133 chain.clear(); 134 chain.clear();
134 EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one. 135 is_permitted = false;
135 b_.public_deps().erase(b_.public_deps().begin()); 136 EXPECT_TRUE(checker->IsDependencyOf(&c_, &p, &chain, &is_permitted));
136 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); 137 ASSERT_EQ(2u, chain.size());
137 EXPECT_EQ(&c_, chain[0]); 138 EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
138 EXPECT_EQ(&a_, chain[1]); 139 EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
139 EXPECT_FALSE(is_public); 140 EXPECT_TRUE(is_permitted);
140 } 141 }
141 142
142 TEST_F(HeaderCheckerTest, CheckInclude) { 143 TEST_F(HeaderCheckerTest, CheckInclude) {
143 InputFile input_file(SourceFile("//some_file.cc")); 144 InputFile input_file(SourceFile("//some_file.cc"));
144 input_file.SetContents(std::string()); 145 input_file.SetContents(std::string());
145 LocationRange range; // Dummy value. 146 LocationRange range; // Dummy value.
146 147
147 // Add a disconnected target d with a header to check that you have to have 148 // Add a disconnected target d with a header to check that you have to have
148 // to depend on a target listing a header. 149 // to depend on a target listing a header.
149 SourceFile d_header("//d_header.h"); 150 SourceFile d_header("//d_header.h");
150 d_.sources().push_back(SourceFile(d_header)); 151 d_.sources().push_back(SourceFile(d_header));
151 152
152 // Add a header on B and say everything in B is public. 153 // Add a header on B and say everything in B is public.
153 SourceFile b_public("//b_public.h"); 154 SourceFile b_public("//b_public.h");
154 b_.sources().push_back(b_public); 155 b_.sources().push_back(b_public);
155 c_.set_all_headers_public(true); 156 c_.set_all_headers_public(true);
156 157
157 // Add a public and private header on C. 158 // Add a public and private header on C.
158 SourceFile c_public("//c_public.h"); 159 SourceFile c_public("//c_public.h");
159 SourceFile c_private("//c_private.h"); 160 SourceFile c_private("//c_private.h");
160 c_.sources().push_back(c_private); 161 c_.sources().push_back(c_private);
161 c_.public_headers().push_back(c_public); 162 c_.public_headers().push_back(c_public);
162 c_.set_all_headers_public(false); 163 c_.set_all_headers_public(false);
163 164
164 targets_.push_back(&d_);
165 scoped_refptr<HeaderChecker> checker( 165 scoped_refptr<HeaderChecker> checker(
166 new HeaderChecker(setup_.build_settings(), targets_)); 166 new HeaderChecker(setup_.build_settings(), targets_));
167 167
168 // A file in target A can't include a header from D because A has no 168 // A file in target A can't include a header from D because A has no
169 // dependency on D. 169 // dependency on D.
170 Err err; 170 Err err;
171 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err)); 171 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err));
172 EXPECT_TRUE(err.has_error()); 172 EXPECT_TRUE(err.has_error());
173 173
174 // A can include the public header in B. 174 // A can include the public header in B.
175 err = Err(); 175 err = Err();
176 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, b_public, range, &err)); 176 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, b_public, range, &err));
177 EXPECT_FALSE(err.has_error()); 177 EXPECT_FALSE(err.has_error());
178 178
179 // Check A depending on the public and private headers in C. 179 // Check A depending on the public and private headers in C.
180 err = Err(); 180 err = Err();
181 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err)); 181 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
182 EXPECT_FALSE(err.has_error()); 182 EXPECT_FALSE(err.has_error());
183 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err)); 183 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
184 EXPECT_TRUE(err.has_error()); 184 EXPECT_TRUE(err.has_error());
185 185
186 // A can depend on a random file unknown to the build. 186 // A can depend on a random file unknown to the build.
187 err = Err(); 187 err = Err();
188 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"), 188 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"),
189 range, &err)); 189 range, &err));
190 EXPECT_FALSE(err.has_error()); 190 EXPECT_FALSE(err.has_error());
191 } 191 }
192 192
193 // A public chain of dependencies should always be identified first, even if
194 // it is longer than a private one.
195 TEST_F(HeaderCheckerTest, PublicFirst) {
196 // Now make a A -> Z -> D private dependency chain (one shorter than the
197 // public one to get to D).
198 Target z(setup_.settings(), Label(SourceDir("//a/"), "a"));
199 z.set_output_type(Target::SOURCE_SET);
200 Err err;
201 EXPECT_TRUE(z.SetToolchain(setup_.toolchain(), &err));
202 z.private_deps().push_back(LabelTargetPair(&d_));
203 EXPECT_TRUE(z.OnResolved(&err));
204 targets_.push_back(&z);
205
206 a_.private_deps().push_back(LabelTargetPair(&z));
207
208 // Check that D can be found from A, but since it's private, it will be
209 // marked as not permitted.
210 bool is_permitted = false;
211 HeaderChecker::Chain chain;
212 scoped_refptr<HeaderChecker> checker(
213 new HeaderChecker(setup_.build_settings(), targets_));
214 EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted));
215
216 EXPECT_FALSE(is_permitted);
217 ASSERT_EQ(3u, chain.size());
218 EXPECT_EQ(HeaderChecker::ChainLink(&d_, false), chain[0]);
219 EXPECT_EQ(HeaderChecker::ChainLink(&z, false), chain[1]);
220 EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
221
222 // Hook up D to the existing public A -> B -> C chain to make a long one, and
223 // search for D again.
224 c_.public_deps().push_back(LabelTargetPair(&d_));
225 checker = new HeaderChecker(setup_.build_settings(), targets_);
226 chain.clear();
227 EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted));
228
229 // This should have found the long public one.
230 EXPECT_TRUE(is_permitted);
231 ASSERT_EQ(4u, chain.size());
232 EXPECT_EQ(HeaderChecker::ChainLink(&d_, true), chain[0]);
233 EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[1]);
234 EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[2]);
235 EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[3]);
236 }
237
193 // Checks that the allow_circular_includes_from list works. 238 // Checks that the allow_circular_includes_from list works.
194 TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) { 239 TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) {
195 InputFile input_file(SourceFile("//some_file.cc")); 240 InputFile input_file(SourceFile("//some_file.cc"));
196 input_file.SetContents(std::string()); 241 input_file.SetContents(std::string());
197 LocationRange range; // Dummy value. 242 LocationRange range; // Dummy value.
198 243
199 // Add an include file to A. 244 // Add an include file to A.
200 SourceFile a_public("//a_public.h"); 245 SourceFile a_public("//a_public.h");
201 a_.sources().push_back(a_public); 246 a_.sources().push_back(a_public);
202 247
203 scoped_refptr<HeaderChecker> checker( 248 scoped_refptr<HeaderChecker> checker(
204 new HeaderChecker(setup_.build_settings(), targets_)); 249 new HeaderChecker(setup_.build_settings(), targets_));
205 250
206 // A depends on B. So B normally can't include headers from A. 251 // A depends on B. So B normally can't include headers from A.
207 Err err; 252 Err err;
208 EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err)); 253 EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
209 EXPECT_TRUE(err.has_error()); 254 EXPECT_TRUE(err.has_error());
210 255
211 // Add an allow_circular_includes_from on A that lists B. 256 // Add an allow_circular_includes_from on A that lists B.
212 a_.allow_circular_includes_from().insert(b_.label()); 257 a_.allow_circular_includes_from().insert(b_.label());
213 258
214 // Now the include from B to A should be allowed. 259 // Now the include from B to A should be allowed.
215 err = Err(); 260 err = Err();
216 EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err)); 261 EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
217 EXPECT_FALSE(err.has_error()); 262 EXPECT_FALSE(err.has_error());
218 } 263 }
OLDNEW
« no previous file with comments | « tools/gn/header_checker.cc ('k') | ui/accelerometer/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698