Landing Recent QUIC changes until 8/19/2015 17:00 UTC.
[chromium-blink-merge.git] / tools / gn / ninja_action_target_writer_unittest.cc
blob74f155baea35b58ee7ee835f9bd6eb2ba270115c
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.
5 #include <algorithm>
6 #include <sstream>
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "tools/gn/ninja_action_target_writer.h"
10 #include "tools/gn/substitution_list.h"
11 #include "tools/gn/target.h"
12 #include "tools/gn/test_with_scope.h"
14 TEST(NinjaActionTargetWriter, WriteOutputFilesForBuildLine) {
15 TestWithScope setup;
16 Err err;
18 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
20 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
21 target.set_output_type(Target::ACTION_FOREACH);
22 target.action_values().outputs() = SubstitutionList::MakeForTest(
23 "//out/Debug/gen/a b{{source_name_part}}.h",
24 "//out/Debug/gen/{{source_name_part}}.cc");
26 target.SetToolchain(setup.toolchain());
27 ASSERT_TRUE(target.OnResolved(&err));
29 std::ostringstream out;
30 NinjaActionTargetWriter writer(&target, out);
32 SourceFile source("//foo/bar.in");
33 std::vector<OutputFile> output_files;
34 writer.WriteOutputFilesForBuildLine(source, &output_files);
36 EXPECT_EQ(" gen/a$ bbar.h gen/bar.cc", out.str());
39 // Tests an action with no sources.
40 TEST(NinjaActionTargetWriter, ActionNoSources) {
41 TestWithScope setup;
42 Err err;
44 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
45 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
46 target.set_output_type(Target::ACTION);
48 target.action_values().set_script(SourceFile("//foo/script.py"));
49 target.inputs().push_back(SourceFile("//foo/included.txt"));
51 target.action_values().outputs() =
52 SubstitutionList::MakeForTest("//out/Debug/foo.out");
54 target.SetToolchain(setup.toolchain());
55 ASSERT_TRUE(target.OnResolved(&err));
57 setup.settings()->set_target_os(Settings::LINUX);
58 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
59 "/usr/bin/python")));
61 std::ostringstream out;
62 NinjaActionTargetWriter writer(&target, out);
63 writer.Run();
65 const char expected[] =
66 "rule __foo_bar___rule\n"
67 " command = /usr/bin/python ../../foo/script.py\n"
68 " description = ACTION //foo:bar()\n"
69 " restat = 1\n"
70 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
71 "../../foo/included.txt\n"
72 "\n"
73 "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
74 "\n"
75 "build obj/foo/bar.stamp: stamp foo.out\n";
76 EXPECT_EQ(expected, out.str());
79 // Makes sure that we write sources as input dependencies for actions with
80 // both sources and inputs (ACTION_FOREACH treats the sources differently).
81 TEST(NinjaActionTargetWriter, ActionWithSources) {
82 TestWithScope setup;
83 Err err;
85 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
86 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
87 target.set_output_type(Target::ACTION);
89 target.action_values().set_script(SourceFile("//foo/script.py"));
91 target.sources().push_back(SourceFile("//foo/source.txt"));
92 target.inputs().push_back(SourceFile("//foo/included.txt"));
94 target.action_values().outputs() =
95 SubstitutionList::MakeForTest("//out/Debug/foo.out");
97 target.SetToolchain(setup.toolchain());
98 ASSERT_TRUE(target.OnResolved(&err));
100 // Posix.
102 setup.settings()->set_target_os(Settings::LINUX);
103 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
104 "/usr/bin/python")));
106 std::ostringstream out;
107 NinjaActionTargetWriter writer(&target, out);
108 writer.Run();
110 const char expected_linux[] =
111 "rule __foo_bar___rule\n"
112 " command = /usr/bin/python ../../foo/script.py\n"
113 " description = ACTION //foo:bar()\n"
114 " restat = 1\n"
115 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
116 "../../foo/included.txt ../../foo/source.txt\n"
117 "\n"
118 "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
119 "\n"
120 "build obj/foo/bar.stamp: stamp foo.out\n";
121 EXPECT_EQ(expected_linux, out.str());
124 // Windows.
126 // Note: we use forward slashes here so that the output will be the same on
127 // Linux and Windows.
128 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
129 "C:/python/python.exe")));
130 setup.settings()->set_target_os(Settings::WIN);
132 std::ostringstream out;
133 NinjaActionTargetWriter writer(&target, out);
134 writer.Run();
136 const char expected_win[] =
137 "rule __foo_bar___rule\n"
138 " command = C$:/python/python.exe gyp-win-tool action-wrapper environment.x86 __foo_bar___rule.$unique_name.rsp\n"
139 " description = ACTION //foo:bar()\n"
140 " restat = 1\n"
141 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
142 " rspfile_content = C$:/python/python.exe ../../foo/script.py\n"
143 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
144 "../../foo/included.txt ../../foo/source.txt\n"
145 "\n"
146 "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
147 "\n"
148 "build obj/foo/bar.stamp: stamp foo.out\n";
149 EXPECT_EQ(expected_win, out.str());
153 TEST(NinjaActionTargetWriter, ForEach) {
154 TestWithScope setup;
155 Err err;
157 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
159 // Some dependencies that the action can depend on. Use actions for these
160 // so they have a nice platform-independent stamp file that can appear in the
161 // output (rather than having to worry about how the current platform names
162 // binaries).
163 Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
164 dep.set_output_type(Target::ACTION);
165 dep.visibility().SetPublic();
166 dep.SetToolchain(setup.toolchain());
167 ASSERT_TRUE(dep.OnResolved(&err));
169 Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep"));
170 datadep.set_output_type(Target::ACTION);
171 datadep.visibility().SetPublic();
172 datadep.SetToolchain(setup.toolchain());
173 ASSERT_TRUE(datadep.OnResolved(&err));
175 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
176 target.set_output_type(Target::ACTION_FOREACH);
177 target.private_deps().push_back(LabelTargetPair(&dep));
178 target.data_deps().push_back(LabelTargetPair(&datadep));
180 target.sources().push_back(SourceFile("//foo/input1.txt"));
181 target.sources().push_back(SourceFile("//foo/input2.txt"));
183 target.action_values().set_script(SourceFile("//foo/script.py"));
185 target.action_values().args() = SubstitutionList::MakeForTest(
186 "-i",
187 "{{source}}",
188 "--out=foo bar{{source_name_part}}.o");
189 target.action_values().outputs() = SubstitutionList::MakeForTest(
190 "//out/Debug/{{source_name_part}}.out");
192 target.inputs().push_back(SourceFile("//foo/included.txt"));
194 target.SetToolchain(setup.toolchain());
195 ASSERT_TRUE(target.OnResolved(&err));
197 // Posix.
199 setup.settings()->set_target_os(Settings::LINUX);
200 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
201 "/usr/bin/python")));
203 std::ostringstream out;
204 NinjaActionTargetWriter writer(&target, out);
205 writer.Run();
207 const char expected_linux[] =
208 "rule __foo_bar___rule\n"
209 " command = /usr/bin/python ../../foo/script.py -i ${in} "
210 // Escaping is different between Windows and Posix.
211 #if defined(OS_WIN)
212 "\"--out=foo$ bar${source_name_part}.o\"\n"
213 #else
214 "--out=foo\\$ bar${source_name_part}.o\n"
215 #endif
216 " description = ACTION //foo:bar()\n"
217 " restat = 1\n"
218 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
219 "../../foo/included.txt obj/foo/dep.stamp\n"
220 "\n"
221 "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
222 "obj/foo/bar.inputdeps.stamp\n"
223 " source_name_part = input1\n"
224 "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
225 "obj/foo/bar.inputdeps.stamp\n"
226 " source_name_part = input2\n"
227 "\n"
228 "build obj/foo/bar.stamp: "
229 "stamp input1.out input2.out || obj/foo/datadep.stamp\n";
231 std::string out_str = out.str();
232 #if defined(OS_WIN)
233 std::replace(out_str.begin(), out_str.end(), '\\', '/');
234 #endif
235 EXPECT_EQ(expected_linux, out_str);
238 // Windows.
240 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
241 "C:/python/python.exe")));
242 setup.settings()->set_target_os(Settings::WIN);
244 std::ostringstream out;
245 NinjaActionTargetWriter writer(&target, out);
246 writer.Run();
248 const char expected_win[] =
249 "rule __foo_bar___rule\n"
250 " command = C$:/python/python.exe gyp-win-tool action-wrapper "
251 "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
252 " description = ACTION //foo:bar()\n"
253 " restat = 1\n"
254 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
255 " rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
256 #if defined(OS_WIN)
257 "${in} \"--out=foo$ bar${source_name_part}.o\"\n"
258 #else
259 "${in} --out=foo\\$ bar${source_name_part}.o\n"
260 #endif
261 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
262 "../../foo/included.txt obj/foo/dep.stamp\n"
263 "\n"
264 "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
265 "obj/foo/bar.inputdeps.stamp\n"
266 " unique_name = 0\n"
267 " source_name_part = input1\n"
268 "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
269 "obj/foo/bar.inputdeps.stamp\n"
270 " unique_name = 1\n"
271 " source_name_part = input2\n"
272 "\n"
273 "build obj/foo/bar.stamp: "
274 "stamp input1.out input2.out || obj/foo/datadep.stamp\n";
275 EXPECT_EQ(expected_win, out.str());
279 TEST(NinjaActionTargetWriter, ForEachWithDepfile) {
280 TestWithScope setup;
281 Err err;
283 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
284 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
285 target.set_output_type(Target::ACTION_FOREACH);
287 target.sources().push_back(SourceFile("//foo/input1.txt"));
288 target.sources().push_back(SourceFile("//foo/input2.txt"));
290 target.action_values().set_script(SourceFile("//foo/script.py"));
292 target.SetToolchain(setup.toolchain());
293 ASSERT_TRUE(target.OnResolved(&err));
295 SubstitutionPattern depfile;
296 ASSERT_TRUE(
297 depfile.Parse("//out/Debug/gen/{{source_name_part}}.d", nullptr, &err));
298 target.action_values().set_depfile(depfile);
300 target.action_values().args() = SubstitutionList::MakeForTest(
301 "-i",
302 "{{source}}",
303 "--out=foo bar{{source_name_part}}.o");
304 target.action_values().outputs() = SubstitutionList::MakeForTest(
305 "//out/Debug/{{source_name_part}}.out");
307 target.inputs().push_back(SourceFile("//foo/included.txt"));
309 // Posix.
311 setup.settings()->set_target_os(Settings::LINUX);
312 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
313 "/usr/bin/python")));
315 std::ostringstream out;
316 NinjaActionTargetWriter writer(&target, out);
317 writer.Run();
319 const char expected_linux[] =
320 "rule __foo_bar___rule\n"
321 " command = /usr/bin/python ../../foo/script.py -i ${in} "
322 #if defined(OS_WIN)
323 "\"--out=foo$ bar${source_name_part}.o\"\n"
324 #else
325 "--out=foo\\$ bar${source_name_part}.o\n"
326 #endif
327 " description = ACTION //foo:bar()\n"
328 " restat = 1\n"
329 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
330 "../../foo/included.txt\n"
331 "\n"
332 "build input1.out: __foo_bar___rule ../../foo/input1.txt"
333 " | obj/foo/bar.inputdeps.stamp\n"
334 " source_name_part = input1\n"
335 " depfile = gen/input1.d\n"
336 "build input2.out: __foo_bar___rule ../../foo/input2.txt"
337 " | obj/foo/bar.inputdeps.stamp\n"
338 " source_name_part = input2\n"
339 " depfile = gen/input2.d\n"
340 "\n"
341 "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
342 EXPECT_EQ(expected_linux, out.str());
345 // Windows.
347 setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
348 "C:/python/python.exe")));
349 setup.settings()->set_target_os(Settings::WIN);
351 std::ostringstream out;
352 NinjaActionTargetWriter writer(&target, out);
353 writer.Run();
355 const char expected_win[] =
356 "rule __foo_bar___rule\n"
357 " command = C$:/python/python.exe gyp-win-tool action-wrapper "
358 "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
359 " description = ACTION //foo:bar()\n"
360 " restat = 1\n"
361 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
362 " rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
363 #if defined(OS_WIN)
364 "${in} \"--out=foo$ bar${source_name_part}.o\"\n"
365 #else
366 "${in} --out=foo\\$ bar${source_name_part}.o\n"
367 #endif
368 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
369 "../../foo/included.txt\n"
370 "\n"
371 "build input1.out: __foo_bar___rule ../../foo/input1.txt"
372 " | obj/foo/bar.inputdeps.stamp\n"
373 " unique_name = 0\n"
374 " source_name_part = input1\n"
375 " depfile = gen/input1.d\n"
376 "build input2.out: __foo_bar___rule ../../foo/input2.txt"
377 " | obj/foo/bar.inputdeps.stamp\n"
378 " unique_name = 1\n"
379 " source_name_part = input2\n"
380 " depfile = gen/input2.d\n"
381 "\n"
382 "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
383 EXPECT_EQ(expected_win, out.str());