blob: 690277c664a6358d814bb86d240696307ecfc965 [file] [log] [blame]
Colin Cross2a076922018-10-04 23:28:25 -07001// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package genrule
16
17import (
18 "io/ioutil"
19 "os"
Paul Duffin672cb9f2021-03-03 02:30:37 +000020 "regexp"
Colin Cross2a076922018-10-04 23:28:25 -070021 "testing"
22
23 "android/soong/android"
Colin Crossba71a3f2019-03-18 12:12:48 -070024
25 "github.com/google/blueprint/proptools"
Colin Cross2a076922018-10-04 23:28:25 -070026)
27
28var buildDir string
29
30func setUp() {
31 var err error
Colin Crossef354482018-10-23 11:27:50 -070032 buildDir, err = ioutil.TempDir("", "genrule_test")
Colin Cross2a076922018-10-04 23:28:25 -070033 if err != nil {
34 panic(err)
35 }
36}
37
38func tearDown() {
39 os.RemoveAll(buildDir)
40}
41
42func TestMain(m *testing.M) {
43 run := func() int {
44 setUp()
45 defer tearDown()
46
47 return m.Run()
48 }
49
50 os.Exit(run())
51}
52
Paul Duffin672cb9f2021-03-03 02:30:37 +000053var genruleFixtureFactory = android.NewFixtureFactory(
54 &buildDir,
55 android.PrepareForTestWithArchMutator,
56 android.PrepareForTestWithDefaults,
Colin Cross2a076922018-10-04 23:28:25 -070057
Paul Duffin672cb9f2021-03-03 02:30:37 +000058 android.PrepareForTestWithFilegroup,
59 PrepareForTestWithGenRuleBuildComponents,
60 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
61 ctx.RegisterModuleType("tool", toolFactory)
62 }),
63 android.FixtureMergeMockFs(android.MockFS{
64 "tool": nil,
65 "tool_file1": nil,
66 "tool_file2": nil,
67 "in1": nil,
68 "in2": nil,
69 "in1.txt": nil,
70 "in2.txt": nil,
71 "in3.txt": nil,
72 }),
73)
Martin Stjernholm710ec3a2020-01-16 15:12:04 +000074
Paul Duffin672cb9f2021-03-03 02:30:37 +000075func testGenruleBp() string {
76 return `
Colin Cross2a076922018-10-04 23:28:25 -070077 tool {
78 name: "tool",
79 }
80
81 filegroup {
82 name: "tool_files",
83 srcs: [
84 "tool_file1",
85 "tool_file2",
86 ],
87 }
88
89 filegroup {
90 name: "1tool_file",
91 srcs: [
92 "tool_file1",
93 ],
94 }
95
96 filegroup {
97 name: "ins",
98 srcs: [
99 "in1",
100 "in2",
101 ],
102 }
103
104 filegroup {
105 name: "1in",
106 srcs: [
107 "in1",
108 ],
109 }
110
111 filegroup {
112 name: "empty",
113 }
114 `
Colin Cross2a076922018-10-04 23:28:25 -0700115}
116
117func TestGenruleCmd(t *testing.T) {
118 testcases := []struct {
119 name string
120 prop string
121
Colin Crossba71a3f2019-03-18 12:12:48 -0700122 allowMissingDependencies bool
123
Colin Cross2a076922018-10-04 23:28:25 -0700124 err string
125 expect string
126 }{
127 {
128 name: "empty location tool",
129 prop: `
130 tools: ["tool"],
131 out: ["out"],
132 cmd: "$(location) > $(out)",
133 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800134 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700135 },
136 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700137 name: "empty location tool2",
138 prop: `
139 tools: [":tool"],
140 out: ["out"],
141 cmd: "$(location) > $(out)",
142 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800143 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700144 },
145 {
Colin Cross2a076922018-10-04 23:28:25 -0700146 name: "empty location tool file",
147 prop: `
148 tool_files: ["tool_file1"],
149 out: ["out"],
150 cmd: "$(location) > $(out)",
151 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800152 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700153 },
154 {
155 name: "empty location tool file fg",
156 prop: `
157 tool_files: [":1tool_file"],
158 out: ["out"],
159 cmd: "$(location) > $(out)",
160 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800161 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700162 },
163 {
164 name: "empty location tool and tool file",
165 prop: `
166 tools: ["tool"],
167 tool_files: ["tool_file1"],
168 out: ["out"],
169 cmd: "$(location) > $(out)",
170 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800171 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700172 },
173 {
174 name: "tool",
175 prop: `
176 tools: ["tool"],
177 out: ["out"],
178 cmd: "$(location tool) > $(out)",
179 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800180 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700181 },
182 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700183 name: "tool2",
184 prop: `
185 tools: [":tool"],
186 out: ["out"],
187 cmd: "$(location :tool) > $(out)",
188 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800189 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700190 },
191 {
Colin Cross2a076922018-10-04 23:28:25 -0700192 name: "tool file",
193 prop: `
194 tool_files: ["tool_file1"],
195 out: ["out"],
196 cmd: "$(location tool_file1) > $(out)",
197 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800198 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700199 },
200 {
201 name: "tool file fg",
202 prop: `
203 tool_files: [":1tool_file"],
204 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700205 cmd: "$(location :1tool_file) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700206 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800207 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700208 },
209 {
210 name: "tool files",
211 prop: `
212 tool_files: [":tool_files"],
213 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700214 cmd: "$(locations :tool_files) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700215 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800216 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 __SBOX_SANDBOX_DIR__/tools/src/tool_file2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700217 },
218 {
219 name: "in1",
220 prop: `
221 srcs: ["in1"],
222 out: ["out"],
223 cmd: "cat $(in) > $(out)",
224 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800225 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700226 },
227 {
228 name: "in1 fg",
229 prop: `
230 srcs: [":1in"],
231 out: ["out"],
232 cmd: "cat $(in) > $(out)",
233 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800234 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700235 },
236 {
237 name: "ins",
238 prop: `
239 srcs: ["in1", "in2"],
240 out: ["out"],
241 cmd: "cat $(in) > $(out)",
242 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800243 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700244 },
245 {
246 name: "ins fg",
247 prop: `
248 srcs: [":ins"],
249 out: ["out"],
250 cmd: "cat $(in) > $(out)",
251 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800252 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700253 },
254 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700255 name: "location in1",
256 prop: `
257 srcs: ["in1"],
258 out: ["out"],
259 cmd: "cat $(location in1) > $(out)",
260 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800261 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700262 },
263 {
264 name: "location in1 fg",
265 prop: `
266 srcs: [":1in"],
267 out: ["out"],
268 cmd: "cat $(location :1in) > $(out)",
269 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800270 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700271 },
272 {
273 name: "location ins",
274 prop: `
275 srcs: ["in1", "in2"],
276 out: ["out"],
277 cmd: "cat $(location in1) > $(out)",
278 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800279 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700280 },
281 {
282 name: "location ins fg",
283 prop: `
284 srcs: [":ins"],
285 out: ["out"],
286 cmd: "cat $(locations :ins) > $(out)",
287 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800288 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700289 },
290 {
Colin Cross2a076922018-10-04 23:28:25 -0700291 name: "outs",
292 prop: `
293 out: ["out", "out2"],
294 cmd: "echo foo > $(out)",
295 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800296 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross2a076922018-10-04 23:28:25 -0700297 },
298 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700299 name: "location out",
300 prop: `
301 out: ["out", "out2"],
302 cmd: "echo foo > $(location out2)",
303 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800304 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross08f15ab2018-10-04 23:29:14 -0700305 },
306 {
Colin Cross2a076922018-10-04 23:28:25 -0700307 name: "depfile",
308 prop: `
309 out: ["out"],
310 depfile: true,
311 cmd: "echo foo > $(out) && touch $(depfile)",
312 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800313 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out && touch __SBOX_DEPFILE__",
Colin Cross2a076922018-10-04 23:28:25 -0700314 },
315 {
316 name: "gendir",
317 prop: `
318 out: ["out"],
319 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
320 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800321 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/foo && cp __SBOX_SANDBOX_DIR__/out/foo __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700322 },
323
324 {
325 name: "error empty location",
326 prop: `
327 out: ["out"],
328 cmd: "$(location) > $(out)",
329 `,
330 err: "at least one `tools` or `tool_files` is required if $(location) is used",
331 },
332 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700333 name: "error empty location no files",
334 prop: `
335 tool_files: [":empty"],
336 out: ["out"],
337 cmd: "$(location) > $(out)",
338 `,
339 err: `default label ":empty" has no files`,
340 },
341 {
342 name: "error empty location multiple files",
343 prop: `
344 tool_files: [":tool_files"],
345 out: ["out"],
346 cmd: "$(location) > $(out)",
347 `,
348 err: `default label ":tool_files" has multiple files`,
349 },
350 {
Colin Cross2a076922018-10-04 23:28:25 -0700351 name: "error location",
352 prop: `
353 out: ["out"],
354 cmd: "echo foo > $(location missing)",
355 `,
356 err: `unknown location label "missing"`,
357 },
358 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700359 name: "error locations",
360 prop: `
361 out: ["out"],
362 cmd: "echo foo > $(locations missing)",
363 `,
364 err: `unknown locations label "missing"`,
365 },
366 {
367 name: "error location no files",
368 prop: `
369 out: ["out"],
370 srcs: [":empty"],
371 cmd: "echo $(location :empty) > $(out)",
372 `,
373 err: `label ":empty" has no files`,
374 },
375 {
376 name: "error locations no files",
377 prop: `
378 out: ["out"],
379 srcs: [":empty"],
380 cmd: "echo $(locations :empty) > $(out)",
381 `,
382 err: `label ":empty" has no files`,
383 },
384 {
385 name: "error location multiple files",
386 prop: `
387 out: ["out"],
388 srcs: [":ins"],
389 cmd: "echo $(location :ins) > $(out)",
390 `,
391 err: `label ":ins" has multiple files`,
392 },
393 {
Colin Cross2a076922018-10-04 23:28:25 -0700394 name: "error variable",
395 prop: `
396 out: ["out"],
397 srcs: ["in1"],
398 cmd: "echo $(foo) > $(out)",
399 `,
400 err: `unknown variable '$(foo)'`,
401 },
402 {
403 name: "error depfile",
404 prop: `
405 out: ["out"],
406 cmd: "echo foo > $(out) && touch $(depfile)",
407 `,
408 err: "$(depfile) used without depfile property",
409 },
410 {
411 name: "error no depfile",
412 prop: `
413 out: ["out"],
414 depfile: true,
415 cmd: "echo foo > $(out)",
416 `,
417 err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
418 },
419 {
420 name: "error no out",
421 prop: `
422 cmd: "echo foo > $(out)",
423 `,
424 err: "must have at least one output file",
425 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700426 {
427 name: "srcs allow missing dependencies",
428 prop: `
429 srcs: [":missing"],
430 out: ["out"],
431 cmd: "cat $(location :missing) > $(out)",
432 `,
433
434 allowMissingDependencies: true,
435
Colin Crosse16ce362020-11-12 08:29:30 -0800436 expect: "cat ***missing srcs :missing*** > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700437 },
438 {
439 name: "tool allow missing dependencies",
440 prop: `
441 tools: [":missing"],
442 out: ["out"],
443 cmd: "$(location :missing) > $(out)",
444 `,
445
446 allowMissingDependencies: true,
447
Colin Crosse16ce362020-11-12 08:29:30 -0800448 expect: "***missing tool :missing*** > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700449 },
Colin Cross2a076922018-10-04 23:28:25 -0700450 }
451
452 for _, test := range testcases {
453 t.Run(test.name, func(t *testing.T) {
Colin Cross2a076922018-10-04 23:28:25 -0700454 bp := "genrule {\n"
455 bp += "name: \"gen\",\n"
456 bp += test.prop
457 bp += "}\n"
458
Paul Duffin672cb9f2021-03-03 02:30:37 +0000459 var expectedErrors []string
460 if test.err != "" {
461 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700462 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000463
464 result := genruleFixtureFactory.Extend(
465 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
466 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
467 }),
468 android.FixtureModifyContext(func(ctx *android.TestContext) {
469 ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
470 }),
471 ).
472 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
473 RunTestWithBp(t, testGenruleBp()+bp)
474
475 if expectedErrors != nil {
Colin Cross2a076922018-10-04 23:28:25 -0700476 return
477 }
478
Paul Duffin672cb9f2021-03-03 02:30:37 +0000479 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000480 android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
Colin Cross2a076922018-10-04 23:28:25 -0700481 })
482 }
Colin Cross1a527682019-09-23 15:55:30 -0700483}
484
Bill Peckhamc087be12020-02-13 15:55:10 -0800485func TestGenruleHashInputs(t *testing.T) {
486
487 // The basic idea here is to verify that the sbox command (which is
488 // in the Command field of the generate rule) contains a hash of the
489 // inputs, but only if $(in) is not referenced in the genrule cmd
490 // property.
491
492 // By including a hash of the inputs, we cause the rule to re-run if
493 // the list of inputs changes (because the sbox command changes).
494
495 // However, if the genrule cmd property already contains $(in), then
496 // the dependency is already expressed, so we don't need to include the
497 // hash in that case.
498
499 bp := `
500 genrule {
501 name: "hash0",
502 srcs: ["in1.txt", "in2.txt"],
503 out: ["out"],
504 cmd: "echo foo > $(out)",
505 }
506 genrule {
507 name: "hash1",
508 srcs: ["*.txt"],
509 out: ["out"],
510 cmd: "echo bar > $(out)",
511 }
512 genrule {
513 name: "hash2",
514 srcs: ["*.txt"],
515 out: ["out"],
516 cmd: "echo $(in) > $(out)",
517 }
518 `
519 testcases := []struct {
520 name string
521 expectedHash string
522 }{
523 {
524 name: "hash0",
Colin Cross3d680512020-11-13 16:23:53 -0800525 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
526 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
Bill Peckhamc087be12020-02-13 15:55:10 -0800527 },
528 {
529 name: "hash1",
Colin Cross3d680512020-11-13 16:23:53 -0800530 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
531 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800532 },
533 {
534 name: "hash2",
Colin Cross3d680512020-11-13 16:23:53 -0800535 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
536 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800537 },
538 }
539
Paul Duffin672cb9f2021-03-03 02:30:37 +0000540 result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
Bill Peckhamc087be12020-02-13 15:55:10 -0800541
542 for _, test := range testcases {
543 t.Run(test.name, func(t *testing.T) {
Paul Duffine84b1332021-03-12 11:59:43 +0000544 gen := result.ModuleForTests(test.name, "")
Colin Crosse16ce362020-11-12 08:29:30 -0800545 manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
546 hash := manifest.Commands[0].GetInputHash()
Bill Peckhamc087be12020-02-13 15:55:10 -0800547
Paul Duffine84b1332021-03-12 11:59:43 +0000548 android.AssertStringEquals(t, "hash", test.expectedHash, hash)
Bill Peckhamc087be12020-02-13 15:55:10 -0800549 })
550 }
551}
552
Colin Cross1a527682019-09-23 15:55:30 -0700553func TestGenSrcs(t *testing.T) {
554 testcases := []struct {
555 name string
556 prop string
557
558 allowMissingDependencies bool
559
560 err string
561 cmds []string
562 deps []string
563 files []string
564 }{
565 {
566 name: "gensrcs",
567 prop: `
568 tools: ["tool"],
569 srcs: ["in1.txt", "in2.txt"],
570 cmd: "$(location) $(in) > $(out)",
571 `,
572 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800573 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700574 },
575 deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
576 files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
577 },
578 {
579 name: "shards",
580 prop: `
581 tools: ["tool"],
582 srcs: ["in1.txt", "in2.txt", "in3.txt"],
583 cmd: "$(location) $(in) > $(out)",
584 shard_size: 2,
585 `,
586 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800587 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
588 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700589 },
590 deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
591 files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
592 },
593 }
594
595 for _, test := range testcases {
596 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700597 bp := "gensrcs {\n"
598 bp += `name: "gen",` + "\n"
599 bp += `output_extension: "h",` + "\n"
600 bp += test.prop
601 bp += "}\n"
602
Paul Duffin672cb9f2021-03-03 02:30:37 +0000603 var expectedErrors []string
604 if test.err != "" {
605 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700606 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000607
608 result := genruleFixtureFactory.
609 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
610 RunTestWithBp(t, testGenruleBp()+bp)
611
612 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700613 return
614 }
615
Paul Duffin672cb9f2021-03-03 02:30:37 +0000616 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000617 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700618
Paul Duffine84b1332021-03-12 11:59:43 +0000619 android.AssertDeepEquals(t, "deps", test.deps, gen.outputDeps.Strings())
Colin Cross1a527682019-09-23 15:55:30 -0700620
Paul Duffine84b1332021-03-12 11:59:43 +0000621 android.AssertDeepEquals(t, "files", test.files, gen.outputFiles.Strings())
Colin Cross1a527682019-09-23 15:55:30 -0700622 })
623 }
Colin Cross2a076922018-10-04 23:28:25 -0700624}
625
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800626func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800627 bp := `
628 genrule_defaults {
629 name: "gen_defaults1",
630 cmd: "cp $(in) $(out)",
631 }
632
633 genrule_defaults {
634 name: "gen_defaults2",
635 srcs: ["in1"],
636 }
637
638 genrule {
639 name: "gen",
640 out: ["out"],
641 defaults: ["gen_defaults1", "gen_defaults2"],
642 }
643 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000644
645 result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
646
647 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800648
Colin Crosse16ce362020-11-12 08:29:30 -0800649 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000650 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800651
652 expectedSrcs := []string{"in1"}
Paul Duffine84b1332021-03-12 11:59:43 +0000653 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800654}
655
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400656func TestGenruleWithBazel(t *testing.T) {
657 bp := `
658 genrule {
659 name: "foo",
660 out: ["one.txt", "two.txt"],
Chris Parsonsaa8be052020-10-14 16:22:37 -0400661 bazel_module: { label: "//foo/bar:bar" },
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400662 }
663 `
664
Paul Duffin672cb9f2021-03-03 02:30:37 +0000665 result := genruleFixtureFactory.Extend(android.FixtureModifyConfig(func(config android.Config) {
666 config.BazelContext = android.MockBazelContext{
667 AllFiles: map[string][]string{
668 "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
669 })).RunTestWithBp(t, testGenruleBp()+bp)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400670
Paul Duffin672cb9f2021-03-03 02:30:37 +0000671 gen := result.Module("foo", "").(*Module)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400672
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500673 expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
674 "outputbase/execroot/__main__/bazeltwo.txt"}
Paul Duffine84b1332021-03-12 11:59:43 +0000675 android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
676 android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400677}
678
Colin Cross2a076922018-10-04 23:28:25 -0700679type testTool struct {
680 android.ModuleBase
681 outputFile android.Path
682}
683
684func toolFactory() android.Module {
685 module := &testTool{}
686 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
687 return module
688}
689
Colin Cross2a076922018-10-04 23:28:25 -0700690func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -0800691 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -0700692}
693
694func (t *testTool) HostToolPath() android.OptionalPath {
695 return android.OptionalPathForPath(t.outputFile)
696}
697
Colin Crossfe17f6f2019-03-28 19:30:56 -0700698var _ android.HostToolProvider = (*testTool)(nil)