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

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

Issue 561273003: Add public deps to GN (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') | tools/gn/ninja_action_target_writer.cc » ('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"
11 #include "tools/gn/target.h" 11 #include "tools/gn/target.h"
12 #include "tools/gn/test_with_scope.h" 12 #include "tools/gn/test_with_scope.h"
13 13
14 namespace { 14 namespace {
15 15
16 class HeaderCheckerTest : public testing::Test { 16 class HeaderCheckerTest : public testing::Test {
17 public: 17 public:
18 HeaderCheckerTest() 18 HeaderCheckerTest()
19 : a_(setup_.settings(), Label(SourceDir("//a/"), "a")), 19 : a_(setup_.settings(), Label(SourceDir("//a/"), "a")),
20 b_(setup_.settings(), Label(SourceDir("//b/"), "a")), 20 b_(setup_.settings(), Label(SourceDir("//b/"), "b")),
21 c_(setup_.settings(), Label(SourceDir("//c/"), "c")), 21 c_(setup_.settings(), Label(SourceDir("//c/"), "c")),
22 d_(setup_.settings(), Label(SourceDir("//d/"), "d")) { 22 d_(setup_.settings(), Label(SourceDir("//d/"), "d")) {
23 a_.deps().push_back(LabelTargetPair(&b_)); 23 a_.set_output_type(Target::SOURCE_SET);
24 b_.deps().push_back(LabelTargetPair(&c_)); 24 b_.set_output_type(Target::SOURCE_SET);
25 c_.set_output_type(Target::SOURCE_SET);
26 d_.set_output_type(Target::SOURCE_SET);
27
28 Err err;
29 a_.SetToolchain(setup_.toolchain(), &err);
30 b_.SetToolchain(setup_.toolchain(), &err);
31 c_.SetToolchain(setup_.toolchain(), &err);
32 d_.SetToolchain(setup_.toolchain(), &err);
33
34 a_.public_deps().push_back(LabelTargetPair(&b_));
35 b_.public_deps().push_back(LabelTargetPair(&c_));
25 36
26 // Start with all public visibility. 37 // Start with all public visibility.
27 a_.visibility().SetPublic(); 38 a_.visibility().SetPublic();
28 b_.visibility().SetPublic(); 39 b_.visibility().SetPublic();
29 c_.visibility().SetPublic(); 40 c_.visibility().SetPublic();
30 d_.visibility().SetPublic(); 41 d_.visibility().SetPublic();
31 42
43 d_.OnResolved(&err);
44 c_.OnResolved(&err);
45 b_.OnResolved(&err);
46 a_.OnResolved(&err);
47
32 targets_.push_back(&a_); 48 targets_.push_back(&a_);
33 targets_.push_back(&b_); 49 targets_.push_back(&b_);
34 targets_.push_back(&c_); 50 targets_.push_back(&c_);
35 targets_.push_back(&d_); 51 targets_.push_back(&d_);
36 } 52 }
37 53
38 protected: 54 protected:
39 Scheduler scheduler_; 55 Scheduler scheduler_;
40 56
41 TestWithScope setup_; 57 TestWithScope setup_;
42 58
43 // Some headers that are automatically set up with a dependency chain. 59 // Some headers that are automatically set up with a dependency chain.
44 // a -> b -> c 60 // a -> b -> c
45 Target a_; 61 Target a_;
46 Target b_; 62 Target b_;
47 Target c_; 63 Target c_;
48 Target d_; 64 Target d_;
49 65
50 std::vector<const Target*> targets_; 66 std::vector<const Target*> targets_;
51 }; 67 };
52 68
53 } // namespace 69 } // namespace
54 70
55 TEST_F(HeaderCheckerTest, IsDependencyOf) { 71 TEST_F(HeaderCheckerTest, IsDependencyOf) {
56 scoped_refptr<HeaderChecker> checker( 72 scoped_refptr<HeaderChecker> checker(
57 new HeaderChecker(setup_.build_settings(), targets_)); 73 new HeaderChecker(setup_.build_settings(), targets_));
58 74
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.
77 Err err;
78 Target p(setup_.settings(), Label(SourceDir("//p/"), "p"));
79 p.set_output_type(Target::SOURCE_SET);
80 p.SetToolchain(setup_.toolchain(), &err);
81 EXPECT_FALSE(err.has_error());
82 p.private_deps().push_back(LabelTargetPair(&c_));
83 p.visibility().SetPublic();
84 p.OnResolved(&err);
85
86 a_.public_deps().push_back(LabelTargetPair(&p));
87
88 // A does not depend on itself.
89 bool is_public = false;
59 std::vector<const Target*> chain; 90 std::vector<const Target*> chain;
60 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, false, &chain, NULL)); 91 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_public));
61 92
93 // A depends on B.
62 chain.clear(); 94 chain.clear();
63 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, false, &chain, NULL)); 95 is_public = false;
96 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_public));
64 ASSERT_EQ(2u, chain.size()); 97 ASSERT_EQ(2u, chain.size());
65 EXPECT_EQ(&b_, chain[0]); 98 EXPECT_EQ(&b_, chain[0]);
66 EXPECT_EQ(&a_, chain[1]); 99 EXPECT_EQ(&a_, chain[1]);
100 EXPECT_TRUE(is_public);
67 101
102 // A indirectly depends on C. The "public" dependency path through B should
103 // be identified.
68 chain.clear(); 104 chain.clear();
69 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, false, &chain, NULL)); 105 is_public = false;
106 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public));
70 ASSERT_EQ(3u, chain.size()); 107 ASSERT_EQ(3u, chain.size());
71 EXPECT_EQ(&c_, chain[0]); 108 EXPECT_EQ(&c_, chain[0]);
72 EXPECT_EQ(&b_, chain[1]); 109 EXPECT_EQ(&b_, chain[1]);
73 EXPECT_EQ(&a_, chain[2]); 110 EXPECT_EQ(&a_, chain[2]);
111 EXPECT_TRUE(is_public);
74 112
113 // C does not depend on A.
75 chain.clear(); 114 chain.clear();
76 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, false, &chain, NULL)); 115 is_public = false;
116 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_public));
77 EXPECT_TRUE(chain.empty()); 117 EXPECT_TRUE(chain.empty());
118 EXPECT_FALSE(is_public);
78 119
79 // If an a -> c dependency exists, this should be chosen for the chain. 120 // Add a private A -> C dependency. This should not be detected since it's
121 // private, even though it's shorter than the A -> B -> C one.
80 chain.clear(); 122 chain.clear();
81 a_.deps().push_back(LabelTargetPair(&c_)); 123 is_public = false;
82 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, false, &chain, NULL)); 124 a_.private_deps().push_back(LabelTargetPair(&c_));
83 EXPECT_EQ(&c_, chain[0]); 125 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public));
84 EXPECT_EQ(&a_, chain[1]);
85 }
86
87 TEST_F(HeaderCheckerTest, IsDependencyOf_ForwardsDirectDependentConfigs) {
88 scoped_refptr<HeaderChecker> checker(
89 new HeaderChecker(setup_.build_settings(), targets_));
90
91 // The a -> b -> c chain is found, since no chains that forward direct-
92 // dependent configs exist.
93 std::vector<const Target*> chain;
94 bool direct_dependent_configs_apply = false;
95 EXPECT_TRUE(checker->IsDependencyOf(
96 &c_, &a_, true, &chain, &direct_dependent_configs_apply));
97 EXPECT_FALSE(direct_dependent_configs_apply);
98 EXPECT_EQ(3u, chain.size());
99 EXPECT_EQ(&c_, chain[0]); 126 EXPECT_EQ(&c_, chain[0]);
100 EXPECT_EQ(&b_, chain[1]); 127 EXPECT_EQ(&b_, chain[1]);
101 EXPECT_EQ(&a_, chain[2]); 128 EXPECT_EQ(&a_, chain[2]);
129 EXPECT_TRUE(is_public);
102 130
103 // Create a chain a -> d -> c where d forwards direct-dependent configs. 131 // Remove the B -> C public dependency, leaving A's private dep on C the only
104 // This path should be preferred when dependency chains which forward 132 // path. This should now be found.
105 // direct-dependent configs are preferred.
106 chain.clear(); 133 chain.clear();
107 direct_dependent_configs_apply = false; 134 EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one.
108 d_.deps().push_back(LabelTargetPair(&c_)); 135 b_.public_deps().erase(b_.public_deps().begin());
109 d_.forward_dependent_configs().push_back(LabelTargetPair(&c_)); 136 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public));
110 a_.deps().push_back(LabelTargetPair(&d_));
111 EXPECT_TRUE(checker->IsDependencyOf(
112 &c_, &a_, true, &chain, &direct_dependent_configs_apply));
113 EXPECT_TRUE(direct_dependent_configs_apply);
114 EXPECT_EQ(3u, chain.size());
115 EXPECT_EQ(&c_, chain[0]);
116 EXPECT_EQ(&d_, chain[1]);
117 EXPECT_EQ(&a_, chain[2]);
118
119 // d also forwards direct-dependent configs if it is a group.
120 chain.clear();
121 direct_dependent_configs_apply = false;
122 d_.set_output_type(Target::GROUP);
123 d_.forward_dependent_configs().clear();
124 EXPECT_TRUE(checker->IsDependencyOf(
125 &c_, &a_, true, &chain, &direct_dependent_configs_apply));
126 EXPECT_TRUE(direct_dependent_configs_apply);
127 EXPECT_EQ(3u, chain.size());
128 EXPECT_EQ(&c_, chain[0]);
129 EXPECT_EQ(&d_, chain[1]);
130 EXPECT_EQ(&a_, chain[2]);
131
132 // A direct dependency a -> c carries direct-dependent configs.
133 chain.clear();
134 direct_dependent_configs_apply = false;
135 a_.deps().push_back(LabelTargetPair(&c_));
136 EXPECT_TRUE(checker->IsDependencyOf(
137 &c_, &a_, true, &chain, &direct_dependent_configs_apply));
138 EXPECT_TRUE(direct_dependent_configs_apply);
139 EXPECT_EQ(2u, chain.size());
140 EXPECT_EQ(&c_, chain[0]); 137 EXPECT_EQ(&c_, chain[0]);
141 EXPECT_EQ(&a_, chain[1]); 138 EXPECT_EQ(&a_, chain[1]);
139 EXPECT_FALSE(is_public);
142 } 140 }
143 141
144 TEST_F(HeaderCheckerTest, CheckInclude) { 142 TEST_F(HeaderCheckerTest, CheckInclude) {
145 InputFile input_file(SourceFile("//some_file.cc")); 143 InputFile input_file(SourceFile("//some_file.cc"));
146 input_file.SetContents(std::string()); 144 input_file.SetContents(std::string());
147 LocationRange range; // Dummy value. 145 LocationRange range; // Dummy value.
148 146
149 // Add a disconnected target d with a header to check that you have to have 147 // Add a disconnected target d with a header to check that you have to have
150 // to depend on a target listing a header. 148 // to depend on a target listing a header.
151 SourceFile d_header("//d_header.h"); 149 SourceFile d_header("//d_header.h");
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err)); 181 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
184 EXPECT_FALSE(err.has_error()); 182 EXPECT_FALSE(err.has_error());
185 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err)); 183 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
186 EXPECT_TRUE(err.has_error()); 184 EXPECT_TRUE(err.has_error());
187 185
188 // A can depend on a random file unknown to the build. 186 // A can depend on a random file unknown to the build.
189 err = Err(); 187 err = Err();
190 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"), 188 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"),
191 range, &err)); 189 range, &err));
192 EXPECT_FALSE(err.has_error()); 190 EXPECT_FALSE(err.has_error());
193
194 // If C is not visible from A, A can't include public headers even if there
195 // is a dependency path.
196 c_.visibility().SetPrivate(c_.label().dir());
197 err = Err();
198 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
199 EXPECT_TRUE(err.has_error());
200 c_.visibility().SetPublic();
201
202 // If C has direct-dependent configs, then B must forward them to A.
203 // If B is a group, that suffices to forward direct-dependent configs.
204 {
205 Config direct(setup_.settings(), Label(SourceDir("//c/"), "config"));
206 direct.config_values().cflags().push_back("-DSOME_DEFINE");
207
208 c_.direct_dependent_configs().push_back(LabelConfigPair(&direct));
209 err = Err();
210 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
211 EXPECT_TRUE(err.has_error());
212
213 b_.forward_dependent_configs().push_back(LabelTargetPair(&c_));
214 err = Err();
215 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
216 EXPECT_FALSE(err.has_error());
217
218 b_.forward_dependent_configs().clear();
219 b_.set_output_type(Target::GROUP);
220 err = Err();
221 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
222 EXPECT_FALSE(err.has_error());
223
224 b_.set_output_type(Target::UNKNOWN);
225 c_.direct_dependent_configs().clear();
226 }
227 } 191 }
228 192
229 // Checks that the allow_circular_includes_from list works. 193 // Checks that the allow_circular_includes_from list works.
230 TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) { 194 TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) {
231 InputFile input_file(SourceFile("//some_file.cc")); 195 InputFile input_file(SourceFile("//some_file.cc"));
232 input_file.SetContents(std::string()); 196 input_file.SetContents(std::string());
233 LocationRange range; // Dummy value. 197 LocationRange range; // Dummy value.
234 198
235 // Add an include file to A. 199 // Add an include file to A.
236 SourceFile a_public("//a_public.h"); 200 SourceFile a_public("//a_public.h");
237 a_.sources().push_back(a_public); 201 a_.sources().push_back(a_public);
238 202
239 scoped_refptr<HeaderChecker> checker( 203 scoped_refptr<HeaderChecker> checker(
240 new HeaderChecker(setup_.build_settings(), targets_)); 204 new HeaderChecker(setup_.build_settings(), targets_));
241 205
242 // A depends on B. So B normally can't include headers from A. 206 // A depends on B. So B normally can't include headers from A.
243 Err err; 207 Err err;
244 EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err)); 208 EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
245 EXPECT_TRUE(err.has_error()); 209 EXPECT_TRUE(err.has_error());
246 210
247 // Add an allow_circular_includes_from on A that lists B. 211 // Add an allow_circular_includes_from on A that lists B.
248 a_.allow_circular_includes_from().insert(b_.label()); 212 a_.allow_circular_includes_from().insert(b_.label());
249 213
250 // Now the include from B to A should be allowed. 214 // Now the include from B to A should be allowed.
251 err = Err(); 215 err = Err();
252 EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err)); 216 EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
253 EXPECT_FALSE(err.has_error()); 217 EXPECT_FALSE(err.has_error());
254 } 218 }
255
256 TEST_F(HeaderCheckerTest, GetDependentConfigChainProblemIndex) {
257 // Assume we have a chain A -> B -> C -> D.
258 Target target_a(setup_.settings(), Label(SourceDir("//a/"), "a"));
259 Target target_b(setup_.settings(), Label(SourceDir("//b/"), "b"));
260 Target target_c(setup_.settings(), Label(SourceDir("//c/"), "c"));
261 Target target_d(setup_.settings(), Label(SourceDir("//d/"), "d"));
262
263 // C is a group, and B forwards deps from C, so A should get configs from D.
264 target_a.set_output_type(Target::SOURCE_SET);
265 target_b.set_output_type(Target::SOURCE_SET);
266 target_c.set_output_type(Target::GROUP);
267 target_d.set_output_type(Target::SOURCE_SET);
268 target_b.forward_dependent_configs().push_back(
269 LabelTargetPair(&target_c));
270
271 // Dependency chain goes from bottom to top.
272 std::vector<const Target*> chain;
273 chain.push_back(&target_d);
274 chain.push_back(&target_c);
275 chain.push_back(&target_b);
276 chain.push_back(&target_a);
277
278 // If C is not a group, it shouldn't work anymore.
279 target_c.set_output_type(Target::SOURCE_SET);
280 EXPECT_EQ(1u, HeaderChecker::GetDependentConfigChainProblemIndex(chain));
281
282 // Or if B stops forwarding from C, it shouldn't work anymore.
283 target_c.set_output_type(Target::GROUP);
284 target_b.forward_dependent_configs().clear();
285 EXPECT_EQ(2u, HeaderChecker::GetDependentConfigChainProblemIndex(chain));
286 }
OLDNEW
« no previous file with comments | « tools/gn/header_checker.cc ('k') | tools/gn/ninja_action_target_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698