Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / gn / header_checker_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include <vector>
6
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "tools/gn/config.h"
9 #include "tools/gn/header_checker.h"
10 #include "tools/gn/scheduler.h"
11 #include "tools/gn/target.h"
12 #include "tools/gn/test_with_scope.h"
13
14 namespace {
15
16 class HeaderCheckerTest : public testing::Test {
17  public:
18   HeaderCheckerTest()
19       : a_(setup_.settings(), Label(SourceDir("//a/"), "a")),
20         b_(setup_.settings(), Label(SourceDir("//b/"), "b")),
21         c_(setup_.settings(), Label(SourceDir("//c/"), "c")),
22         d_(setup_.settings(), Label(SourceDir("//d/"), "d")) {
23     a_.set_output_type(Target::SOURCE_SET);
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_));
36
37     // Start with all public visibility.
38     a_.visibility().SetPublic();
39     b_.visibility().SetPublic();
40     c_.visibility().SetPublic();
41     d_.visibility().SetPublic();
42
43     d_.OnResolved(&err);
44     c_.OnResolved(&err);
45     b_.OnResolved(&err);
46     a_.OnResolved(&err);
47
48     targets_.push_back(&a_);
49     targets_.push_back(&b_);
50     targets_.push_back(&c_);
51     targets_.push_back(&d_);
52   }
53
54  protected:
55   Scheduler scheduler_;
56
57   TestWithScope setup_;
58
59   // Some headers that are automatically set up with a public dependency chain.
60   // a -> b -> c. D is unconnected.
61   Target a_;
62   Target b_;
63   Target c_;
64   Target d_;
65
66   std::vector<const Target*> targets_;
67 };
68
69 }  // namespace
70
71 TEST_F(HeaderCheckerTest, IsDependencyOf) {
72   scoped_refptr<HeaderChecker> checker(
73       new HeaderChecker(setup_.build_settings(), targets_));
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_permitted = false;
90   HeaderChecker::Chain chain;
91   EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_permitted));
92
93   // A depends publicly on B.
94   chain.clear();
95   is_permitted = false;
96   EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_permitted));
97   ASSERT_EQ(2u, chain.size());
98   EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[0]);
99   EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[1]);
100   EXPECT_TRUE(is_permitted);
101
102   // A indirectly depends on C. The "public" dependency path through B should
103   // be identified.
104   chain.clear();
105   is_permitted = false;
106   EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
107   ASSERT_EQ(3u, chain.size());
108   EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[0]);
109   EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[1]);
110   EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
111   EXPECT_TRUE(is_permitted);
112
113   // C does not depend on A.
114   chain.clear();
115   is_permitted = false;
116   EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_permitted));
117   EXPECT_TRUE(chain.empty());
118   EXPECT_FALSE(is_permitted);
119
120   // Remove the B -> C public dependency, leaving P's private dep on C the only
121   // path from A to C. This should now be found.
122   chain.clear();
123   EXPECT_EQ(&c_, b_.public_deps()[0].ptr);  // Validate it's the right one.
124   b_.public_deps().erase(b_.public_deps().begin());
125   EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
126   EXPECT_EQ(3u, chain.size());
127   EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
128   EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
129   EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
130   EXPECT_FALSE(is_permitted);
131
132   // P privately depends on C. That dependency should be OK since it's only
133   // one hop.
134   chain.clear();
135   is_permitted = false;
136   EXPECT_TRUE(checker->IsDependencyOf(&c_, &p, &chain, &is_permitted));
137   ASSERT_EQ(2u, chain.size());
138   EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
139   EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
140   EXPECT_TRUE(is_permitted);
141 }
142
143 TEST_F(HeaderCheckerTest, CheckInclude) {
144   InputFile input_file(SourceFile("//some_file.cc"));
145   input_file.SetContents(std::string());
146   LocationRange range;  // Dummy value.
147
148   // Add a disconnected target d with a header to check that you have to have
149   // to depend on a target listing a header.
150   SourceFile d_header("//d_header.h");
151   d_.sources().push_back(SourceFile(d_header));
152
153   // Add a header on B and say everything in B is public.
154   SourceFile b_public("//b_public.h");
155   b_.sources().push_back(b_public);
156   c_.set_all_headers_public(true);
157
158   // Add a public and private header on C.
159   SourceFile c_public("//c_public.h");
160   SourceFile c_private("//c_private.h");
161   c_.sources().push_back(c_private);
162   c_.public_headers().push_back(c_public);
163   c_.set_all_headers_public(false);
164
165   scoped_refptr<HeaderChecker> checker(
166       new HeaderChecker(setup_.build_settings(), targets_));
167
168   // A file in target A can't include a header from D because A has no
169   // dependency on D.
170   Err err;
171   EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err));
172   EXPECT_TRUE(err.has_error());
173
174   // A can include the public header in B.
175   err = Err();
176   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, b_public, range, &err));
177   EXPECT_FALSE(err.has_error());
178
179   // Check A depending on the public and private headers in C.
180   err = Err();
181   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
182   EXPECT_FALSE(err.has_error());
183   EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
184   EXPECT_TRUE(err.has_error());
185
186   // A can depend on a random file unknown to the build.
187   err = Err();
188   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"),
189                                     range, &err));
190   EXPECT_FALSE(err.has_error());
191 }
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
238 // Checks that the allow_circular_includes_from list works.
239 TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) {
240   InputFile input_file(SourceFile("//some_file.cc"));
241   input_file.SetContents(std::string());
242   LocationRange range;  // Dummy value.
243
244   // Add an include file to A.
245   SourceFile a_public("//a_public.h");
246   a_.sources().push_back(a_public);
247
248   scoped_refptr<HeaderChecker> checker(
249       new HeaderChecker(setup_.build_settings(), targets_));
250
251   // A depends on B. So B normally can't include headers from A.
252   Err err;
253   EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
254   EXPECT_TRUE(err.has_error());
255
256   // Add an allow_circular_includes_from on A that lists B.
257   a_.allow_circular_includes_from().insert(b_.label());
258
259   // Now the include from B to A should be allowed.
260   err = Err();
261   EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
262   EXPECT_FALSE(err.has_error());
263 }