Upstream version 9.38.198.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/"), "a")),
21         c_(setup_.settings(), Label(SourceDir("//c/"), "c")),
22         d_(setup_.settings(), Label(SourceDir("//d/"), "d")) {
23     a_.deps().push_back(LabelTargetPair(&b_));
24     b_.deps().push_back(LabelTargetPair(&c_));
25
26     // Start with all public visibility.
27     a_.visibility().SetPublic();
28     b_.visibility().SetPublic();
29     c_.visibility().SetPublic();
30     d_.visibility().SetPublic();
31
32     targets_.push_back(&a_);
33     targets_.push_back(&b_);
34     targets_.push_back(&c_);
35     targets_.push_back(&d_);
36   }
37
38  protected:
39   Scheduler scheduler_;
40
41   TestWithScope setup_;
42
43   // Some headers that are automatically set up with a dependency chain.
44   // a -> b -> c
45   Target a_;
46   Target b_;
47   Target c_;
48   Target d_;
49
50   std::vector<const Target*> targets_;
51 };
52
53 }  // namespace
54
55 TEST_F(HeaderCheckerTest, IsDependencyOf) {
56   scoped_refptr<HeaderChecker> checker(
57       new HeaderChecker(setup_.build_settings(), targets_));
58
59   std::vector<const Target*> chain;
60   EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, false, &chain, NULL));
61
62   chain.clear();
63   EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, false, &chain, NULL));
64   ASSERT_EQ(2u, chain.size());
65   EXPECT_EQ(&b_, chain[0]);
66   EXPECT_EQ(&a_, chain[1]);
67
68   chain.clear();
69   EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, false, &chain, NULL));
70   ASSERT_EQ(3u, chain.size());
71   EXPECT_EQ(&c_, chain[0]);
72   EXPECT_EQ(&b_, chain[1]);
73   EXPECT_EQ(&a_, chain[2]);
74
75   chain.clear();
76   EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, false, &chain, NULL));
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]);
142 }
143
144 TEST_F(HeaderCheckerTest, CheckInclude) {
145   InputFile input_file(SourceFile("//some_file.cc"));
146   input_file.SetContents(std::string());
147   LocationRange range;  // Dummy value.
148
149   // Add a disconnected target d with a header to check that you have to have
150   // to depend on a target listing a header.
151   SourceFile d_header("//d_header.h");
152   d_.sources().push_back(SourceFile(d_header));
153
154   // Add a header on B and say everything in B is public.
155   SourceFile b_public("//b_public.h");
156   b_.sources().push_back(b_public);
157   c_.set_all_headers_public(true);
158
159   // Add a public and private header on C.
160   SourceFile c_public("//c_public.h");
161   SourceFile c_private("//c_private.h");
162   c_.sources().push_back(c_private);
163   c_.public_headers().push_back(c_public);
164   c_.set_all_headers_public(false);
165
166   targets_.push_back(&d_);
167   scoped_refptr<HeaderChecker> checker(
168       new HeaderChecker(setup_.build_settings(), targets_));
169
170   // A file in target A can't include a header from D because A has no
171   // dependency on D.
172   Err err;
173   EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err));
174   EXPECT_TRUE(err.has_error());
175
176   // A can include the public header in B.
177   err = Err();
178   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, b_public, range, &err));
179   EXPECT_FALSE(err.has_error());
180
181   // Check A depending on the public and private headers in C.
182   err = Err();
183   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
184   EXPECT_FALSE(err.has_error());
185   EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
186   EXPECT_TRUE(err.has_error());
187
188   // A can depend on a random file unknown to the build.
189   err = Err();
190   EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"),
191                                     range, &err));
192   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 }
228
229 TEST_F(HeaderCheckerTest, GetDependentConfigChainProblemIndex) {
230   // Assume we have a chain A -> B -> C -> D.
231   Target target_a(setup_.settings(), Label(SourceDir("//a/"), "a"));
232   Target target_b(setup_.settings(), Label(SourceDir("//b/"), "b"));
233   Target target_c(setup_.settings(), Label(SourceDir("//c/"), "c"));
234   Target target_d(setup_.settings(), Label(SourceDir("//d/"), "d"));
235
236   // C is a group, and B forwards deps from C, so A should get configs from D.
237   target_a.set_output_type(Target::SOURCE_SET);
238   target_b.set_output_type(Target::SOURCE_SET);
239   target_c.set_output_type(Target::GROUP);
240   target_d.set_output_type(Target::SOURCE_SET);
241   target_b.forward_dependent_configs().push_back(
242       LabelTargetPair(&target_c));
243
244   // Dependency chain goes from bottom to top.
245   std::vector<const Target*> chain;
246   chain.push_back(&target_d);
247   chain.push_back(&target_c);
248   chain.push_back(&target_b);
249   chain.push_back(&target_a);
250
251   // If C is not a group, it shouldn't work anymore.
252   target_c.set_output_type(Target::SOURCE_SET);
253   EXPECT_EQ(1u, HeaderChecker::GetDependentConfigChainProblemIndex(chain));
254
255   // Or if B stops forwarding from C, it shouldn't work anymore.
256   target_c.set_output_type(Target::GROUP);
257   target_b.forward_dependent_configs().clear();
258   EXPECT_EQ(2u, HeaderChecker::GetDependentConfigChainProblemIndex(chain));
259 }