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.
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "tools/gn/header_checker.h"
9 #include "tools/gn/scheduler.h"
10 #include "tools/gn/target.h"
11 #include "tools/gn/test_with_scope.h"
15 class HeaderCheckerTest
: public testing::Test
{
18 : a_(setup_
.settings(), Label(SourceDir("//a/"), "a")),
19 b_(setup_
.settings(), Label(SourceDir("//b/"), "a")),
20 c_(setup_
.settings(), Label(SourceDir("//c/"), "c")) {
21 a_
.deps().push_back(LabelTargetPair(&b_
));
22 b_
.deps().push_back(LabelTargetPair(&c_
));
24 // Start with all public visibility.
25 a_
.visibility().SetPublic();
26 b_
.visibility().SetPublic();
27 c_
.visibility().SetPublic();
29 targets_
.push_back(&a_
);
30 targets_
.push_back(&b_
);
31 targets_
.push_back(&c_
);
39 // Some headers that are automatically set up with a dependency chain.
45 std::vector
<const Target
*> targets_
;
50 TEST_F(HeaderCheckerTest
, IsDependencyOf
) {
51 scoped_refptr
<HeaderChecker
> checker(
52 new HeaderChecker(setup_
.build_settings(), targets_
));
54 std::vector
<const Target
*> chain
;
55 EXPECT_FALSE(checker
->IsDependencyOf(&a_
, &a_
, &chain
));
58 EXPECT_TRUE(checker
->IsDependencyOf(&b_
, &a_
, &chain
));
59 ASSERT_EQ(2u, chain
.size());
60 EXPECT_EQ(&b_
, chain
[0]);
61 EXPECT_EQ(&a_
, chain
[1]);
64 EXPECT_TRUE(checker
->IsDependencyOf(&c_
, &a_
, &chain
));
65 ASSERT_EQ(3u, chain
.size());
66 EXPECT_EQ(&c_
, chain
[0]);
67 EXPECT_EQ(&b_
, chain
[1]);
68 EXPECT_EQ(&a_
, chain
[2]);
71 EXPECT_FALSE(checker
->IsDependencyOf(&a_
, &c_
, &chain
));
72 EXPECT_TRUE(chain
.empty());
75 TEST_F(HeaderCheckerTest
, CheckInclude
) {
76 InputFile
input_file(SourceFile("//some_file.cc"));
77 input_file
.SetContents(std::string());
78 LocationRange range
; // Dummy value.
80 // Add a disconnected target d with a header to check that you have to have
81 // to depend on a target listing a header.
82 Target
d(setup_
.settings(), Label(SourceDir("//"), "d"));
83 SourceFile
d_header("//d_header.h");
84 d
.sources().push_back(SourceFile(d_header
));
86 // Add a header on B and say everything in B is public.
87 SourceFile
b_public("//b_public.h");
88 b_
.sources().push_back(b_public
);
89 c_
.set_all_headers_public(true);
91 // Add a public and private header on C.
92 SourceFile
c_public("//c_public.h");
93 SourceFile
c_private("//c_private.h");
94 c_
.sources().push_back(c_private
);
95 c_
.public_headers().push_back(c_public
);
96 c_
.set_all_headers_public(false);
98 targets_
.push_back(&d
);
99 scoped_refptr
<HeaderChecker
> checker(
100 new HeaderChecker(setup_
.build_settings(), targets_
));
102 // A file in target A can't include a header from D because A has no
105 EXPECT_FALSE(checker
->CheckInclude(&a_
, input_file
, d_header
, range
, &err
));
106 EXPECT_TRUE(err
.has_error());
108 // A can include the public header in B.
110 EXPECT_TRUE(checker
->CheckInclude(&a_
, input_file
, b_public
, range
, &err
));
111 EXPECT_FALSE(err
.has_error());
113 // Check A depending on the public and private headers in C.
115 EXPECT_TRUE(checker
->CheckInclude(&a_
, input_file
, c_public
, range
, &err
));
116 EXPECT_FALSE(err
.has_error());
117 EXPECT_FALSE(checker
->CheckInclude(&a_
, input_file
, c_private
, range
, &err
));
118 EXPECT_TRUE(err
.has_error());
120 // A can depend on a random file unknown to the build.
122 EXPECT_TRUE(checker
->CheckInclude(&a_
, input_file
, SourceFile("//random.h"),
124 EXPECT_FALSE(err
.has_error());
126 // If C is not visible from A, A can't include public headers even if there
127 // is a dependency path.
128 c_
.visibility().SetPrivate(c_
.label().dir());
130 EXPECT_FALSE(checker
->CheckInclude(&a_
, input_file
, c_public
, range
, &err
));
131 EXPECT_TRUE(err
.has_error());
134 TEST_F(HeaderCheckerTest
, DoDirectDependentConfigsApply
) {
135 // Assume we have a chain A -> B -> C -> D.
136 Target
target_a(setup_
.settings(), Label(SourceDir("//a/"), "a"));
137 Target
target_b(setup_
.settings(), Label(SourceDir("//b/"), "b"));
138 Target
target_c(setup_
.settings(), Label(SourceDir("//c/"), "c"));
139 Target
target_d(setup_
.settings(), Label(SourceDir("//d/"), "d"));
141 // 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
);
143 target_b
.set_output_type(Target::SOURCE_SET
);
144 target_c
.set_output_type(Target::GROUP
);
145 target_d
.set_output_type(Target::SOURCE_SET
);
146 target_b
.forward_dependent_configs().push_back(
147 LabelTargetPair(&target_c
));
149 // Dependency chain goes from bottom to top.
150 std::vector
<const Target
*> chain
;
151 chain
.push_back(&target_d
);
152 chain
.push_back(&target_c
);
153 chain
.push_back(&target_b
);
154 chain
.push_back(&target_a
);
156 // This chain should be valid.
158 EXPECT_TRUE(HeaderChecker::DoDirectDependentConfigsApply(chain
, &badone
));
160 // If C is not a group, it shouldn't work anymore.
161 target_c
.set_output_type(Target::SOURCE_SET
);
162 EXPECT_FALSE(HeaderChecker::DoDirectDependentConfigsApply(chain
, &badone
));
163 EXPECT_EQ(1u, badone
);
165 // Or if B stops forwarding from C, it shouldn't work anymore.
166 target_c
.set_output_type(Target::GROUP
);
168 target_b
.forward_dependent_configs().clear();
169 EXPECT_FALSE(HeaderChecker::DoDirectDependentConfigsApply(chain
, &badone
));
170 EXPECT_EQ(2u, badone
);