1// Copyright (c) 2013 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.
4
5#include "testing/gtest/include/gtest/gtest.h"
6#include "tools/gn/build_settings.h"
7#include "tools/gn/config.h"
8#include "tools/gn/settings.h"
9#include "tools/gn/target.h"
10#include "tools/gn/toolchain.h"
11
12namespace {
13
14class TargetTest : public testing::Test {
15 public:
16  TargetTest()
17      : build_settings_(),
18        settings_(&build_settings_, std::string()),
19        toolchain_(&settings_, Label(SourceDir("//tc/"), "tc")) {
20    settings_.set_toolchain_label(toolchain_.label());
21  }
22  virtual ~TargetTest() {
23  }
24
25 protected:
26  BuildSettings build_settings_;
27  Settings settings_;
28  Toolchain toolchain_;
29};
30
31}  // namespace
32
33// Tests that depending on a group is like depending directly on the group's
34// deps.
35TEST_F(TargetTest, GroupDeps) {
36  // Two low-level targets.
37  Target x(&settings_, Label(SourceDir("//component/"), "x"));
38  Target y(&settings_, Label(SourceDir("//component/"), "y"));
39
40  // Make a group for both x and y.
41  Target g(&settings_, Label(SourceDir("//group/"), "g"));
42  g.set_output_type(Target::GROUP);
43  g.deps().push_back(LabelTargetPair(&x));
44  g.deps().push_back(LabelTargetPair(&y));
45
46  // Random placeholder target so we can see the group's deps get inserted at
47  // the right place.
48  Target b(&settings_, Label(SourceDir("//app/"), "b"));
49
50  // Make a target depending on the group and "b". OnResolved will expand.
51  Target a(&settings_, Label(SourceDir("//app/"), "a"));
52  a.set_output_type(Target::EXECUTABLE);
53  a.deps().push_back(LabelTargetPair(&g));
54  a.deps().push_back(LabelTargetPair(&b));
55  a.OnResolved();
56
57  // The group's deps should be inserted after the group itself in the deps
58  // list, so we should get "g, x, y, b"
59  ASSERT_EQ(4u, a.deps().size());
60  EXPECT_EQ(&g, a.deps()[0].ptr);
61  EXPECT_EQ(&x, a.deps()[1].ptr);
62  EXPECT_EQ(&y, a.deps()[2].ptr);
63  EXPECT_EQ(&b, a.deps()[3].ptr);
64}
65
66// Tests that lib[_dir]s are inherited across deps boundaries for static
67// libraries but not executables.
68TEST_F(TargetTest, LibInheritance) {
69  const std::string lib("foo");
70  const SourceDir libdir("/foo_dir/");
71
72  // Leaf target with ldflags set.
73  Target z(&settings_, Label(SourceDir("//foo/"), "z"));
74  z.set_output_type(Target::STATIC_LIBRARY);
75  z.config_values().libs().push_back(lib);
76  z.config_values().lib_dirs().push_back(libdir);
77  z.OnResolved();
78
79  // All lib[_dir]s should be set when target is resolved.
80  ASSERT_EQ(1u, z.all_libs().size());
81  EXPECT_EQ(lib, z.all_libs()[0]);
82  ASSERT_EQ(1u, z.all_lib_dirs().size());
83  EXPECT_EQ(libdir, z.all_lib_dirs()[0]);
84
85  // Shared library target should inherit the libs from the static library
86  // and its own. Its own flag should be before the inherited one.
87  const std::string second_lib("bar");
88  const SourceDir second_libdir("/bar_dir/");
89  Target shared(&settings_, Label(SourceDir("//foo/"), "shared"));
90  shared.set_output_type(Target::SHARED_LIBRARY);
91  shared.config_values().libs().push_back(second_lib);
92  shared.config_values().lib_dirs().push_back(second_libdir);
93  shared.deps().push_back(LabelTargetPair(&z));
94  shared.OnResolved();
95
96  ASSERT_EQ(2u, shared.all_libs().size());
97  EXPECT_EQ(second_lib, shared.all_libs()[0]);
98  EXPECT_EQ(lib, shared.all_libs()[1]);
99  ASSERT_EQ(2u, shared.all_lib_dirs().size());
100  EXPECT_EQ(second_libdir, shared.all_lib_dirs()[0]);
101  EXPECT_EQ(libdir, shared.all_lib_dirs()[1]);
102
103  // Executable target shouldn't get either by depending on shared.
104  Target exec(&settings_, Label(SourceDir("//foo/"), "exec"));
105  exec.set_output_type(Target::EXECUTABLE);
106  exec.deps().push_back(LabelTargetPair(&shared));
107  exec.OnResolved();
108  EXPECT_EQ(0u, exec.all_libs().size());
109  EXPECT_EQ(0u, exec.all_lib_dirs().size());
110}
111
112// Test all/direct_dependent_configs inheritance, and
113// forward_dependent_configs_from
114TEST_F(TargetTest, DependentConfigs) {
115  // Set up a dependency chain of a -> b -> c
116  Target a(&settings_, Label(SourceDir("//foo/"), "a"));
117  a.set_output_type(Target::EXECUTABLE);
118  Target b(&settings_, Label(SourceDir("//foo/"), "b"));
119  b.set_output_type(Target::STATIC_LIBRARY);
120  Target c(&settings_, Label(SourceDir("//foo/"), "c"));
121  c.set_output_type(Target::STATIC_LIBRARY);
122  a.deps().push_back(LabelTargetPair(&b));
123  b.deps().push_back(LabelTargetPair(&c));
124
125  // Normal non-inherited config.
126  Config config(&settings_, Label(SourceDir("//foo/"), "config"));
127  c.configs().push_back(LabelConfigPair(&config));
128
129  // All dependent config.
130  Config all(&settings_, Label(SourceDir("//foo/"), "all"));
131  c.all_dependent_configs().push_back(LabelConfigPair(&all));
132
133  // Direct dependent config.
134  Config direct(&settings_, Label(SourceDir("//foo/"), "direct"));
135  c.direct_dependent_configs().push_back(LabelConfigPair(&direct));
136
137  c.OnResolved();
138  b.OnResolved();
139  a.OnResolved();
140
141  // B should have gotten both dependent configs from C.
142  ASSERT_EQ(2u, b.configs().size());
143  EXPECT_EQ(&all, b.configs()[0].ptr);
144  EXPECT_EQ(&direct, b.configs()[1].ptr);
145  ASSERT_EQ(1u, b.all_dependent_configs().size());
146  EXPECT_EQ(&all, b.all_dependent_configs()[0].ptr);
147
148  // A should have just gotten the "all" dependent config from C.
149  ASSERT_EQ(1u, a.configs().size());
150  EXPECT_EQ(&all, a.configs()[0].ptr);
151  EXPECT_EQ(&all, a.all_dependent_configs()[0].ptr);
152
153  // Making an an alternate A and B with B forwarding the direct dependents.
154  Target a_fwd(&settings_, Label(SourceDir("//foo/"), "a_fwd"));
155  a_fwd.set_output_type(Target::EXECUTABLE);
156  Target b_fwd(&settings_, Label(SourceDir("//foo/"), "b_fwd"));
157  b_fwd.set_output_type(Target::STATIC_LIBRARY);
158  a_fwd.deps().push_back(LabelTargetPair(&b_fwd));
159  b_fwd.deps().push_back(LabelTargetPair(&c));
160  b_fwd.forward_dependent_configs().push_back(LabelTargetPair(&c));
161
162  b_fwd.OnResolved();
163  a_fwd.OnResolved();
164
165  // A_fwd should now have both configs.
166  ASSERT_EQ(2u, a_fwd.configs().size());
167  EXPECT_EQ(&all, a_fwd.configs()[0].ptr);
168  EXPECT_EQ(&direct, a_fwd.configs()[1].ptr);
169  ASSERT_EQ(1u, a_fwd.all_dependent_configs().size());
170  EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr);
171}
172
173// Tests that forward_dependent_configs_from works for groups, forwarding the
174// group's deps' dependent configs.
175TEST_F(TargetTest, ForwardDependentConfigsFromGroups) {
176  Target a(&settings_, Label(SourceDir("//foo/"), "a"));
177  a.set_output_type(Target::EXECUTABLE);
178  Target b(&settings_, Label(SourceDir("//foo/"), "b"));
179  b.set_output_type(Target::GROUP);
180  Target c(&settings_, Label(SourceDir("//foo/"), "c"));
181  c.set_output_type(Target::STATIC_LIBRARY);
182  a.deps().push_back(LabelTargetPair(&b));
183  b.deps().push_back(LabelTargetPair(&c));
184
185  // Direct dependent config on C.
186  Config direct(&settings_, Label(SourceDir("//foo/"), "direct"));
187  c.direct_dependent_configs().push_back(LabelConfigPair(&direct));
188
189  // A forwards the dependent configs from B.
190  a.forward_dependent_configs().push_back(LabelTargetPair(&b));
191
192  c.OnResolved();
193  b.OnResolved();
194  a.OnResolved();
195
196  // The config should now be on A, and in A's direct dependent configs.
197  ASSERT_EQ(1u, a.configs().size());
198  ASSERT_EQ(&direct, a.configs()[0].ptr);
199  ASSERT_EQ(1u, a.direct_dependent_configs().size());
200  ASSERT_EQ(&direct, a.direct_dependent_configs()[0].ptr);
201}
202
203TEST_F(TargetTest, InheritLibs) {
204  // Create a dependency chain:
205  //   A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
206  Target a(&settings_, Label(SourceDir("//foo/"), "a"));
207  a.set_output_type(Target::EXECUTABLE);
208  Target b(&settings_, Label(SourceDir("//foo/"), "b"));
209  b.set_output_type(Target::SHARED_LIBRARY);
210  Target c(&settings_, Label(SourceDir("//foo/"), "c"));
211  c.set_output_type(Target::STATIC_LIBRARY);
212  Target d(&settings_, Label(SourceDir("//foo/"), "d"));
213  d.set_output_type(Target::SOURCE_SET);
214  a.deps().push_back(LabelTargetPair(&b));
215  b.deps().push_back(LabelTargetPair(&c));
216  c.deps().push_back(LabelTargetPair(&d));
217
218  d.OnResolved();
219  c.OnResolved();
220  b.OnResolved();
221  a.OnResolved();
222
223  // C should have D in its inherited libs.
224  const std::set<const Target*>& c_inherited = c.inherited_libraries();
225  EXPECT_EQ(1u, c_inherited.size());
226  EXPECT_TRUE(c_inherited.find(&d) != c_inherited.end());
227
228  // B should have C and D in its inherited libs.
229  const std::set<const Target*>& b_inherited = b.inherited_libraries();
230  EXPECT_EQ(2u, b_inherited.size());
231  EXPECT_TRUE(b_inherited.find(&c) != b_inherited.end());
232  EXPECT_TRUE(b_inherited.find(&d) != b_inherited.end());
233
234  // A should have B in its inherited libs, but not any others (the shared
235  // library will include the static library and source set).
236  const std::set<const Target*>& a_inherited = a.inherited_libraries();
237  EXPECT_EQ(1u, a_inherited.size());
238  EXPECT_TRUE(a_inherited.find(&b) != a_inherited.end());
239}
240