summaryrefslogtreecommitdiffstats
path: root/tools/gn/target_unittest.cc
diff options
context:
space:
mode:
authorBrett Wilson <brettw@chromium.org>2014-09-02 12:29:42 -0700
committerBrett Wilson <brettw@chromium.org>2014-09-02 19:44:38 +0000
commit85423a03bb323c0660c402d3a1f62169ca696dd8 (patch)
treea05c749a63bc0e81ac714d81639e368392cc2e9f /tools/gn/target_unittest.cc
parentd2787a392a65c1172ad64e9a13e77e023d9b8d31 (diff)
downloadchromium_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.cc155
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));
+}