1 // Copyright 2016 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 "gn/ninja_create_bundle_target_writer.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <sstream>
10
11 #include "gn/target.h"
12 #include "gn/test_with_scope.h"
13 #include "util/test/test.h"
14
15 namespace {
16
SetupBundleDataDir(BundleData * bundle_data,const std::string & root_dir)17 void SetupBundleDataDir(BundleData* bundle_data, const std::string& root_dir) {
18 std::string bundle_root_dir = root_dir + "/bar.bundle";
19 bundle_data->root_dir() = SourceDir(bundle_root_dir);
20 bundle_data->contents_dir() = SourceDir(bundle_root_dir + "/Contents");
21 bundle_data->resources_dir() =
22 SourceDir(bundle_data->contents_dir().value() + "/Resources");
23 bundle_data->executable_dir() =
24 SourceDir(bundle_data->contents_dir().value() + "/MacOS");
25 }
26
NewAction(const TestWithScope & setup)27 std::unique_ptr<Target> NewAction(const TestWithScope& setup) {
28 Err err;
29 auto action = std::make_unique<Target>(setup.settings(),
30 Label(SourceDir("//foo/"), "bar"));
31 action->set_output_type(Target::ACTION);
32 action->visibility().SetPublic();
33 action->action_values().set_script(SourceFile("//foo/script.py"));
34
35 action->action_values().outputs() =
36 SubstitutionList::MakeForTest("//out/Debug/foo.out");
37
38 action->SetToolchain(setup.toolchain());
39 return action;
40 }
41
42 } // namespace
43
44 // Tests multiple files with an output pattern.
TEST(NinjaCreateBundleTargetWriter,Run)45 TEST(NinjaCreateBundleTargetWriter, Run) {
46 Err err;
47 TestWithScope setup;
48
49 std::unique_ptr<Target> action = NewAction(setup);
50 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
51
52 Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
53 bundle_data.set_output_type(Target::BUNDLE_DATA);
54 bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
55 bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
56 bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
57 "{{bundle_resources_dir}}/{{source_file_part}}");
58 bundle_data.SetToolchain(setup.toolchain());
59 bundle_data.visibility().SetPublic();
60 ASSERT_TRUE(bundle_data.OnResolved(&err));
61
62 Target create_bundle(
63 setup.settings(),
64 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
65 setup.toolchain()->label().name()));
66 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
67 create_bundle.set_output_type(Target::CREATE_BUNDLE);
68 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
69 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
70 create_bundle.SetToolchain(setup.toolchain());
71 ASSERT_TRUE(create_bundle.OnResolved(&err));
72
73 std::ostringstream out;
74 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
75 writer.Run();
76
77 const char expected[] =
78 "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
79 "obj/foo/data.stamp\n"
80 "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
81 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
82 "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
83 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
84 "build obj/baz/bar.stamp: stamp "
85 "bar.bundle/Contents/Resources/input1.txt "
86 "bar.bundle/Contents/Resources/input2.txt"
87 " || obj/baz/bar.inputdeps.stamp\n"
88 "build bar.bundle: phony obj/baz/bar.stamp\n";
89 std::string out_str = out.str();
90 EXPECT_EQ(expected, out_str);
91 }
92
93 // Tests creating a bundle in a sub-directory of $root_out_dir.
TEST(NinjaCreateBundleTargetWriter,InSubDirectory)94 TEST(NinjaCreateBundleTargetWriter, InSubDirectory) {
95 Err err;
96 TestWithScope setup;
97
98 std::unique_ptr<Target> action = NewAction(setup);
99 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
100
101 Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
102 bundle_data.set_output_type(Target::BUNDLE_DATA);
103 bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
104 bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
105 bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
106 "{{bundle_resources_dir}}/{{source_file_part}}");
107 bundle_data.SetToolchain(setup.toolchain());
108 bundle_data.visibility().SetPublic();
109 ASSERT_TRUE(bundle_data.OnResolved(&err));
110
111 Target create_bundle(
112 setup.settings(),
113 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
114 setup.toolchain()->label().name()));
115 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug/gen");
116 create_bundle.set_output_type(Target::CREATE_BUNDLE);
117 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
118 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
119 create_bundle.SetToolchain(setup.toolchain());
120 ASSERT_TRUE(create_bundle.OnResolved(&err));
121
122 std::ostringstream out;
123 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
124 writer.Run();
125
126 const char expected[] =
127 "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
128 "obj/foo/data.stamp\n"
129 "build gen/bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
130 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
131 "build gen/bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
132 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
133 "build obj/baz/bar.stamp: stamp "
134 "gen/bar.bundle/Contents/Resources/input1.txt "
135 "gen/bar.bundle/Contents/Resources/input2.txt || "
136 "obj/baz/bar.inputdeps.stamp\n"
137 "build gen/bar.bundle: phony obj/baz/bar.stamp\n";
138 std::string out_str = out.str();
139 EXPECT_EQ(expected, out_str);
140 }
141
142 // Tests empty asset catalog with partial_info_plist property defined.
TEST(NinjaCreateBundleTargetWriter,JustPartialInfoPlist)143 TEST(NinjaCreateBundleTargetWriter, JustPartialInfoPlist) {
144 Err err;
145 TestWithScope setup;
146
147 std::unique_ptr<Target> action = NewAction(setup);
148 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
149
150 Target create_bundle(
151 setup.settings(),
152 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
153 setup.toolchain()->label().name()));
154 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
155 create_bundle.set_output_type(Target::CREATE_BUNDLE);
156 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
157 create_bundle.bundle_data().product_type().assign("com.apple.product-type");
158 create_bundle.bundle_data().set_partial_info_plist(
159 SourceFile("//out/Debug/baz/bar/bar_partial_info.plist"));
160 create_bundle.SetToolchain(setup.toolchain());
161 ASSERT_TRUE(create_bundle.OnResolved(&err));
162
163 std::ostringstream out;
164 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
165 writer.Run();
166
167 const char expected[] =
168 "build baz/bar/bar_partial_info.plist: stamp || obj/foo/bar.stamp\n"
169 "build obj/baz/bar.stamp: stamp "
170 "baz/bar/bar_partial_info.plist || obj/foo/bar.stamp\n"
171 "build bar.bundle: phony obj/baz/bar.stamp\n";
172 std::string out_str = out.str();
173 EXPECT_EQ(expected, out_str);
174 }
175
176 // Tests multiple files from asset catalog.
TEST(NinjaCreateBundleTargetWriter,AssetCatalog)177 TEST(NinjaCreateBundleTargetWriter, AssetCatalog) {
178 Err err;
179 TestWithScope setup;
180
181 std::unique_ptr<Target> action = NewAction(setup);
182 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
183
184 Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
185 bundle_data.set_output_type(Target::BUNDLE_DATA);
186 bundle_data.sources().push_back(
187 SourceFile("//foo/Foo.xcassets/Contents.json"));
188 bundle_data.sources().push_back(
189 SourceFile("//foo/Foo.xcassets/foo.colorset/Contents.json"));
190 bundle_data.sources().push_back(
191 SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
192 bundle_data.sources().push_back(
193 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
194 bundle_data.sources().push_back(
195 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
196 bundle_data.sources().push_back(
197 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
198 bundle_data.sources().push_back(
199 SourceFile("//foo/Foo.xcassets/foo.dataset/Contents.json"));
200 bundle_data.sources().push_back(
201 SourceFile("//foo/Foo.xcassets/foo.dataset/FooScript.js"));
202 bundle_data.sources().push_back(
203 SourceFile("//foo/Foo.xcassets/file/with/no/known/pattern"));
204 bundle_data.sources().push_back(
205 SourceFile("//foo/Foo.xcassets/nested/bar.xcassets/my/file"));
206 bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
207 "{{bundle_resources_dir}}/{{source_file_part}}");
208 bundle_data.SetToolchain(setup.toolchain());
209 bundle_data.visibility().SetPublic();
210 ASSERT_TRUE(bundle_data.OnResolved(&err));
211
212 Target create_bundle(
213 setup.settings(),
214 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
215 setup.toolchain()->label().name()));
216 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
217 create_bundle.set_output_type(Target::CREATE_BUNDLE);
218 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
219 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
220 create_bundle.bundle_data().product_type().assign("com.apple.product-type");
221 create_bundle.bundle_data().xcasset_compiler_flags() =
222 SubstitutionList::MakeForTest("--app-icon", "foo");
223
224 create_bundle.SetToolchain(setup.toolchain());
225 ASSERT_TRUE(create_bundle.OnResolved(&err));
226
227 std::ostringstream out;
228 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
229 writer.Run();
230
231 const char expected[] =
232 "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
233 "obj/foo/data.stamp\n"
234 "build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
235 "../../foo/Foo.xcassets | obj/foo/data.stamp || "
236 "obj/baz/bar.inputdeps.stamp\n"
237 " product_type = com.apple.product-type\n"
238 " xcasset_compiler_flags = --app-icon foo\n"
239 "build obj/baz/bar.stamp: stamp "
240 "bar.bundle/Contents/Resources/Assets.car || "
241 "obj/baz/bar.inputdeps.stamp\n"
242 "build bar.bundle: phony obj/baz/bar.stamp\n";
243 std::string out_str = out.str();
244 EXPECT_EQ(expected, out_str);
245 }
246
247 // Tests that the phony target for the top-level bundle directory is generated
248 // correctly.
TEST(NinjaCreateBundleTargetWriter,PhonyTarget)249 TEST(NinjaCreateBundleTargetWriter, PhonyTarget) {
250 Err err;
251 TestWithScope setup;
252
253 Target create_bundle(
254 setup.settings(),
255 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
256 setup.toolchain()->label().name()));
257 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
258 create_bundle.set_output_type(Target::CREATE_BUNDLE);
259 create_bundle.SetToolchain(setup.toolchain());
260 ASSERT_TRUE(create_bundle.OnResolved(&err));
261
262 std::ostringstream out;
263 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
264 writer.Run();
265
266 const char expected[] =
267 "build obj/baz/bar.stamp: stamp\n"
268 "build bar.bundle: phony obj/baz/bar.stamp\n";
269 std::string out_str = out.str();
270 EXPECT_EQ(expected, out_str);
271 }
272
273 // Tests complex target with multiple bundle_data sources, including
274 // some asset catalog.
TEST(NinjaCreateBundleTargetWriter,Complex)275 TEST(NinjaCreateBundleTargetWriter, Complex) {
276 Err err;
277 TestWithScope setup;
278
279 std::unique_ptr<Target> action = NewAction(setup);
280 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
281
282 Target bundle_data0(setup.settings(),
283 Label(SourceDir("//qux/"), "info_plist"));
284 bundle_data0.set_output_type(Target::BUNDLE_DATA);
285 bundle_data0.sources().push_back(SourceFile("//qux/qux-Info.plist"));
286 bundle_data0.action_values().outputs() =
287 SubstitutionList::MakeForTest("{{bundle_contents_dir}}/Info.plist");
288 bundle_data0.SetToolchain(setup.toolchain());
289 bundle_data0.visibility().SetPublic();
290 ASSERT_TRUE(bundle_data0.OnResolved(&err));
291
292 Target bundle_data1(setup.settings(), Label(SourceDir("//foo/"), "data"));
293 bundle_data1.set_output_type(Target::BUNDLE_DATA);
294 bundle_data1.sources().push_back(SourceFile("//foo/input1.txt"));
295 bundle_data1.sources().push_back(SourceFile("//foo/input2.txt"));
296 bundle_data1.action_values().outputs() = SubstitutionList::MakeForTest(
297 "{{bundle_resources_dir}}/{{source_file_part}}");
298 bundle_data1.SetToolchain(setup.toolchain());
299 bundle_data1.visibility().SetPublic();
300 ASSERT_TRUE(bundle_data1.OnResolved(&err));
301
302 Target bundle_data2(setup.settings(), Label(SourceDir("//foo/"), "assets"));
303 bundle_data2.set_output_type(Target::BUNDLE_DATA);
304 bundle_data2.sources().push_back(
305 SourceFile("//foo/Foo.xcassets/Contents.json"));
306 bundle_data2.sources().push_back(
307 SourceFile("//foo/Foo.xcassets/foo.colorset/Contents.json"));
308 bundle_data2.sources().push_back(
309 SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
310 bundle_data2.sources().push_back(
311 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
312 bundle_data2.sources().push_back(
313 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
314 bundle_data2.sources().push_back(
315 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
316 bundle_data2.sources().push_back(
317 SourceFile("//foo/Foo.xcassets/foo.dataset/Contents.json"));
318 bundle_data2.sources().push_back(
319 SourceFile("//foo/Foo.xcassets/foo.dataset/FooScript.js"));
320 bundle_data2.sources().push_back(
321 SourceFile("//foo/Foo.xcassets/file/with/no/known/pattern"));
322 bundle_data2.sources().push_back(
323 SourceFile("//foo/Foo.xcassets/nested/bar.xcassets/my/file"));
324 bundle_data2.action_values().outputs() = SubstitutionList::MakeForTest(
325 "{{bundle_resources_dir}}/{{source_file_part}}");
326 bundle_data2.SetToolchain(setup.toolchain());
327 bundle_data2.visibility().SetPublic();
328 ASSERT_TRUE(bundle_data2.OnResolved(&err));
329
330 Target bundle_data3(setup.settings(), Label(SourceDir("//quz/"), "assets"));
331 bundle_data3.set_output_type(Target::BUNDLE_DATA);
332 bundle_data3.sources().push_back(
333 SourceFile("//quz/Quz.xcassets/Contents.json"));
334 bundle_data3.sources().push_back(
335 SourceFile("//quz/Quz.xcassets/quz.imageset/Contents.json"));
336 bundle_data3.sources().push_back(
337 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29.png"));
338 bundle_data3.sources().push_back(
339 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@2x.png"));
340 bundle_data3.sources().push_back(
341 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@3x.png"));
342 bundle_data3.sources().push_back(
343 SourceFile("//quz/Quz.xcassets/quz.dataset/Contents.json"));
344 bundle_data3.sources().push_back(
345 SourceFile("//quz/Quz.xcassets/quz.dataset/QuzScript.js"));
346 bundle_data3.action_values().outputs() = SubstitutionList::MakeForTest(
347 "{{bundle_resources_dir}}/{{source_file_part}}");
348 bundle_data3.SetToolchain(setup.toolchain());
349 bundle_data3.visibility().SetPublic();
350 ASSERT_TRUE(bundle_data3.OnResolved(&err));
351
352 Target bundle_data4(setup.settings(), Label(SourceDir("//biz/"), "assets"));
353 bundle_data4.set_output_type(Target::BUNDLE_DATA);
354 bundle_data4.sources().push_back(
355 SourceFile("//biz/Biz.xcassets/Contents.json"));
356 bundle_data4.sources().push_back(
357 SourceFile("//biz/Biz.xcassets/biz.colorset/Contents.json"));
358 bundle_data4.action_values().outputs() = SubstitutionList::MakeForTest(
359 "{{bundle_resources_dir}}/{{source_file_part}}");
360 bundle_data4.SetToolchain(setup.toolchain());
361 bundle_data4.visibility().SetPublic();
362 ASSERT_TRUE(bundle_data4.OnResolved(&err));
363
364 Target create_bundle(
365 setup.settings(),
366 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
367 setup.toolchain()->label().name()));
368 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
369 create_bundle.set_output_type(Target::CREATE_BUNDLE);
370 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data0));
371 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data1));
372 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data2));
373 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data3));
374 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data4));
375 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
376 create_bundle.bundle_data().product_type().assign("com.apple.product-type");
377 create_bundle.bundle_data().set_partial_info_plist(
378 SourceFile("//out/Debug/baz/bar/bar_partial_info.plist"));
379 create_bundle.SetToolchain(setup.toolchain());
380 ASSERT_TRUE(create_bundle.OnResolved(&err));
381
382 std::ostringstream out;
383 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
384 writer.Run();
385
386 const char expected[] =
387 "build obj/baz/bar.inputdeps.stamp: stamp obj/biz/assets.stamp "
388 "obj/foo/assets.stamp obj/foo/bar.stamp obj/foo/data.stamp "
389 "obj/qux/info_plist.stamp obj/quz/assets.stamp\n"
390 "build bar.bundle/Contents/Info.plist: copy_bundle_data "
391 "../../qux/qux-Info.plist || obj/baz/bar.inputdeps.stamp\n"
392 "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
393 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
394 "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
395 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
396 "build obj/baz/bar.xcassets.inputdeps.stamp: stamp "
397 "obj/foo/assets.stamp "
398 "obj/quz/assets.stamp obj/biz/assets.stamp\n"
399 "build bar.bundle/Contents/Resources/Assets.car | "
400 "baz/bar/bar_partial_info.plist: compile_xcassets "
401 "../../foo/Foo.xcassets ../../quz/Quz.xcassets "
402 "../../biz/Biz.xcassets | obj/baz/bar.xcassets.inputdeps.stamp || "
403 "obj/baz/bar.inputdeps.stamp\n"
404 " product_type = com.apple.product-type\n"
405 " partial_info_plist = baz/bar/bar_partial_info.plist\n"
406 "build obj/baz/bar.stamp: stamp "
407 "bar.bundle/Contents/Info.plist "
408 "bar.bundle/Contents/Resources/input1.txt "
409 "bar.bundle/Contents/Resources/input2.txt "
410 "bar.bundle/Contents/Resources/Assets.car "
411 "baz/bar/bar_partial_info.plist || obj/baz/bar.inputdeps.stamp\n"
412 "build bar.bundle: phony obj/baz/bar.stamp\n";
413 std::string out_str = out.str();
414 EXPECT_EQ(expected, out_str);
415 }
416
417 // Tests post-processing step.
TEST(NinjaCreateBundleTargetWriter,PostProcessing)418 TEST(NinjaCreateBundleTargetWriter, PostProcessing) {
419 Err err;
420 TestWithScope setup;
421
422 std::unique_ptr<Target> action = NewAction(setup);
423 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
424
425 Target executable(setup.settings(), Label(SourceDir("//baz/"), "quz"));
426 executable.set_output_type(Target::EXECUTABLE);
427 executable.sources().push_back(SourceFile("//baz/quz.c"));
428 executable.SetToolchain(setup.toolchain());
429 executable.visibility().SetPublic();
430 ASSERT_TRUE(executable.OnResolved(&err));
431
432 Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
433 bundle_data.set_output_type(Target::BUNDLE_DATA);
434 bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
435 bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
436 bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
437 "{{bundle_resources_dir}}/{{source_file_part}}");
438 bundle_data.SetToolchain(setup.toolchain());
439 bundle_data.visibility().SetPublic();
440 ASSERT_TRUE(bundle_data.OnResolved(&err));
441
442 Target create_bundle(
443 setup.settings(),
444 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
445 setup.toolchain()->label().name()));
446 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
447 create_bundle.set_output_type(Target::CREATE_BUNDLE);
448 create_bundle.bundle_data().set_post_processing_script(
449 SourceFile("//build/codesign.py"));
450 create_bundle.bundle_data().post_processing_sources().push_back(
451 SourceFile("//out/Debug/quz"));
452 create_bundle.bundle_data().post_processing_outputs() =
453 SubstitutionList::MakeForTest(
454 "//out/Debug/bar.bundle/Contents/quz",
455 "//out/Debug/bar.bundle/_CodeSignature/CodeResources");
456 create_bundle.bundle_data().post_processing_args() =
457 SubstitutionList::MakeForTest("-b=quz", "bar.bundle");
458 create_bundle.public_deps().push_back(LabelTargetPair(&executable));
459 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
460 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
461 create_bundle.SetToolchain(setup.toolchain());
462 ASSERT_TRUE(create_bundle.OnResolved(&err));
463
464 std::ostringstream out;
465 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
466 writer.Run();
467
468 const char expected[] =
469 "build obj/baz/bar.inputdeps.stamp: stamp ./quz obj/foo/bar.stamp "
470 "obj/foo/data.stamp\n"
471 "rule __baz_bar___toolchain_default__post_processing_rule\n"
472 " command = ../../build/codesign.py -b=quz bar.bundle\n"
473 " description = POST PROCESSING //baz:bar(//toolchain:default)\n"
474 " restat = 1\n"
475 "\n"
476 "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
477 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
478 "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
479 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
480 "build obj/baz/bar.postprocessing.inputdeps.stamp: stamp "
481 "../../build/codesign.py "
482 "quz "
483 "bar.bundle/Contents/Resources/input1.txt "
484 "bar.bundle/Contents/Resources/input2.txt || "
485 "obj/baz/bar.inputdeps.stamp\n"
486 "build bar.bundle/Contents/quz bar.bundle/_CodeSignature/CodeResources: "
487 "__baz_bar___toolchain_default__post_processing_rule "
488 "| obj/baz/bar.postprocessing.inputdeps.stamp\n"
489 "build obj/baz/bar.stamp: stamp "
490 "bar.bundle/Contents/quz "
491 "bar.bundle/_CodeSignature/CodeResources || obj/baz/bar.inputdeps.stamp\n"
492 "build bar.bundle: phony obj/baz/bar.stamp\n";
493 std::string out_str = out.str();
494 EXPECT_EQ(expected, out_str);
495 }
496