1 // Copyright 2015 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.
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "tools/gn/runtime_deps.h"
9 #include "tools/gn/target.h"
10 #include "tools/gn/test_with_scope.h"
14 void InitTargetWithType(TestWithScope
& setup
,
16 Target::OutputType type
) {
17 target
->set_output_type(type
);
18 target
->visibility().SetPublic();
19 target
->SetToolchain(setup
.toolchain());
22 // Convenience function to make the correct kind of pair.
23 std::pair
<OutputFile
, const Target
*> MakePair(const char* str
,
25 return std::pair
<OutputFile
, const Target
*>(OutputFile(str
), t
);
28 std::string
GetVectorDescription(
29 const std::vector
<std::pair
<OutputFile
, const Target
*>>& v
) {
31 for (size_t i
= 0; i
< v
.size(); i
++) {
34 result
.append("\"" + v
[i
].first
.value() + "\"");
41 // Tests an exe depending on different types of libraries.
42 TEST(RuntimeDeps
, Libs
) {
46 // Dependency hierarchy: main(exe) -> stat
50 Target
stat(setup
.settings(), Label(SourceDir("//"), "stat"));
51 InitTargetWithType(setup
, &stat
, Target::STATIC_LIBRARY
);
52 stat
.data().push_back("//stat.dat");
53 ASSERT_TRUE(stat
.OnResolved(&err
));
55 Target
shared(setup
.settings(), Label(SourceDir("//"), "shared"));
56 InitTargetWithType(setup
, &shared
, Target::SHARED_LIBRARY
);
57 shared
.data().push_back("//shared.dat");
58 ASSERT_TRUE(shared
.OnResolved(&err
));
60 Target
set(setup
.settings(), Label(SourceDir("//"), "set"));
61 InitTargetWithType(setup
, &set
, Target::SOURCE_SET
);
62 set
.data().push_back("//set.dat");
63 ASSERT_TRUE(set
.OnResolved(&err
));
65 Target
main(setup
.settings(), Label(SourceDir("//"), "main"));
66 InitTargetWithType(setup
, &main
, Target::EXECUTABLE
);
67 main
.private_deps().push_back(LabelTargetPair(&stat
));
68 main
.private_deps().push_back(LabelTargetPair(&shared
));
69 main
.private_deps().push_back(LabelTargetPair(&set
));
70 main
.data().push_back("//main.dat");
71 ASSERT_TRUE(main
.OnResolved(&err
));
73 std::vector
<std::pair
<OutputFile
, const Target
*>> result
=
74 ComputeRuntimeDeps(&main
);
76 // The result should have deps of main, all 4 dat files, and libshared.so
77 ASSERT_EQ(6u, result
.size()) << GetVectorDescription(result
);
79 // The first one should always be the main exe.
80 EXPECT_TRUE(MakePair("./main", &main
) == result
[0]);
82 // The rest of the ordering is undefined. First the data files.
83 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
84 MakePair("../../stat.dat", &stat
)) !=
85 result
.end()) << GetVectorDescription(result
);
86 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
87 MakePair("../../shared.dat", &shared
)) !=
88 result
.end()) << GetVectorDescription(result
);
89 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
90 MakePair("../../set.dat", &set
)) !=
91 result
.end()) << GetVectorDescription(result
);
92 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
93 MakePair("../../main.dat", &main
)) !=
94 result
.end()) << GetVectorDescription(result
);
96 // Check the static library
97 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
98 MakePair("./libshared.so", &shared
)) !=
99 result
.end()) << GetVectorDescription(result
);
102 // Tests that executables that aren't listed as data deps aren't included in
103 // the output, but executables that are data deps are included.
104 TEST(RuntimeDeps
, ExeDataDep
) {
108 // Dependency hierarchy: main(exe) -> datadep(exe) -> final_in(source set)
109 // -> dep(exe) -> final_out(source set)
110 // The final_in/out targets each have data files. final_in's should be
111 // included, final_out's should not be.
113 Target
final_in(setup
.settings(), Label(SourceDir("//"), "final_in"));
114 InitTargetWithType(setup
, &final_in
, Target::SOURCE_SET
);
115 final_in
.data().push_back("//final_in.dat");
116 ASSERT_TRUE(final_in
.OnResolved(&err
));
118 Target
datadep(setup
.settings(), Label(SourceDir("//"), "datadep"));
119 InitTargetWithType(setup
, &datadep
, Target::EXECUTABLE
);
120 datadep
.private_deps().push_back(LabelTargetPair(&final_in
));
121 ASSERT_TRUE(datadep
.OnResolved(&err
));
123 Target
final_out(setup
.settings(), Label(SourceDir("//"), "final_out"));
124 InitTargetWithType(setup
, &final_out
, Target::SOURCE_SET
);
125 final_out
.data().push_back("//final_out.dat");
126 ASSERT_TRUE(final_out
.OnResolved(&err
));
128 Target
dep(setup
.settings(), Label(SourceDir("//"), "dep"));
129 InitTargetWithType(setup
, &dep
, Target::EXECUTABLE
);
130 dep
.private_deps().push_back(LabelTargetPair(&final_out
));
131 ASSERT_TRUE(dep
.OnResolved(&err
));
133 Target
main(setup
.settings(), Label(SourceDir("//"), "main"));
134 InitTargetWithType(setup
, &main
, Target::EXECUTABLE
);
135 main
.private_deps().push_back(LabelTargetPair(&dep
));
136 main
.data_deps().push_back(LabelTargetPair(&datadep
));
137 ASSERT_TRUE(main
.OnResolved(&err
));
139 std::vector
<std::pair
<OutputFile
, const Target
*>> result
=
140 ComputeRuntimeDeps(&main
);
142 // The result should have deps of main, datadep, final_in.dat
143 ASSERT_EQ(3u, result
.size()) << GetVectorDescription(result
);
145 // The first one should always be the main exe.
146 EXPECT_TRUE(MakePair("./main", &main
) == result
[0]);
148 // The rest of the ordering is undefined.
149 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
150 MakePair("./datadep", &datadep
)) !=
151 result
.end()) << GetVectorDescription(result
);
152 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
153 MakePair("../../final_in.dat", &final_in
)) !=
154 result
.end()) << GetVectorDescription(result
);
157 // Tests that action and copy outputs are considered if they're data deps, but
158 // not if they're regular deps. Action and copy "data" files are always
160 TEST(RuntimeDeps
, ActionOutputs
) {
164 // Dependency hierarchy: main(exe) -> datadep (action)
165 // -> datadep_copy (copy)
167 // -> dep_copy (copy)
169 Target
datadep(setup
.settings(), Label(SourceDir("//"), "datadep"));
170 InitTargetWithType(setup
, &datadep
, Target::ACTION
);
171 datadep
.data().push_back("//datadep.data");
172 datadep
.action_values().outputs() =
173 SubstitutionList::MakeForTest("//datadep.output");
174 ASSERT_TRUE(datadep
.OnResolved(&err
));
176 Target
datadep_copy(setup
.settings(), Label(SourceDir("//"), "datadep_copy"));
177 InitTargetWithType(setup
, &datadep_copy
, Target::COPY_FILES
);
178 datadep_copy
.sources().push_back(SourceFile("//input"));
179 datadep_copy
.data().push_back("//datadep_copy.data");
180 datadep_copy
.action_values().outputs() =
181 SubstitutionList::MakeForTest("//datadep_copy.output");
182 ASSERT_TRUE(datadep_copy
.OnResolved(&err
));
184 Target
dep(setup
.settings(), Label(SourceDir("//"), "dep"));
185 InitTargetWithType(setup
, &dep
, Target::ACTION
);
186 dep
.data().push_back("//dep.data");
187 dep
.action_values().outputs() =
188 SubstitutionList::MakeForTest("//dep.output");
189 ASSERT_TRUE(dep
.OnResolved(&err
));
191 Target
dep_copy(setup
.settings(), Label(SourceDir("//"), "dep_copy"));
192 InitTargetWithType(setup
, &dep_copy
, Target::COPY_FILES
);
193 dep_copy
.sources().push_back(SourceFile("//input"));
194 dep_copy
.data().push_back("//dep_copy/data/"); // Tests a directory.
195 dep_copy
.action_values().outputs() =
196 SubstitutionList::MakeForTest("//dep_copy.output");
197 ASSERT_TRUE(dep_copy
.OnResolved(&err
));
199 Target
main(setup
.settings(), Label(SourceDir("//"), "main"));
200 InitTargetWithType(setup
, &main
, Target::EXECUTABLE
);
201 main
.private_deps().push_back(LabelTargetPair(&dep
));
202 main
.private_deps().push_back(LabelTargetPair(&dep_copy
));
203 main
.data_deps().push_back(LabelTargetPair(&datadep
));
204 main
.data_deps().push_back(LabelTargetPair(&datadep_copy
));
205 ASSERT_TRUE(main
.OnResolved(&err
));
207 std::vector
<std::pair
<OutputFile
, const Target
*>> result
=
208 ComputeRuntimeDeps(&main
);
210 // The result should have deps of main, both datadeps files, but only
211 // the data file from dep.
212 ASSERT_EQ(7u, result
.size()) << GetVectorDescription(result
);
214 // The first one should always be the main exe.
215 EXPECT_TRUE(MakePair("./main", &main
) == result
[0]);
217 // The rest of the ordering is undefined.
218 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
219 MakePair("../../datadep.data", &datadep
)) !=
220 result
.end()) << GetVectorDescription(result
);
221 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
222 MakePair("../../datadep_copy.data", &datadep_copy
)) !=
223 result
.end()) << GetVectorDescription(result
);
224 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
225 MakePair("../../datadep.output", &datadep
)) !=
226 result
.end()) << GetVectorDescription(result
);
227 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
228 MakePair("../../datadep_copy.output", &datadep_copy
)) !=
229 result
.end()) << GetVectorDescription(result
);
230 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
231 MakePair("../../dep.data", &dep
)) !=
232 result
.end()) << GetVectorDescription(result
);
233 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
234 MakePair("../../dep_copy/data/", &dep_copy
)) !=
235 result
.end()) << GetVectorDescription(result
);
237 // Explicitly asking for the runtime deps of an action target only includes
238 // the data and not all outputs.
239 result
= ComputeRuntimeDeps(&dep
);
240 ASSERT_EQ(1u, result
.size());
241 EXPECT_TRUE(MakePair("../../dep.data", &dep
) == result
[0]);
244 // Tests that a dependency duplicated in regular and data deps is processed
246 TEST(RuntimeDeps
, Dupe
) {
250 Target
action(setup
.settings(), Label(SourceDir("//"), "action"));
251 InitTargetWithType(setup
, &action
, Target::ACTION
);
252 action
.action_values().outputs() =
253 SubstitutionList::MakeForTest("//action.output");
254 ASSERT_TRUE(action
.OnResolved(&err
));
256 Target
target(setup
.settings(), Label(SourceDir("//"), "foo"));
257 InitTargetWithType(setup
, &target
, Target::EXECUTABLE
);
258 target
.private_deps().push_back(LabelTargetPair(&action
));
259 target
.data_deps().push_back(LabelTargetPair(&action
));
260 ASSERT_TRUE(target
.OnResolved(&err
));
262 // The results should be the executable and the copy output.
263 std::vector
<std::pair
<OutputFile
, const Target
*>> result
=
264 ComputeRuntimeDeps(&target
);
265 EXPECT_TRUE(std::find(result
.begin(), result
.end(),
266 MakePair("../../action.output", &action
)) !=
267 result
.end()) << GetVectorDescription(result
);