Upstream version 9.38.198.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/test_with_scope.h"
12
13 TEST(NinjaActionTargetWriter, WriteOutputFilesForBuildLine) {
14   TestWithScope setup;
15   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
16   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
17   target.action_values().outputs() = SubstitutionList::MakeForTest(
18       "//out/Debug/gen/a b{{source_name_part}}.h",
19       "//out/Debug/gen/{{source_name_part}}.cc");
20
21   std::ostringstream out;
22   NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
23
24   SourceFile source("//foo/bar.in");
25   std::vector<OutputFile> output_files;
26   writer.WriteOutputFilesForBuildLine(source, &output_files);
27
28   EXPECT_EQ(" gen/a$ bbar.h gen/bar.cc", out.str());
29 }
30
31 // Tests an action with no sources.
32 TEST(NinjaActionTargetWriter, ActionNoSources) {
33   TestWithScope setup;
34   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
35   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
36   target.set_output_type(Target::ACTION);
37
38   target.action_values().set_script(SourceFile("//foo/script.py"));
39   target.inputs().push_back(SourceFile("//foo/included.txt"));
40
41   target.action_values().outputs() =
42       SubstitutionList::MakeForTest("//out/Debug/foo.out");
43
44   setup.settings()->set_target_os(Settings::LINUX);
45   setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
46       "/usr/bin/python")));
47
48   std::ostringstream out;
49   NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
50   writer.Run();
51
52   const char expected[] =
53       "rule __foo_bar___rule\n"
54       "  command = /usr/bin/python ../../foo/script.py\n"
55       "  description = ACTION //foo:bar()\n"
56       "  restat = 1\n"
57       "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
58           "../../foo/included.txt\n"
59       "\n"
60       "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
61       "\n"
62       "build obj/foo/bar.stamp: stamp foo.out\n";
63   EXPECT_EQ(expected, out.str());
64 }
65
66 // Makes sure that we write sources as input dependencies for actions with
67 // both sources and inputs (ACTION_FOREACH treats the sources differently).
68 TEST(NinjaActionTargetWriter, ActionWithSources) {
69   TestWithScope setup;
70   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
71   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
72   target.set_output_type(Target::ACTION);
73
74   target.action_values().set_script(SourceFile("//foo/script.py"));
75
76   target.sources().push_back(SourceFile("//foo/source.txt"));
77   target.inputs().push_back(SourceFile("//foo/included.txt"));
78
79   target.action_values().outputs() =
80       SubstitutionList::MakeForTest("//out/Debug/foo.out");
81
82   // Posix.
83   {
84     setup.settings()->set_target_os(Settings::LINUX);
85     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
86         "/usr/bin/python")));
87
88     std::ostringstream out;
89     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
90     writer.Run();
91
92     const char expected_linux[] =
93         "rule __foo_bar___rule\n"
94         "  command = /usr/bin/python ../../foo/script.py\n"
95         "  description = ACTION //foo:bar()\n"
96         "  restat = 1\n"
97         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
98             "../../foo/included.txt ../../foo/source.txt\n"
99         "\n"
100         "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
101         "\n"
102         "build obj/foo/bar.stamp: stamp foo.out\n";
103     EXPECT_EQ(expected_linux, out.str());
104   }
105
106   // Windows.
107   {
108     // Note: we use forward slashes here so that the output will be the same on
109     // Linux and Windows.
110     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
111         "C:/python/python.exe")));
112     setup.settings()->set_target_os(Settings::WIN);
113
114     std::ostringstream out;
115     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
116     writer.Run();
117
118     const char expected_win[] =
119         "rule __foo_bar___rule\n"
120         "  command = C$:/python/python.exe gyp-win-tool action-wrapper environment.x86 __foo_bar___rule.$unique_name.rsp\n"
121         "  description = ACTION //foo:bar()\n"
122         "  restat = 1\n"
123         "  rspfile = __foo_bar___rule.$unique_name.rsp\n"
124         "  rspfile_content = C$:/python/python.exe ../../foo/script.py\n"
125         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
126             "../../foo/included.txt ../../foo/source.txt\n"
127         "\n"
128         "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
129         "\n"
130         "build obj/foo/bar.stamp: stamp foo.out\n";
131     EXPECT_EQ(expected_win, out.str());
132   }
133 }
134
135 TEST(NinjaActionTargetWriter, ForEach) {
136   TestWithScope setup;
137   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
138
139   // Some dependencies that the action can depend on. Use actions for these
140   // so they have a nice platform-independent stamp file that can appear in the
141   // output (rather than having to worry about how the current platform names
142   // binaries).
143   Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
144   dep.set_output_type(Target::ACTION);
145   Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep"));
146   datadep.set_output_type(Target::ACTION);
147
148   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
149   target.set_output_type(Target::ACTION_FOREACH);
150   target.deps().push_back(LabelTargetPair(&dep));
151   target.datadeps().push_back(LabelTargetPair(&datadep));
152
153   target.sources().push_back(SourceFile("//foo/input1.txt"));
154   target.sources().push_back(SourceFile("//foo/input2.txt"));
155
156   target.action_values().set_script(SourceFile("//foo/script.py"));
157
158   target.action_values().args() = SubstitutionList::MakeForTest(
159       "-i",
160       "{{source}}",
161       "--out=foo bar{{source_name_part}}.o");
162   target.action_values().outputs() = SubstitutionList::MakeForTest(
163       "//out/Debug/{{source_name_part}}.out");
164
165   target.inputs().push_back(SourceFile("//foo/included.txt"));
166
167   // Posix.
168   {
169     setup.settings()->set_target_os(Settings::LINUX);
170     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
171         "/usr/bin/python")));
172
173     std::ostringstream out;
174     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
175     writer.Run();
176
177     const char expected_linux[] =
178         "rule __foo_bar___rule\n"
179         "  command = /usr/bin/python ../../foo/script.py -i ${in} "
180             // Escaping is different between Windows and Posix.
181 #if defined(OS_WIN)
182             "\"--out=foo$ bar${source_name_part}.o\"\n"
183 #else
184             "--out=foo\\$ bar${source_name_part}.o\n"
185 #endif
186         "  description = ACTION //foo:bar()\n"
187         "  restat = 1\n"
188         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
189             "../../foo/included.txt obj/foo/dep.stamp\n"
190         "\n"
191         "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
192             "obj/foo/bar.inputdeps.stamp\n"
193         "  source_name_part = input1\n"
194         "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
195             "obj/foo/bar.inputdeps.stamp\n"
196         "  source_name_part = input2\n"
197         "\n"
198         "build obj/foo/bar.stamp: "
199             "stamp input1.out input2.out obj/foo/datadep.stamp\n";
200
201     std::string out_str = out.str();
202 #if defined(OS_WIN)
203     std::replace(out_str.begin(), out_str.end(), '\\', '/');
204 #endif
205     EXPECT_EQ(expected_linux, out_str);
206   }
207
208   // Windows.
209   {
210     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
211         "C:/python/python.exe")));
212     setup.settings()->set_target_os(Settings::WIN);
213
214     std::ostringstream out;
215     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
216     writer.Run();
217
218     const char expected_win[] =
219         "rule __foo_bar___rule\n"
220         "  command = C$:/python/python.exe gyp-win-tool action-wrapper "
221             "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
222         "  description = ACTION //foo:bar()\n"
223         "  restat = 1\n"
224         "  rspfile = __foo_bar___rule.$unique_name.rsp\n"
225         "  rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
226 #if defined(OS_WIN)
227             "${in} \"--out=foo$ bar${source_name_part}.o\"\n"
228 #else
229             "${in} --out=foo\\$ bar${source_name_part}.o\n"
230 #endif
231         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
232             "../../foo/included.txt obj/foo/dep.stamp\n"
233         "\n"
234         "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
235             "obj/foo/bar.inputdeps.stamp\n"
236         "  unique_name = 0\n"
237         "  source_name_part = input1\n"
238         "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
239             "obj/foo/bar.inputdeps.stamp\n"
240         "  unique_name = 1\n"
241         "  source_name_part = input2\n"
242         "\n"
243         "build obj/foo/bar.stamp: "
244             "stamp input1.out input2.out obj/foo/datadep.stamp\n";
245     EXPECT_EQ(expected_win, out.str());
246   }
247 }
248
249 TEST(NinjaActionTargetWriter, ForEachWithDepfile) {
250   TestWithScope setup;
251   setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
252   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
253   target.set_output_type(Target::ACTION_FOREACH);
254
255   target.sources().push_back(SourceFile("//foo/input1.txt"));
256   target.sources().push_back(SourceFile("//foo/input2.txt"));
257
258   target.action_values().set_script(SourceFile("//foo/script.py"));
259
260   SubstitutionPattern depfile;
261   Err err;
262   ASSERT_TRUE(
263       depfile.Parse("//out/Debug/gen/{{source_name_part}}.d", NULL, &err));
264   target.action_values().set_depfile(depfile);
265
266   target.action_values().args() = SubstitutionList::MakeForTest(
267       "-i",
268       "{{source}}",
269       "--out=foo bar{{source_name_part}}.o");
270   target.action_values().outputs() = SubstitutionList::MakeForTest(
271       "//out/Debug/{{source_name_part}}.out");
272
273   target.inputs().push_back(SourceFile("//foo/included.txt"));
274
275   // Posix.
276   {
277     setup.settings()->set_target_os(Settings::LINUX);
278     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
279         "/usr/bin/python")));
280
281     std::ostringstream out;
282     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
283     writer.Run();
284
285     const char expected_linux[] =
286         "rule __foo_bar___rule\n"
287         "  command = /usr/bin/python ../../foo/script.py -i ${in} "
288 #if defined(OS_WIN)
289             "\"--out=foo$ bar${source_name_part}.o\"\n"
290 #else
291             "--out=foo\\$ bar${source_name_part}.o\n"
292 #endif
293         "  description = ACTION //foo:bar()\n"
294         "  restat = 1\n"
295         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
296             "../../foo/included.txt\n"
297         "\n"
298         "build input1.out: __foo_bar___rule ../../foo/input1.txt"
299             " | obj/foo/bar.inputdeps.stamp\n"
300         "  source_name_part = input1\n"
301         "  depfile = gen/input1.d\n"
302         "build input2.out: __foo_bar___rule ../../foo/input2.txt"
303             " | obj/foo/bar.inputdeps.stamp\n"
304         "  source_name_part = input2\n"
305         "  depfile = gen/input2.d\n"
306         "\n"
307         "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
308     EXPECT_EQ(expected_linux, out.str());
309   }
310
311   // Windows.
312   {
313     setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
314         "C:/python/python.exe")));
315     setup.settings()->set_target_os(Settings::WIN);
316
317     std::ostringstream out;
318     NinjaActionTargetWriter writer(&target, setup.toolchain(), out);
319     writer.Run();
320
321     const char expected_win[] =
322         "rule __foo_bar___rule\n"
323         "  command = C$:/python/python.exe gyp-win-tool action-wrapper "
324             "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
325         "  description = ACTION //foo:bar()\n"
326         "  restat = 1\n"
327         "  rspfile = __foo_bar___rule.$unique_name.rsp\n"
328         "  rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
329 #if defined(OS_WIN)
330             "${in} \"--out=foo$ bar${source_name_part}.o\"\n"
331 #else
332             "${in} --out=foo\\$ bar${source_name_part}.o\n"
333 #endif
334         "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
335             "../../foo/included.txt\n"
336         "\n"
337         "build input1.out: __foo_bar___rule ../../foo/input1.txt"
338             " | obj/foo/bar.inputdeps.stamp\n"
339         "  unique_name = 0\n"
340         "  source_name_part = input1\n"
341         "  depfile = gen/input1.d\n"
342         "build input2.out: __foo_bar___rule ../../foo/input2.txt"
343             " | obj/foo/bar.inputdeps.stamp\n"
344         "  unique_name = 1\n"
345         "  source_name_part = input2\n"
346         "  depfile = gen/input2.d\n"
347         "\n"
348         "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
349     EXPECT_EQ(expected_win, out.str());
350   }
351 }