diff options
author | Brett Wilson <brettw@chromium.org> | 2014-09-02 12:29:42 -0700 |
---|---|---|
committer | Brett Wilson <brettw@chromium.org> | 2014-09-02 19:44:38 +0000 |
commit | 85423a03bb323c0660c402d3a1f62169ca696dd8 (patch) | |
tree | a05c749a63bc0e81ac714d81639e368392cc2e9f /tools/gn/target_unittest.cc | |
parent | d2787a392a65c1172ad64e9a13e77e023d9b8d31 (diff) | |
download | chromium_src-85423a03bb323c0660c402d3a1f62169ca696dd8.zip chromium_src-85423a03bb323c0660c402d3a1f62169ca696dd8.tar.gz chromium_src-85423a03bb323c0660c402d3a1f62169ca696dd8.tar.bz2 |
Add testonly flag to GN
This also reworks visibility so both it and the testonly flag are checked when
a target is marked resolved, rather than when it is written out. The previous
code would not check visibility when doing non-"gen" commands like "check",
which is counterintuitive.
This change required OnResolved to be able to report a failure, which required
updating many callers. But it makes visibility mush easier to test, so I
added some additional visibility tests.
BUG=357779
R=hclam@chromium.org
Review URL: https://codereview.chromium.org/524623005
Cr-Commit-Position: refs/heads/master@{#292976}
Diffstat (limited to 'tools/gn/target_unittest.cc')
-rw-r--r-- | tools/gn/target_unittest.cc | 155 |
1 files changed, 132 insertions, 23 deletions
diff --git a/tools/gn/target_unittest.cc b/tools/gn/target_unittest.cc index 9bf0c30..25e3aab 100644 --- a/tools/gn/target_unittest.cc +++ b/tools/gn/target_unittest.cc @@ -14,37 +14,47 @@ // deps. TEST(Target, GroupDeps) { TestWithScope setup; + Err err; + + // Used as the origin for the not-automatically-set deps. + IdentifierNode origin; // Two low-level targets. Target x(setup.settings(), Label(SourceDir("//component/"), "x")); x.set_output_type(Target::STATIC_LIBRARY); x.SetToolchain(setup.toolchain()); - x.OnResolved(); + ASSERT_TRUE(x.OnResolved(&err)); Target y(setup.settings(), Label(SourceDir("//component/"), "y")); y.set_output_type(Target::STATIC_LIBRARY); y.SetToolchain(setup.toolchain()); - y.OnResolved(); + ASSERT_TRUE(y.OnResolved(&err)); // Make a group for both x and y. Target g(setup.settings(), Label(SourceDir("//group/"), "g")); g.set_output_type(Target::GROUP); + g.visibility().SetPublic(); g.deps().push_back(LabelTargetPair(&x)); + g.deps()[0].origin = &origin; g.deps().push_back(LabelTargetPair(&y)); + g.deps()[1].origin = &origin; // Random placeholder target so we can see the group's deps get inserted at // the right place. Target b(setup.settings(), Label(SourceDir("//app/"), "b")); b.set_output_type(Target::STATIC_LIBRARY); b.SetToolchain(setup.toolchain()); - b.OnResolved(); + b.visibility().SetPublic(); + ASSERT_TRUE(b.OnResolved(&err)); // Make a target depending on the group and "b". OnResolved will expand. Target a(setup.settings(), Label(SourceDir("//app/"), "a")); a.set_output_type(Target::EXECUTABLE); a.deps().push_back(LabelTargetPair(&g)); + a.deps()[0].origin = &origin; a.deps().push_back(LabelTargetPair(&b)); + a.deps()[1].origin = &origin; a.SetToolchain(setup.toolchain()); - a.OnResolved(); + ASSERT_TRUE(a.OnResolved(&err)); // The group's deps should be inserted after the group itself in the deps // list, so we should get "g, x, y, b" @@ -53,12 +63,20 @@ TEST(Target, GroupDeps) { EXPECT_EQ(&x, a.deps()[1].ptr); EXPECT_EQ(&y, a.deps()[2].ptr); EXPECT_EQ(&b, a.deps()[3].ptr); + + // The "regular" deps on a should have the origin set. The automatically + // expanded ones will have a null origin so we know they are generated. + EXPECT_EQ(&origin, a.deps()[0].origin); + EXPECT_EQ(NULL, a.deps()[1].origin); + EXPECT_EQ(NULL, a.deps()[2].origin); + EXPECT_EQ(&origin, a.deps()[3].origin); } // Tests that lib[_dir]s are inherited across deps boundaries for static // libraries but not executables. TEST(Target, LibInheritance) { TestWithScope setup; + Err err; const std::string lib("foo"); const SourceDir libdir("/foo_dir/"); @@ -69,7 +87,7 @@ TEST(Target, LibInheritance) { z.config_values().libs().push_back(lib); z.config_values().lib_dirs().push_back(libdir); z.SetToolchain(setup.toolchain()); - z.OnResolved(); + ASSERT_TRUE(z.OnResolved(&err)); // All lib[_dir]s should be set when target is resolved. ASSERT_EQ(1u, z.all_libs().size()); @@ -87,7 +105,7 @@ TEST(Target, LibInheritance) { shared.config_values().lib_dirs().push_back(second_libdir); shared.deps().push_back(LabelTargetPair(&z)); shared.SetToolchain(setup.toolchain()); - shared.OnResolved(); + ASSERT_TRUE(shared.OnResolved(&err)); ASSERT_EQ(2u, shared.all_libs().size()); EXPECT_EQ(second_lib, shared.all_libs()[0]); @@ -101,7 +119,7 @@ TEST(Target, LibInheritance) { exec.set_output_type(Target::EXECUTABLE); exec.deps().push_back(LabelTargetPair(&shared)); exec.SetToolchain(setup.toolchain()); - exec.OnResolved(); + ASSERT_TRUE(exec.OnResolved(&err)); EXPECT_EQ(0u, exec.all_libs().size()); EXPECT_EQ(0u, exec.all_lib_dirs().size()); } @@ -110,6 +128,7 @@ TEST(Target, LibInheritance) { // forward_dependent_configs_from TEST(Target, DependentConfigs) { TestWithScope setup; + Err err; // Set up a dependency chain of a -> b -> c Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); @@ -136,9 +155,9 @@ TEST(Target, DependentConfigs) { Config direct(setup.settings(), Label(SourceDir("//foo/"), "direct")); c.direct_dependent_configs().push_back(LabelConfigPair(&direct)); - c.OnResolved(); - b.OnResolved(); - a.OnResolved(); + ASSERT_TRUE(c.OnResolved(&err)); + ASSERT_TRUE(b.OnResolved(&err)); + ASSERT_TRUE(a.OnResolved(&err)); // B should have gotten both dependent configs from C. ASSERT_EQ(2u, b.configs().size()); @@ -163,8 +182,8 @@ TEST(Target, DependentConfigs) { b_fwd.deps().push_back(LabelTargetPair(&c)); b_fwd.forward_dependent_configs().push_back(LabelTargetPair(&c)); - b_fwd.OnResolved(); - a_fwd.OnResolved(); + ASSERT_TRUE(b_fwd.OnResolved(&err)); + ASSERT_TRUE(a_fwd.OnResolved(&err)); // A_fwd should now have both configs. ASSERT_EQ(2u, a_fwd.configs().size()); @@ -178,6 +197,7 @@ TEST(Target, DependentConfigs) { // group's deps' dependent configs. TEST(Target, ForwardDependentConfigsFromGroups) { TestWithScope setup; + Err err; Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); a.set_output_type(Target::EXECUTABLE); @@ -198,9 +218,9 @@ TEST(Target, ForwardDependentConfigsFromGroups) { // A forwards the dependent configs from B. a.forward_dependent_configs().push_back(LabelTargetPair(&b)); - c.OnResolved(); - b.OnResolved(); - a.OnResolved(); + ASSERT_TRUE(c.OnResolved(&err)); + ASSERT_TRUE(b.OnResolved(&err)); + ASSERT_TRUE(a.OnResolved(&err)); // The config should now be on A, and in A's direct dependent configs. ASSERT_EQ(1u, a.configs().size()); @@ -211,6 +231,7 @@ TEST(Target, ForwardDependentConfigsFromGroups) { TEST(Target, InheritLibs) { TestWithScope setup; + Err err; // Create a dependency chain: // A (executable) -> B (shared lib) -> C (static lib) -> D (source set) @@ -230,10 +251,10 @@ TEST(Target, InheritLibs) { b.deps().push_back(LabelTargetPair(&c)); c.deps().push_back(LabelTargetPair(&d)); - d.OnResolved(); - c.OnResolved(); - b.OnResolved(); - a.OnResolved(); + ASSERT_TRUE(d.OnResolved(&err)); + ASSERT_TRUE(c.OnResolved(&err)); + ASSERT_TRUE(b.OnResolved(&err)); + ASSERT_TRUE(a.OnResolved(&err)); // C should have D in its inherited libs. const UniqueVector<const Target*>& c_inherited = c.inherited_libraries(); @@ -255,13 +276,14 @@ TEST(Target, InheritLibs) { TEST(Target, GetComputedOutputName) { TestWithScope setup; + Err err; // Basic target with no prefix (executable type tool in the TestWithScope has // no prefix) or output name. Target basic(setup.settings(), Label(SourceDir("//foo/"), "bar")); basic.set_output_type(Target::EXECUTABLE); basic.SetToolchain(setup.toolchain()); - basic.OnResolved(); + ASSERT_TRUE(basic.OnResolved(&err)); EXPECT_EQ("bar", basic.GetComputedOutputName(false)); EXPECT_EQ("bar", basic.GetComputedOutputName(true)); @@ -270,7 +292,7 @@ TEST(Target, GetComputedOutputName) { with_name.set_output_type(Target::EXECUTABLE); with_name.set_output_name("myoutput"); with_name.SetToolchain(setup.toolchain()); - with_name.OnResolved(); + ASSERT_TRUE(with_name.OnResolved(&err)); EXPECT_EQ("myoutput", with_name.GetComputedOutputName(false)); EXPECT_EQ("myoutput", with_name.GetComputedOutputName(true)); @@ -279,7 +301,7 @@ TEST(Target, GetComputedOutputName) { Target with_prefix(setup.settings(), Label(SourceDir("//foo/"), "bar")); with_prefix.set_output_type(Target::STATIC_LIBRARY); with_prefix.SetToolchain(setup.toolchain()); - with_prefix.OnResolved(); + ASSERT_TRUE(with_prefix.OnResolved(&err)); EXPECT_EQ("bar", with_prefix.GetComputedOutputName(false)); EXPECT_EQ("libbar", with_prefix.GetComputedOutputName(true)); @@ -289,7 +311,94 @@ TEST(Target, GetComputedOutputName) { dup_prefix.set_output_type(Target::STATIC_LIBRARY); dup_prefix.set_output_name("libbar"); dup_prefix.SetToolchain(setup.toolchain()); - dup_prefix.OnResolved(); + ASSERT_TRUE(dup_prefix.OnResolved(&err)); EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName(false)); EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName(true)); } + +// Test visibility failure case. +TEST(Target, VisibilityFails) { + TestWithScope setup; + Err err; + + Target b(setup.settings(), Label(SourceDir("//private/"), "b")); + b.set_output_type(Target::STATIC_LIBRARY); + b.SetToolchain(setup.toolchain()); + b.visibility().SetPrivate(b.label().dir()); + ASSERT_TRUE(b.OnResolved(&err)); + + // Make a target depending on "b". The dependency must have an origin to mark + // it as user-set so we check visibility. This check should fail. + Target a(setup.settings(), Label(SourceDir("//app/"), "a")); + a.set_output_type(Target::EXECUTABLE); + a.deps().push_back(LabelTargetPair(&b)); + IdentifierNode origin; // Dummy origin. + a.deps()[0].origin = &origin; + a.SetToolchain(setup.toolchain()); + ASSERT_FALSE(a.OnResolved(&err)); +} + +// Tests that A -> Group -> B where the group is visible from A but B isn't, +// passes visibility even though the group's deps get expanded into A. +TEST(Target, VisibilityGroup) { + TestWithScope setup; + Err err; + + IdentifierNode origin; // Dummy origin. + + // B has private visibility. This lets the group see it since the group is in + // the same directory. + Target b(setup.settings(), Label(SourceDir("//private/"), "b")); + b.set_output_type(Target::STATIC_LIBRARY); + b.SetToolchain(setup.toolchain()); + b.visibility().SetPrivate(b.label().dir()); + ASSERT_TRUE(b.OnResolved(&err)); + + // The group has public visibility and depends on b. + Target g(setup.settings(), Label(SourceDir("//private/"), "g")); + g.set_output_type(Target::GROUP); + g.SetToolchain(setup.toolchain()); + g.deps().push_back(LabelTargetPair(&b)); + g.deps()[0].origin = &origin; + g.visibility().SetPublic(); + ASSERT_TRUE(b.OnResolved(&err)); + + // Make a target depending on "g". This should succeed. + Target a(setup.settings(), Label(SourceDir("//app/"), "a")); + a.set_output_type(Target::EXECUTABLE); + a.deps().push_back(LabelTargetPair(&g)); + a.deps()[0].origin = &origin; + a.SetToolchain(setup.toolchain()); + ASSERT_TRUE(a.OnResolved(&err)); +} + +// Verifies that only testonly targets can depend on other testonly targets. +// Many of the above dependency checking cases covered the non-testonly +// case. +TEST(Target, Testonly) { + TestWithScope setup; + Err err; + + // "testlib" is a test-only library. + Target testlib(setup.settings(), Label(SourceDir("//test/"), "testlib")); + testlib.set_testonly(true); + testlib.set_output_type(Target::STATIC_LIBRARY); + testlib.SetToolchain(setup.toolchain()); + ASSERT_TRUE(testlib.OnResolved(&err)); + + // "test" is a test-only executable depending on testlib, this is OK. + Target test(setup.settings(), Label(SourceDir("//test/"), "test")); + test.set_testonly(true); + test.set_output_type(Target::EXECUTABLE); + test.deps().push_back(LabelTargetPair(&testlib)); + test.SetToolchain(setup.toolchain()); + ASSERT_TRUE(test.OnResolved(&err)); + + // "product" is a non-test depending on testlib. This should fail. + Target product(setup.settings(), Label(SourceDir("//app/"), "product")); + product.set_testonly(false); + product.set_output_type(Target::EXECUTABLE); + product.deps().push_back(LabelTargetPair(&testlib)); + product.SetToolchain(setup.toolchain()); + ASSERT_FALSE(product.OnResolved(&err)); +} |