Index: tools/gn/header_checker_unittest.cc |
diff --git a/tools/gn/header_checker_unittest.cc b/tools/gn/header_checker_unittest.cc |
index dd1ce24351489f572d4feb5d41beaca153ce72d5..e445a692ef6bcbb35cc23db1270bfb99c4d01745 100644 |
--- a/tools/gn/header_checker_unittest.cc |
+++ b/tools/gn/header_checker_unittest.cc |
@@ -56,8 +56,8 @@ class HeaderCheckerTest : public testing::Test { |
TestWithScope setup_; |
- // Some headers that are automatically set up with a dependency chain. |
- // a -> b -> c |
+ // Some headers that are automatically set up with a public dependency chain. |
+ // a -> b -> c. D is unconnected. |
Target a_; |
Target b_; |
Target c_; |
@@ -86,57 +86,58 @@ TEST_F(HeaderCheckerTest, IsDependencyOf) { |
a_.public_deps().push_back(LabelTargetPair(&p)); |
// A does not depend on itself. |
- bool is_public = false; |
- std::vector<const Target*> chain; |
- EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_public)); |
+ bool is_permitted = false; |
+ HeaderChecker::Chain chain; |
+ EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_permitted)); |
- // A depends on B. |
+ // A depends publicly on B. |
chain.clear(); |
- is_public = false; |
- EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_public)); |
+ is_permitted = false; |
+ EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_permitted)); |
ASSERT_EQ(2u, chain.size()); |
- EXPECT_EQ(&b_, chain[0]); |
- EXPECT_EQ(&a_, chain[1]); |
- EXPECT_TRUE(is_public); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[1]); |
+ EXPECT_TRUE(is_permitted); |
// A indirectly depends on C. The "public" dependency path through B should |
// be identified. |
chain.clear(); |
- is_public = false; |
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); |
+ is_permitted = false; |
+ EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted)); |
ASSERT_EQ(3u, chain.size()); |
- EXPECT_EQ(&c_, chain[0]); |
- EXPECT_EQ(&b_, chain[1]); |
- EXPECT_EQ(&a_, chain[2]); |
- EXPECT_TRUE(is_public); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[1]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]); |
+ EXPECT_TRUE(is_permitted); |
// C does not depend on A. |
chain.clear(); |
- is_public = false; |
- EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_public)); |
+ is_permitted = false; |
+ EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_permitted)); |
EXPECT_TRUE(chain.empty()); |
- EXPECT_FALSE(is_public); |
+ EXPECT_FALSE(is_permitted); |
- // Add a private A -> C dependency. This should not be detected since it's |
- // private, even though it's shorter than the A -> B -> C one. |
+ // Remove the B -> C public dependency, leaving P's private dep on C the only |
+ // path from A to C. This should now be found. |
chain.clear(); |
- is_public = false; |
- a_.private_deps().push_back(LabelTargetPair(&c_)); |
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); |
- EXPECT_EQ(&c_, chain[0]); |
- EXPECT_EQ(&b_, chain[1]); |
- EXPECT_EQ(&a_, chain[2]); |
- EXPECT_TRUE(is_public); |
- |
- // Remove the B -> C public dependency, leaving A's private dep on C the only |
- // path. This should now be found. |
- chain.clear(); |
- EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one. |
+ EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one. |
b_.public_deps().erase(b_.public_deps().begin()); |
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_public)); |
- EXPECT_EQ(&c_, chain[0]); |
- EXPECT_EQ(&a_, chain[1]); |
- EXPECT_FALSE(is_public); |
+ EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted)); |
+ EXPECT_EQ(3u, chain.size()); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]); |
+ EXPECT_FALSE(is_permitted); |
+ |
+ // P privately depends on C. That dependency should be OK since it's only |
+ // one hop. |
+ chain.clear(); |
+ is_permitted = false; |
+ EXPECT_TRUE(checker->IsDependencyOf(&c_, &p, &chain, &is_permitted)); |
+ ASSERT_EQ(2u, chain.size()); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]); |
+ EXPECT_TRUE(is_permitted); |
} |
TEST_F(HeaderCheckerTest, CheckInclude) { |
@@ -161,7 +162,6 @@ TEST_F(HeaderCheckerTest, CheckInclude) { |
c_.public_headers().push_back(c_public); |
c_.set_all_headers_public(false); |
- targets_.push_back(&d_); |
scoped_refptr<HeaderChecker> checker( |
new HeaderChecker(setup_.build_settings(), targets_)); |
@@ -190,6 +190,51 @@ TEST_F(HeaderCheckerTest, CheckInclude) { |
EXPECT_FALSE(err.has_error()); |
} |
+// A public chain of dependencies should always be identified first, even if |
+// it is longer than a private one. |
+TEST_F(HeaderCheckerTest, PublicFirst) { |
+ // Now make a A -> Z -> D private dependency chain (one shorter than the |
+ // public one to get to D). |
+ Target z(setup_.settings(), Label(SourceDir("//a/"), "a")); |
+ z.set_output_type(Target::SOURCE_SET); |
+ Err err; |
+ EXPECT_TRUE(z.SetToolchain(setup_.toolchain(), &err)); |
+ z.private_deps().push_back(LabelTargetPair(&d_)); |
+ EXPECT_TRUE(z.OnResolved(&err)); |
+ targets_.push_back(&z); |
+ |
+ a_.private_deps().push_back(LabelTargetPair(&z)); |
+ |
+ // Check that D can be found from A, but since it's private, it will be |
+ // marked as not permitted. |
+ bool is_permitted = false; |
+ HeaderChecker::Chain chain; |
+ scoped_refptr<HeaderChecker> checker( |
+ new HeaderChecker(setup_.build_settings(), targets_)); |
+ EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted)); |
+ |
+ EXPECT_FALSE(is_permitted); |
+ ASSERT_EQ(3u, chain.size()); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&d_, false), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&z, false), chain[1]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]); |
+ |
+ // Hook up D to the existing public A -> B -> C chain to make a long one, and |
+ // search for D again. |
+ c_.public_deps().push_back(LabelTargetPair(&d_)); |
+ checker = new HeaderChecker(setup_.build_settings(), targets_); |
+ chain.clear(); |
+ EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted)); |
+ |
+ // This should have found the long public one. |
+ EXPECT_TRUE(is_permitted); |
+ ASSERT_EQ(4u, chain.size()); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&d_, true), chain[0]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[1]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[2]); |
+ EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[3]); |
+} |
+ |
// Checks that the allow_circular_includes_from list works. |
TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) { |
InputFile input_file(SourceFile("//some_file.cc")); |