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.action_values().outputs() = SubstitutionList::MakeForTest(
203 "{{bundle_resources_dir}}/{{source_file_part}}");
204 bundle_data.SetToolchain(setup.toolchain());
205 bundle_data.visibility().SetPublic();
206 ASSERT_TRUE(bundle_data.OnResolved(&err));
207
208 Target create_bundle(
209 setup.settings(),
210 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
211 setup.toolchain()->label().name()));
212 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
213 create_bundle.set_output_type(Target::CREATE_BUNDLE);
214 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
215 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
216 create_bundle.bundle_data().product_type().assign("com.apple.product-type");
217 create_bundle.bundle_data().xcasset_compiler_flags() =
218 SubstitutionList::MakeForTest("--app-icon", "foo");
219
220 create_bundle.SetToolchain(setup.toolchain());
221 ASSERT_TRUE(create_bundle.OnResolved(&err));
222
223 std::ostringstream out;
224 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
225 writer.Run();
226
227 const char expected[] =
228 "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
229 "obj/foo/data.stamp\n"
230 "build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
231 "../../foo/Foo.xcassets | obj/foo/data.stamp || "
232 "obj/baz/bar.inputdeps.stamp\n"
233 " product_type = com.apple.product-type\n"
234 " xcasset_compiler_flags = --app-icon foo\n"
235 "build obj/baz/bar.stamp: stamp "
236 "bar.bundle/Contents/Resources/Assets.car || "
237 "obj/baz/bar.inputdeps.stamp\n"
238 "build bar.bundle: phony obj/baz/bar.stamp\n";
239 std::string out_str = out.str();
240 EXPECT_EQ(expected, out_str);
241 }
242
243 // Tests that the phony target for the top-level bundle directory is generated
244 // correctly.
TEST(NinjaCreateBundleTargetWriter,PhonyTarget)245 TEST(NinjaCreateBundleTargetWriter, PhonyTarget) {
246 Err err;
247 TestWithScope setup;
248
249 Target create_bundle(
250 setup.settings(),
251 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
252 setup.toolchain()->label().name()));
253 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
254 create_bundle.set_output_type(Target::CREATE_BUNDLE);
255 create_bundle.SetToolchain(setup.toolchain());
256 ASSERT_TRUE(create_bundle.OnResolved(&err));
257
258 std::ostringstream out;
259 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
260 writer.Run();
261
262 const char expected[] =
263 "build obj/baz/bar.stamp: stamp\n"
264 "build bar.bundle: phony obj/baz/bar.stamp\n";
265 std::string out_str = out.str();
266 EXPECT_EQ(expected, out_str);
267 }
268
269 // Tests complex target with multiple bundle_data sources, including
270 // some asset catalog.
TEST(NinjaCreateBundleTargetWriter,Complex)271 TEST(NinjaCreateBundleTargetWriter, Complex) {
272 Err err;
273 TestWithScope setup;
274
275 std::unique_ptr<Target> action = NewAction(setup);
276 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
277
278 Target bundle_data0(setup.settings(),
279 Label(SourceDir("//qux/"), "info_plist"));
280 bundle_data0.set_output_type(Target::BUNDLE_DATA);
281 bundle_data0.sources().push_back(SourceFile("//qux/qux-Info.plist"));
282 bundle_data0.action_values().outputs() =
283 SubstitutionList::MakeForTest("{{bundle_contents_dir}}/Info.plist");
284 bundle_data0.SetToolchain(setup.toolchain());
285 bundle_data0.visibility().SetPublic();
286 ASSERT_TRUE(bundle_data0.OnResolved(&err));
287
288 Target bundle_data1(setup.settings(), Label(SourceDir("//foo/"), "data"));
289 bundle_data1.set_output_type(Target::BUNDLE_DATA);
290 bundle_data1.sources().push_back(SourceFile("//foo/input1.txt"));
291 bundle_data1.sources().push_back(SourceFile("//foo/input2.txt"));
292 bundle_data1.action_values().outputs() = SubstitutionList::MakeForTest(
293 "{{bundle_resources_dir}}/{{source_file_part}}");
294 bundle_data1.SetToolchain(setup.toolchain());
295 bundle_data1.visibility().SetPublic();
296 ASSERT_TRUE(bundle_data1.OnResolved(&err));
297
298 Target bundle_data2(setup.settings(), Label(SourceDir("//foo/"), "assets"));
299 bundle_data2.set_output_type(Target::BUNDLE_DATA);
300 bundle_data2.sources().push_back(
301 SourceFile("//foo/Foo.xcassets/Contents.json"));
302 bundle_data2.sources().push_back(
303 SourceFile("//foo/Foo.xcassets/foo.colorset/Contents.json"));
304 bundle_data2.sources().push_back(
305 SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
306 bundle_data2.sources().push_back(
307 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
308 bundle_data2.sources().push_back(
309 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
310 bundle_data2.sources().push_back(
311 SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
312 bundle_data2.sources().push_back(
313 SourceFile("//foo/Foo.xcassets/foo.dataset/Contents.json"));
314 bundle_data2.sources().push_back(
315 SourceFile("//foo/Foo.xcassets/foo.dataset/FooScript.js"));
316 bundle_data2.action_values().outputs() = SubstitutionList::MakeForTest(
317 "{{bundle_resources_dir}}/{{source_file_part}}");
318 bundle_data2.SetToolchain(setup.toolchain());
319 bundle_data2.visibility().SetPublic();
320 ASSERT_TRUE(bundle_data2.OnResolved(&err));
321
322 Target bundle_data3(setup.settings(), Label(SourceDir("//quz/"), "assets"));
323 bundle_data3.set_output_type(Target::BUNDLE_DATA);
324 bundle_data3.sources().push_back(
325 SourceFile("//quz/Quz.xcassets/Contents.json"));
326 bundle_data3.sources().push_back(
327 SourceFile("//quz/Quz.xcassets/quz.imageset/Contents.json"));
328 bundle_data3.sources().push_back(
329 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29.png"));
330 bundle_data3.sources().push_back(
331 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@2x.png"));
332 bundle_data3.sources().push_back(
333 SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@3x.png"));
334 bundle_data3.sources().push_back(
335 SourceFile("//quz/Quz.xcassets/quz.dataset/Contents.json"));
336 bundle_data3.sources().push_back(
337 SourceFile("//quz/Quz.xcassets/quz.dataset/QuzScript.js"));
338 bundle_data3.action_values().outputs() = SubstitutionList::MakeForTest(
339 "{{bundle_resources_dir}}/{{source_file_part}}");
340 bundle_data3.SetToolchain(setup.toolchain());
341 bundle_data3.visibility().SetPublic();
342 ASSERT_TRUE(bundle_data3.OnResolved(&err));
343
344 Target bundle_data4(setup.settings(), Label(SourceDir("//biz/"), "assets"));
345 bundle_data4.set_output_type(Target::BUNDLE_DATA);
346 bundle_data4.sources().push_back(
347 SourceFile("//biz/Biz.xcassets/Contents.json"));
348 bundle_data4.sources().push_back(
349 SourceFile("//biz/Biz.xcassets/biz.colorset/Contents.json"));
350 bundle_data4.action_values().outputs() = SubstitutionList::MakeForTest(
351 "{{bundle_resources_dir}}/{{source_file_part}}");
352 bundle_data4.SetToolchain(setup.toolchain());
353 bundle_data4.visibility().SetPublic();
354 ASSERT_TRUE(bundle_data4.OnResolved(&err));
355
356 Target create_bundle(
357 setup.settings(),
358 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
359 setup.toolchain()->label().name()));
360 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
361 create_bundle.set_output_type(Target::CREATE_BUNDLE);
362 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data0));
363 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data1));
364 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data2));
365 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data3));
366 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data4));
367 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
368 create_bundle.bundle_data().product_type().assign("com.apple.product-type");
369 create_bundle.bundle_data().set_partial_info_plist(
370 SourceFile("//out/Debug/baz/bar/bar_partial_info.plist"));
371 create_bundle.SetToolchain(setup.toolchain());
372 ASSERT_TRUE(create_bundle.OnResolved(&err));
373
374 std::ostringstream out;
375 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
376 writer.Run();
377
378 const char expected[] =
379 "build obj/baz/bar.inputdeps.stamp: stamp obj/biz/assets.stamp "
380 "obj/foo/assets.stamp obj/foo/bar.stamp obj/foo/data.stamp "
381 "obj/qux/info_plist.stamp obj/quz/assets.stamp\n"
382 "build bar.bundle/Contents/Info.plist: copy_bundle_data "
383 "../../qux/qux-Info.plist || obj/baz/bar.inputdeps.stamp\n"
384 "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
385 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
386 "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
387 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
388 "build obj/baz/bar.xcassets.inputdeps.stamp: stamp "
389 "obj/foo/assets.stamp "
390 "obj/quz/assets.stamp obj/biz/assets.stamp\n"
391 "build bar.bundle/Contents/Resources/Assets.car | "
392 "baz/bar/bar_partial_info.plist: compile_xcassets "
393 "../../foo/Foo.xcassets ../../quz/Quz.xcassets "
394 "../../biz/Biz.xcassets | obj/baz/bar.xcassets.inputdeps.stamp || "
395 "obj/baz/bar.inputdeps.stamp\n"
396 " product_type = com.apple.product-type\n"
397 " partial_info_plist = baz/bar/bar_partial_info.plist\n"
398 "build obj/baz/bar.stamp: stamp "
399 "bar.bundle/Contents/Info.plist "
400 "bar.bundle/Contents/Resources/input1.txt "
401 "bar.bundle/Contents/Resources/input2.txt "
402 "bar.bundle/Contents/Resources/Assets.car "
403 "baz/bar/bar_partial_info.plist || obj/baz/bar.inputdeps.stamp\n"
404 "build bar.bundle: phony obj/baz/bar.stamp\n";
405 std::string out_str = out.str();
406 EXPECT_EQ(expected, out_str);
407 }
408
409 // Tests code signing steps.
TEST(NinjaCreateBundleTargetWriter,CodeSigning)410 TEST(NinjaCreateBundleTargetWriter, CodeSigning) {
411 Err err;
412 TestWithScope setup;
413
414 std::unique_ptr<Target> action = NewAction(setup);
415 ASSERT_TRUE(action->OnResolved(&err)) << err.message();
416
417 Target executable(setup.settings(), Label(SourceDir("//baz/"), "quz"));
418 executable.set_output_type(Target::EXECUTABLE);
419 executable.sources().push_back(SourceFile("//baz/quz.c"));
420 executable.SetToolchain(setup.toolchain());
421 executable.visibility().SetPublic();
422 ASSERT_TRUE(executable.OnResolved(&err));
423
424 Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
425 bundle_data.set_output_type(Target::BUNDLE_DATA);
426 bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
427 bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
428 bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
429 "{{bundle_resources_dir}}/{{source_file_part}}");
430 bundle_data.SetToolchain(setup.toolchain());
431 bundle_data.visibility().SetPublic();
432 ASSERT_TRUE(bundle_data.OnResolved(&err));
433
434 Target create_bundle(
435 setup.settings(),
436 Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
437 setup.toolchain()->label().name()));
438 SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
439 create_bundle.set_output_type(Target::CREATE_BUNDLE);
440 create_bundle.bundle_data().set_code_signing_script(
441 SourceFile("//build/codesign.py"));
442 create_bundle.bundle_data().code_signing_sources().push_back(
443 SourceFile("//out/Debug/quz"));
444 create_bundle.bundle_data().code_signing_outputs() =
445 SubstitutionList::MakeForTest(
446 "//out/Debug/bar.bundle/Contents/quz",
447 "//out/Debug/bar.bundle/_CodeSignature/CodeResources");
448 create_bundle.bundle_data().code_signing_args() =
449 SubstitutionList::MakeForTest("-b=quz", "bar.bundle");
450 create_bundle.public_deps().push_back(LabelTargetPair(&executable));
451 create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
452 create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
453 create_bundle.SetToolchain(setup.toolchain());
454 ASSERT_TRUE(create_bundle.OnResolved(&err));
455
456 std::ostringstream out;
457 NinjaCreateBundleTargetWriter writer(&create_bundle, out);
458 writer.Run();
459
460 const char expected[] =
461 "build obj/baz/bar.inputdeps.stamp: stamp ./quz obj/foo/bar.stamp "
462 "obj/foo/data.stamp\n"
463 "rule __baz_bar___toolchain_default__code_signing_rule\n"
464 " command = ../../build/codesign.py -b=quz bar.bundle\n"
465 " description = CODE SIGNING //baz:bar(//toolchain:default)\n"
466 " restat = 1\n"
467 "\n"
468 "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
469 "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
470 "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
471 "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
472 "build obj/baz/bar.codesigning.inputdeps.stamp: stamp "
473 "../../build/codesign.py "
474 "quz "
475 "bar.bundle/Contents/Resources/input1.txt "
476 "bar.bundle/Contents/Resources/input2.txt || "
477 "obj/baz/bar.inputdeps.stamp\n"
478 "build bar.bundle/Contents/quz bar.bundle/_CodeSignature/CodeResources: "
479 "__baz_bar___toolchain_default__code_signing_rule "
480 "| obj/baz/bar.codesigning.inputdeps.stamp\n"
481 "build obj/baz/bar.stamp: stamp "
482 "bar.bundle/Contents/quz "
483 "bar.bundle/_CodeSignature/CodeResources || obj/baz/bar.inputdeps.stamp\n"
484 "build bar.bundle: phony obj/baz/bar.stamp\n";
485 std::string out_str = out.str();
486 EXPECT_EQ(expected, out_str);
487 }
488