OLD | NEW |
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/header_checker.h" | 9 #include "tools/gn/header_checker.h" |
9 #include "tools/gn/scheduler.h" | 10 #include "tools/gn/scheduler.h" |
10 #include "tools/gn/target.h" | 11 #include "tools/gn/target.h" |
11 #include "tools/gn/test_with_scope.h" | 12 #include "tools/gn/test_with_scope.h" |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 class HeaderCheckerTest : public testing::Test { | 16 class HeaderCheckerTest : public testing::Test { |
16 public: | 17 public: |
17 HeaderCheckerTest() | 18 HeaderCheckerTest() |
18 : a_(setup_.settings(), Label(SourceDir("//a/"), "a")), | 19 : a_(setup_.settings(), Label(SourceDir("//a/"), "a")), |
19 b_(setup_.settings(), Label(SourceDir("//b/"), "a")), | 20 b_(setup_.settings(), Label(SourceDir("//b/"), "a")), |
20 c_(setup_.settings(), Label(SourceDir("//c/"), "c")) { | 21 c_(setup_.settings(), Label(SourceDir("//c/"), "c")), |
| 22 d_(setup_.settings(), Label(SourceDir("//d/"), "d")) { |
21 a_.deps().push_back(LabelTargetPair(&b_)); | 23 a_.deps().push_back(LabelTargetPair(&b_)); |
22 b_.deps().push_back(LabelTargetPair(&c_)); | 24 b_.deps().push_back(LabelTargetPair(&c_)); |
23 | 25 |
24 // Start with all public visibility. | 26 // Start with all public visibility. |
25 a_.visibility().SetPublic(); | 27 a_.visibility().SetPublic(); |
26 b_.visibility().SetPublic(); | 28 b_.visibility().SetPublic(); |
27 c_.visibility().SetPublic(); | 29 c_.visibility().SetPublic(); |
| 30 d_.visibility().SetPublic(); |
28 | 31 |
29 targets_.push_back(&a_); | 32 targets_.push_back(&a_); |
30 targets_.push_back(&b_); | 33 targets_.push_back(&b_); |
31 targets_.push_back(&c_); | 34 targets_.push_back(&c_); |
| 35 targets_.push_back(&d_); |
32 } | 36 } |
33 | 37 |
34 protected: | 38 protected: |
35 Scheduler scheduler_; | 39 Scheduler scheduler_; |
36 | 40 |
37 TestWithScope setup_; | 41 TestWithScope setup_; |
38 | 42 |
39 // Some headers that are automatically set up with a dependency chain. | 43 // Some headers that are automatically set up with a dependency chain. |
40 // a -> b -> c | 44 // a -> b -> c |
41 Target a_; | 45 Target a_; |
42 Target b_; | 46 Target b_; |
43 Target c_; | 47 Target c_; |
| 48 Target d_; |
44 | 49 |
45 std::vector<const Target*> targets_; | 50 std::vector<const Target*> targets_; |
46 }; | 51 }; |
47 | 52 |
48 } // namespace | 53 } // namespace |
49 | 54 |
50 TEST_F(HeaderCheckerTest, IsDependencyOf) { | 55 TEST_F(HeaderCheckerTest, IsDependencyOf) { |
51 scoped_refptr<HeaderChecker> checker( | 56 scoped_refptr<HeaderChecker> checker( |
52 new HeaderChecker(setup_.build_settings(), targets_)); | 57 new HeaderChecker(setup_.build_settings(), targets_)); |
53 | 58 |
54 std::vector<const Target*> chain; | 59 std::vector<const Target*> chain; |
55 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain)); | 60 EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, false, &chain, NULL)); |
56 | 61 |
57 chain.clear(); | 62 chain.clear(); |
58 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain)); | 63 EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, false, &chain, NULL)); |
59 ASSERT_EQ(2u, chain.size()); | 64 ASSERT_EQ(2u, chain.size()); |
60 EXPECT_EQ(&b_, chain[0]); | 65 EXPECT_EQ(&b_, chain[0]); |
61 EXPECT_EQ(&a_, chain[1]); | 66 EXPECT_EQ(&a_, chain[1]); |
62 | 67 |
63 chain.clear(); | 68 chain.clear(); |
64 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain)); | 69 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, false, &chain, NULL)); |
65 ASSERT_EQ(3u, chain.size()); | 70 ASSERT_EQ(3u, chain.size()); |
66 EXPECT_EQ(&c_, chain[0]); | 71 EXPECT_EQ(&c_, chain[0]); |
67 EXPECT_EQ(&b_, chain[1]); | 72 EXPECT_EQ(&b_, chain[1]); |
68 EXPECT_EQ(&a_, chain[2]); | 73 EXPECT_EQ(&a_, chain[2]); |
69 | 74 |
70 chain.clear(); | 75 chain.clear(); |
71 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain)); | 76 EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, false, &chain, NULL)); |
72 EXPECT_TRUE(chain.empty()); | 77 EXPECT_TRUE(chain.empty()); |
| 78 |
| 79 // If an a -> c dependency exists, this should be chosen for the chain. |
| 80 chain.clear(); |
| 81 a_.deps().push_back(LabelTargetPair(&c_)); |
| 82 EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, false, &chain, NULL)); |
| 83 EXPECT_EQ(&c_, chain[0]); |
| 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]); |
| 100 EXPECT_EQ(&b_, chain[1]); |
| 101 EXPECT_EQ(&a_, chain[2]); |
| 102 |
| 103 // Create a chain a -> d -> c where d forwards direct-dependent configs. |
| 104 // This path should be preferred when dependency chains which forward |
| 105 // direct-dependent configs are preferred. |
| 106 chain.clear(); |
| 107 direct_dependent_configs_apply = false; |
| 108 d_.deps().push_back(LabelTargetPair(&c_)); |
| 109 d_.forward_dependent_configs().push_back(LabelTargetPair(&c_)); |
| 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]); |
| 141 EXPECT_EQ(&a_, chain[1]); |
73 } | 142 } |
74 | 143 |
75 TEST_F(HeaderCheckerTest, CheckInclude) { | 144 TEST_F(HeaderCheckerTest, CheckInclude) { |
76 InputFile input_file(SourceFile("//some_file.cc")); | 145 InputFile input_file(SourceFile("//some_file.cc")); |
77 input_file.SetContents(std::string()); | 146 input_file.SetContents(std::string()); |
78 LocationRange range; // Dummy value. | 147 LocationRange range; // Dummy value. |
79 | 148 |
80 // Add a disconnected target d with a header to check that you have to have | 149 // Add a disconnected target d with a header to check that you have to have |
81 // to depend on a target listing a header. | 150 // to depend on a target listing a header. |
82 Target d(setup_.settings(), Label(SourceDir("//"), "d")); | |
83 SourceFile d_header("//d_header.h"); | 151 SourceFile d_header("//d_header.h"); |
84 d.sources().push_back(SourceFile(d_header)); | 152 d_.sources().push_back(SourceFile(d_header)); |
85 | 153 |
86 // Add a header on B and say everything in B is public. | 154 // Add a header on B and say everything in B is public. |
87 SourceFile b_public("//b_public.h"); | 155 SourceFile b_public("//b_public.h"); |
88 b_.sources().push_back(b_public); | 156 b_.sources().push_back(b_public); |
89 c_.set_all_headers_public(true); | 157 c_.set_all_headers_public(true); |
90 | 158 |
91 // Add a public and private header on C. | 159 // Add a public and private header on C. |
92 SourceFile c_public("//c_public.h"); | 160 SourceFile c_public("//c_public.h"); |
93 SourceFile c_private("//c_private.h"); | 161 SourceFile c_private("//c_private.h"); |
94 c_.sources().push_back(c_private); | 162 c_.sources().push_back(c_private); |
95 c_.public_headers().push_back(c_public); | 163 c_.public_headers().push_back(c_public); |
96 c_.set_all_headers_public(false); | 164 c_.set_all_headers_public(false); |
97 | 165 |
98 targets_.push_back(&d); | 166 targets_.push_back(&d_); |
99 scoped_refptr<HeaderChecker> checker( | 167 scoped_refptr<HeaderChecker> checker( |
100 new HeaderChecker(setup_.build_settings(), targets_)); | 168 new HeaderChecker(setup_.build_settings(), targets_)); |
101 | 169 |
102 // A file in target A can't include a header from D because A has no | 170 // A file in target A can't include a header from D because A has no |
103 // dependency on D. | 171 // dependency on D. |
104 Err err; | 172 Err err; |
105 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err)); | 173 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err)); |
106 EXPECT_TRUE(err.has_error()); | 174 EXPECT_TRUE(err.has_error()); |
107 | 175 |
108 // A can include the public header in B. | 176 // A can include the public header in B. |
(...skipping 13 matching lines...) Expand all Loading... |
122 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"), | 190 EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"), |
123 range, &err)); | 191 range, &err)); |
124 EXPECT_FALSE(err.has_error()); | 192 EXPECT_FALSE(err.has_error()); |
125 | 193 |
126 // If C is not visible from A, A can't include public headers even if there | 194 // If C is not visible from A, A can't include public headers even if there |
127 // is a dependency path. | 195 // is a dependency path. |
128 c_.visibility().SetPrivate(c_.label().dir()); | 196 c_.visibility().SetPrivate(c_.label().dir()); |
129 err = Err(); | 197 err = Err(); |
130 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_public, range, &err)); | 198 EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_public, range, &err)); |
131 EXPECT_TRUE(err.has_error()); | 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 } |
132 } | 227 } |
133 | 228 |
134 TEST_F(HeaderCheckerTest, DoDirectDependentConfigsApply) { | 229 TEST_F(HeaderCheckerTest, GetDependentConfigChainProblemIndex) { |
135 // Assume we have a chain A -> B -> C -> D. | 230 // Assume we have a chain A -> B -> C -> D. |
136 Target target_a(setup_.settings(), Label(SourceDir("//a/"), "a")); | 231 Target target_a(setup_.settings(), Label(SourceDir("//a/"), "a")); |
137 Target target_b(setup_.settings(), Label(SourceDir("//b/"), "b")); | 232 Target target_b(setup_.settings(), Label(SourceDir("//b/"), "b")); |
138 Target target_c(setup_.settings(), Label(SourceDir("//c/"), "c")); | 233 Target target_c(setup_.settings(), Label(SourceDir("//c/"), "c")); |
139 Target target_d(setup_.settings(), Label(SourceDir("//d/"), "d")); | 234 Target target_d(setup_.settings(), Label(SourceDir("//d/"), "d")); |
140 | 235 |
141 // C is a group, and B forwards deps from C, so A should get configs from D. | 236 // C is a group, and B forwards deps from C, so A should get configs from D. |
142 target_a.set_output_type(Target::SOURCE_SET); | 237 target_a.set_output_type(Target::SOURCE_SET); |
143 target_b.set_output_type(Target::SOURCE_SET); | 238 target_b.set_output_type(Target::SOURCE_SET); |
144 target_c.set_output_type(Target::GROUP); | 239 target_c.set_output_type(Target::GROUP); |
145 target_d.set_output_type(Target::SOURCE_SET); | 240 target_d.set_output_type(Target::SOURCE_SET); |
146 target_b.forward_dependent_configs().push_back( | 241 target_b.forward_dependent_configs().push_back( |
147 LabelTargetPair(&target_c)); | 242 LabelTargetPair(&target_c)); |
148 | 243 |
149 // Dependency chain goes from bottom to top. | 244 // Dependency chain goes from bottom to top. |
150 std::vector<const Target*> chain; | 245 std::vector<const Target*> chain; |
151 chain.push_back(&target_d); | 246 chain.push_back(&target_d); |
152 chain.push_back(&target_c); | 247 chain.push_back(&target_c); |
153 chain.push_back(&target_b); | 248 chain.push_back(&target_b); |
154 chain.push_back(&target_a); | 249 chain.push_back(&target_a); |
155 | 250 |
156 // This chain should be valid. | |
157 size_t badone = 0; | |
158 EXPECT_TRUE(HeaderChecker::DoDirectDependentConfigsApply(chain, &badone)); | |
159 | |
160 // If C is not a group, it shouldn't work anymore. | 251 // If C is not a group, it shouldn't work anymore. |
161 target_c.set_output_type(Target::SOURCE_SET); | 252 target_c.set_output_type(Target::SOURCE_SET); |
162 EXPECT_FALSE(HeaderChecker::DoDirectDependentConfigsApply(chain, &badone)); | 253 EXPECT_EQ(1u, HeaderChecker::GetDependentConfigChainProblemIndex(chain)); |
163 EXPECT_EQ(1u, badone); | |
164 | 254 |
165 // Or if B stops forwarding from C, it shouldn't work anymore. | 255 // Or if B stops forwarding from C, it shouldn't work anymore. |
166 target_c.set_output_type(Target::GROUP); | 256 target_c.set_output_type(Target::GROUP); |
167 badone = 0; | |
168 target_b.forward_dependent_configs().clear(); | 257 target_b.forward_dependent_configs().clear(); |
169 EXPECT_FALSE(HeaderChecker::DoDirectDependentConfigsApply(chain, &badone)); | 258 EXPECT_EQ(2u, HeaderChecker::GetDependentConfigChainProblemIndex(chain)); |
170 EXPECT_EQ(2u, badone); | |
171 } | 259 } |
OLD | NEW |