Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / gn / ninja_action_target_writer_unittest.cc
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 <algorithm>
6 #include <sstream>
7
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"
13
14 TEST(NinjaActionTargetWriter, WriteOutputFilesForBuildLine) {
15   TestWithScope setup;
16   Err err;
17
18   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
19
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");
25
26   target.SetToolchain(setup.toolchain());
27   ASSERT_TRUE(target.OnResolved(&err));
28
29   std::ostringstream out;
30   NinjaActionTargetWriter writer(&target, out);
31
32   SourceFile source("//foo/bar.in");
33   std::vector<OutputFile> output_files;
34   writer.WriteOutputFilesForBuildLine(source, &output_files);
35
36   EXPECT_EQ(" gen/a$ bbar.h gen/bar.cc", out.str());
37 }
38
39 // Tests an action with no sources.
40 TEST(NinjaActionTargetWriter, ActionNoSources) {
41   TestWithScope setup;
42   Err err;
43
44   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
45   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
46   target.set_output_type(Target::ACTION);
47
48   target.action_values().set_script(SourceFile("//foo/script.py"));
49   target.inputs().push_back(SourceFile("//foo/included.txt"));
50
51   target.action_values().outputs() =
52       SubstitutionList::MakeForTest("//out/Debug/foo.out");
53
54   target.SetToolchain(setup.toolchain());
55   ASSERT_TRUE(target.OnResolved(&err));
56
57   setup.settings()->set_target_os(Settings::LINUX);
58   setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
59       "/usr/bin/python")));
60
61   std::ostringstream out;
62   NinjaActionTargetWriter writer(&target, out);
63   writer.Run();
64
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());
77 }
78
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;
84
85   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
86   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
87   target.set_output_type(Target::ACTION);
88
89   target.action_values().set_script(SourceFile("//foo/script.py"));
90
91   target.sources().push_back(SourceFile("//foo/source.txt"));
92   target.inputs().push_back(SourceFile("//foo/included.txt"));
93
94   target.action_values().outputs() =
95       SubstitutionList::MakeForTest("//out/Debug/foo.out");
96
97   target.SetToolchain(setup.toolchain());
98   ASSERT_TRUE(target.OnResolved(&err));
99
100   // Posix.
101   {
102     setup.settings()->set_target_os(Settings::LINUX);
103     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
104         "/usr/bin/python")));
105
106     std::ostringstream out;
107     NinjaActionTargetWriter writer(&target, out);
108     writer.Run();
109
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());
122   }
123
124   // Windows.
125   {
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);
131
132     std::ostringstream out;
133     NinjaActionTargetWriter writer(&target, out);
134     writer.Run();
135
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());
150   }
151 }
152
153 TEST(NinjaActionTargetWriter, ForEach) {
154   TestWithScope setup;
155   Err err;
156
157   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
158
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));
168
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));
174
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));
179
180   target.sources().push_back(SourceFile("//foo/input1.txt"));
181   target.sources().push_back(SourceFile("//foo/input2.txt"));
182
183   target.action_values().set_script(SourceFile("//foo/script.py"));
184
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");
191
192   target.inputs().push_back(SourceFile("//foo/included.txt"));
193
194   target.SetToolchain(setup.toolchain());
195   ASSERT_TRUE(target.OnResolved(&err));
196
197   // Posix.
198   {
199     setup.settings()->set_target_os(Settings::LINUX);
200     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
201         "/usr/bin/python")));
202
203     std::ostringstream out;
204     NinjaActionTargetWriter writer(&target, out);
205     writer.Run();
206
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";
230
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);
236   }
237
238   // Windows.
239   {
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);
243
244     std::ostringstream out;
245     NinjaActionTargetWriter writer(&target, out);
246     writer.Run();
247
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());
276   }
277 }
278
279 TEST(NinjaActionTargetWriter, ForEachWithDepfile) {
280   TestWithScope setup;
281   Err err;
282
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);
286
287   target.sources().push_back(SourceFile("//foo/input1.txt"));
288   target.sources().push_back(SourceFile("//foo/input2.txt"));
289
290   target.action_values().set_script(SourceFile("//foo/script.py"));
291
292   target.SetToolchain(setup.toolchain());
293   ASSERT_TRUE(target.OnResolved(&err));
294
295   SubstitutionPattern depfile;
296   ASSERT_TRUE(
297       depfile.Parse("//out/Debug/gen/{{source_name_part}}.d", NULL, &err));
298   target.action_values().set_depfile(depfile);
299
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");
306
307   target.inputs().push_back(SourceFile("//foo/included.txt"));
308
309   // Posix.
310   {
311     setup.settings()->set_target_os(Settings::LINUX);
312     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
313         "/usr/bin/python")));
314
315     std::ostringstream out;
316     NinjaActionTargetWriter writer(&target, out);
317     writer.Run();
318
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());
343   }
344
345   // Windows.
346   {
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);
350
351     std::ostringstream out;
352     NinjaActionTargetWriter writer(&target, out);
353     writer.Run();
354
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());
384   }
385 }