summaryrefslogtreecommitdiffstats
path: root/tools/gn/target_unittest.cc
blob: ef213b5286fa9d1ab9a064182280e742a057ea79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/gtest/include/gtest/gtest.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/config.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
#include "tools/gn/toolchain.h"

namespace {

class TargetTest : public testing::Test {
 public:
  TargetTest()
      : build_settings_(),
        settings_(&build_settings_, std::string()),
        toolchain_(&settings_, Label(SourceDir("//tc/"), "tc")) {
    settings_.set_toolchain_label(toolchain_.label());
  }
  virtual ~TargetTest() {
  }

 protected:
  BuildSettings build_settings_;
  Settings settings_;
  Toolchain toolchain_;
};

}  // namespace

// Tests that depending on a group is like depending directly on the group's
// deps.
TEST_F(TargetTest, GroupDeps) {
  // Two low-level targets.
  Target x(&settings_, Label(SourceDir("//component/"), "x"));
  Target y(&settings_, Label(SourceDir("//component/"), "y"));

  // Make a group for both x and y.
  Target g(&settings_, Label(SourceDir("//group/"), "g"));
  g.set_output_type(Target::GROUP);
  g.deps().push_back(LabelTargetPair(&x));
  g.deps().push_back(LabelTargetPair(&y));

  // Random placeholder target so we can see the group's deps get inserted at
  // the right place.
  Target b(&settings_, Label(SourceDir("//app/"), "b"));

  // Make a target depending on the group and "b". OnResolved will expand.
  Target a(&settings_, Label(SourceDir("//app/"), "a"));
  a.set_output_type(Target::EXECUTABLE);
  a.deps().push_back(LabelTargetPair(&g));
  a.deps().push_back(LabelTargetPair(&b));
  a.OnResolved();

  // The group's deps should be inserted after the group itself in the deps
  // list, so we should get "g, x, y, b"
  ASSERT_EQ(4u, a.deps().size());
  EXPECT_EQ(&g, a.deps()[0].ptr);
  EXPECT_EQ(&x, a.deps()[1].ptr);
  EXPECT_EQ(&y, a.deps()[2].ptr);
  EXPECT_EQ(&b, a.deps()[3].ptr);
}

// Tests that lib[_dir]s are inherited across deps boundaries for static
// libraries but not executables.
TEST_F(TargetTest, LibInheritance) {
  const std::string lib("foo");
  const SourceDir libdir("/foo_dir/");

  // Leaf target with ldflags set.
  Target z(&settings_, Label(SourceDir("//foo/"), "z"));
  z.set_output_type(Target::STATIC_LIBRARY);
  z.config_values().libs().push_back(lib);
  z.config_values().lib_dirs().push_back(libdir);
  z.OnResolved();

  // All lib[_dir]s should be set when target is resolved.
  ASSERT_EQ(1u, z.all_libs().size());
  EXPECT_EQ(lib, z.all_libs()[0]);
  ASSERT_EQ(1u, z.all_lib_dirs().size());
  EXPECT_EQ(libdir, z.all_lib_dirs()[0]);

  // Shared library target should inherit the libs from the static library
  // and its own. Its own flag should be before the inherited one.
  const std::string second_lib("bar");
  const SourceDir second_libdir("/bar_dir/");
  Target shared(&settings_, Label(SourceDir("//foo/"), "shared"));
  shared.set_output_type(Target::SHARED_LIBRARY);
  shared.config_values().libs().push_back(second_lib);
  shared.config_values().lib_dirs().push_back(second_libdir);
  shared.deps().push_back(LabelTargetPair(&z));
  shared.OnResolved();

  ASSERT_EQ(2u, shared.all_libs().size());
  EXPECT_EQ(second_lib, shared.all_libs()[0]);
  EXPECT_EQ(lib, shared.all_libs()[1]);
  ASSERT_EQ(2u, shared.all_lib_dirs().size());
  EXPECT_EQ(second_libdir, shared.all_lib_dirs()[0]);
  EXPECT_EQ(libdir, shared.all_lib_dirs()[1]);

  // Executable target shouldn't get either by depending on shared.
  Target exec(&settings_, Label(SourceDir("//foo/"), "exec"));
  exec.set_output_type(Target::EXECUTABLE);
  exec.deps().push_back(LabelTargetPair(&shared));
  exec.OnResolved();
  EXPECT_EQ(0u, exec.all_libs().size());
  EXPECT_EQ(0u, exec.all_lib_dirs().size());
}

// Test all/direct_dependent_configs inheritance, and
// forward_dependent_configs_from
TEST_F(TargetTest, DependentConfigs) {
  // Set up a dependency chain of a -> b -> c
  Target a(&settings_, Label(SourceDir("//foo/"), "a"));
  a.set_output_type(Target::EXECUTABLE);
  Target b(&settings_, Label(SourceDir("//foo/"), "b"));
  b.set_output_type(Target::STATIC_LIBRARY);
  Target c(&settings_, Label(SourceDir("//foo/"), "c"));
  c.set_output_type(Target::STATIC_LIBRARY);
  a.deps().push_back(LabelTargetPair(&b));
  b.deps().push_back(LabelTargetPair(&c));

  // Normal non-inherited config.
  Config config(&settings_, Label(SourceDir("//foo/"), "config"));
  c.configs().push_back(LabelConfigPair(&config));

  // All dependent config.
  Config all(&settings_, Label(SourceDir("//foo/"), "all"));
  c.all_dependent_configs().push_back(LabelConfigPair(&all));

  // Direct dependent config.
  Config direct(&settings_, Label(SourceDir("//foo/"), "direct"));
  c.direct_dependent_configs().push_back(LabelConfigPair(&direct));

  c.OnResolved();
  b.OnResolved();
  a.OnResolved();

  // B should have gotten both dependent configs from C.
  ASSERT_EQ(2u, b.configs().size());
  EXPECT_EQ(&all, b.configs()[0].ptr);
  EXPECT_EQ(&direct, b.configs()[1].ptr);
  ASSERT_EQ(1u, b.all_dependent_configs().size());
  EXPECT_EQ(&all, b.all_dependent_configs()[0].ptr);

  // A should have just gotten the "all" dependent config from C.
  ASSERT_EQ(1u, a.configs().size());
  EXPECT_EQ(&all, a.configs()[0].ptr);
  EXPECT_EQ(&all, a.all_dependent_configs()[0].ptr);

  // Making an an alternate A and B with B forwarding the direct dependents.
  Target a_fwd(&settings_, Label(SourceDir("//foo/"), "a_fwd"));
  a_fwd.set_output_type(Target::EXECUTABLE);
  Target b_fwd(&settings_, Label(SourceDir("//foo/"), "b_fwd"));
  b_fwd.set_output_type(Target::STATIC_LIBRARY);
  a_fwd.deps().push_back(LabelTargetPair(&b_fwd));
  b_fwd.deps().push_back(LabelTargetPair(&c));
  b_fwd.forward_dependent_configs().push_back(LabelTargetPair(&c));

  b_fwd.OnResolved();
  a_fwd.OnResolved();

  // A_fwd should now have both configs.
  ASSERT_EQ(2u, a_fwd.configs().size());
  EXPECT_EQ(&all, a_fwd.configs()[0].ptr);
  EXPECT_EQ(&direct, a_fwd.configs()[1].ptr);
  ASSERT_EQ(1u, a_fwd.all_dependent_configs().size());
  EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr);
}