blob: 444aedb90b7cda05d0a7965affe1b1580a8406e2 [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 (
Vinh Tran140d5882022-06-10 14:23:27 -040018 "fmt"
Colin Cross2a076922018-10-04 23:28:25 -070019 "os"
Paul Duffin672cb9f2021-03-03 02:30:37 +000020 "regexp"
Liz Kammer796921d2023-07-11 08:21:41 -040021 "strconv"
Colin Cross2a076922018-10-04 23:28:25 -070022 "testing"
23
24 "android/soong/android"
Colin Crossba71a3f2019-03-18 12:12:48 -070025
26 "github.com/google/blueprint/proptools"
Colin Cross2a076922018-10-04 23:28:25 -070027)
28
Colin Cross2a076922018-10-04 23:28:25 -070029func TestMain(m *testing.M) {
Paul Duffine66946b2021-03-16 12:38:33 +000030 os.Exit(m.Run())
Colin Cross2a076922018-10-04 23:28:25 -070031}
32
Paul Duffin89648f92021-03-20 00:36:55 +000033var prepareForGenRuleTest = android.GroupFixturePreparers(
Paul Duffin672cb9f2021-03-03 02:30:37 +000034 android.PrepareForTestWithArchMutator,
35 android.PrepareForTestWithDefaults,
Paul Duffin672cb9f2021-03-03 02:30:37 +000036 android.PrepareForTestWithFilegroup,
37 PrepareForTestWithGenRuleBuildComponents,
38 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000039 android.RegisterPrebuiltMutators(ctx)
Paul Duffin672cb9f2021-03-03 02:30:37 +000040 ctx.RegisterModuleType("tool", toolFactory)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000041 ctx.RegisterModuleType("prebuilt_tool", prebuiltToolFactory)
Colin Crossfa65cee2021-03-22 17:05:59 -070042 ctx.RegisterModuleType("output", outputProducerFactory)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +090043 ctx.RegisterModuleType("use_source", useSourceFactory)
Paul Duffin672cb9f2021-03-03 02:30:37 +000044 }),
45 android.FixtureMergeMockFs(android.MockFS{
46 "tool": nil,
47 "tool_file1": nil,
48 "tool_file2": nil,
49 "in1": nil,
50 "in2": nil,
51 "in1.txt": nil,
52 "in2.txt": nil,
53 "in3.txt": nil,
54 }),
55)
Martin Stjernholm710ec3a2020-01-16 15:12:04 +000056
Paul Duffin672cb9f2021-03-03 02:30:37 +000057func testGenruleBp() string {
58 return `
Colin Cross2a076922018-10-04 23:28:25 -070059 tool {
60 name: "tool",
61 }
62
63 filegroup {
64 name: "tool_files",
65 srcs: [
66 "tool_file1",
67 "tool_file2",
68 ],
69 }
70
71 filegroup {
72 name: "1tool_file",
73 srcs: [
74 "tool_file1",
75 ],
76 }
77
78 filegroup {
79 name: "ins",
80 srcs: [
81 "in1",
82 "in2",
83 ],
84 }
85
86 filegroup {
87 name: "1in",
88 srcs: [
89 "in1",
90 ],
91 }
92
93 filegroup {
94 name: "empty",
95 }
96 `
Colin Cross2a076922018-10-04 23:28:25 -070097}
98
99func TestGenruleCmd(t *testing.T) {
100 testcases := []struct {
Yu Liu6a7940c2023-05-09 17:12:22 -0700101 name string
102 moduleName string
103 prop string
Colin Cross2a076922018-10-04 23:28:25 -0700104
Colin Crossba71a3f2019-03-18 12:12:48 -0700105 allowMissingDependencies bool
106
Colin Cross2a076922018-10-04 23:28:25 -0700107 err string
108 expect string
109 }{
110 {
111 name: "empty location tool",
112 prop: `
113 tools: ["tool"],
114 out: ["out"],
115 cmd: "$(location) > $(out)",
116 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800117 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700118 },
119 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700120 name: "empty location tool2",
121 prop: `
122 tools: [":tool"],
123 out: ["out"],
124 cmd: "$(location) > $(out)",
125 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800126 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700127 },
128 {
Colin Cross2a076922018-10-04 23:28:25 -0700129 name: "empty location tool file",
130 prop: `
131 tool_files: ["tool_file1"],
132 out: ["out"],
133 cmd: "$(location) > $(out)",
134 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800135 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700136 },
137 {
138 name: "empty location tool file fg",
139 prop: `
140 tool_files: [":1tool_file"],
141 out: ["out"],
142 cmd: "$(location) > $(out)",
143 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800144 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700145 },
146 {
147 name: "empty location tool and tool file",
148 prop: `
149 tools: ["tool"],
150 tool_files: ["tool_file1"],
151 out: ["out"],
152 cmd: "$(location) > $(out)",
153 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800154 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700155 },
156 {
157 name: "tool",
158 prop: `
159 tools: ["tool"],
160 out: ["out"],
161 cmd: "$(location tool) > $(out)",
162 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800163 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700164 },
165 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700166 name: "tool2",
167 prop: `
168 tools: [":tool"],
169 out: ["out"],
170 cmd: "$(location :tool) > $(out)",
171 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800172 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700173 },
174 {
Colin Cross2a076922018-10-04 23:28:25 -0700175 name: "tool file",
176 prop: `
177 tool_files: ["tool_file1"],
178 out: ["out"],
179 cmd: "$(location tool_file1) > $(out)",
180 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800181 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700182 },
183 {
184 name: "tool file fg",
185 prop: `
186 tool_files: [":1tool_file"],
187 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700188 cmd: "$(location :1tool_file) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700189 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800190 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700191 },
192 {
193 name: "tool files",
194 prop: `
195 tool_files: [":tool_files"],
196 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700197 cmd: "$(locations :tool_files) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700198 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800199 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 -0700200 },
201 {
202 name: "in1",
203 prop: `
204 srcs: ["in1"],
205 out: ["out"],
206 cmd: "cat $(in) > $(out)",
207 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800208 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700209 },
210 {
211 name: "in1 fg",
212 prop: `
213 srcs: [":1in"],
214 out: ["out"],
215 cmd: "cat $(in) > $(out)",
216 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800217 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700218 },
219 {
220 name: "ins",
221 prop: `
222 srcs: ["in1", "in2"],
223 out: ["out"],
224 cmd: "cat $(in) > $(out)",
225 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800226 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700227 },
228 {
229 name: "ins fg",
230 prop: `
231 srcs: [":ins"],
232 out: ["out"],
233 cmd: "cat $(in) > $(out)",
234 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800235 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700236 },
237 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700238 name: "location in1",
239 prop: `
240 srcs: ["in1"],
241 out: ["out"],
242 cmd: "cat $(location in1) > $(out)",
243 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800244 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700245 },
246 {
247 name: "location in1 fg",
248 prop: `
249 srcs: [":1in"],
250 out: ["out"],
251 cmd: "cat $(location :1in) > $(out)",
252 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800253 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700254 },
255 {
256 name: "location ins",
257 prop: `
258 srcs: ["in1", "in2"],
259 out: ["out"],
260 cmd: "cat $(location in1) > $(out)",
261 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800262 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700263 },
264 {
265 name: "location ins fg",
266 prop: `
267 srcs: [":ins"],
268 out: ["out"],
269 cmd: "cat $(locations :ins) > $(out)",
270 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800271 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700272 },
273 {
Colin Cross2a076922018-10-04 23:28:25 -0700274 name: "outs",
275 prop: `
276 out: ["out", "out2"],
277 cmd: "echo foo > $(out)",
278 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800279 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross2a076922018-10-04 23:28:25 -0700280 },
281 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700282 name: "location out",
283 prop: `
284 out: ["out", "out2"],
285 cmd: "echo foo > $(location out2)",
286 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800287 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross08f15ab2018-10-04 23:29:14 -0700288 },
289 {
Colin Cross2a076922018-10-04 23:28:25 -0700290 name: "gendir",
291 prop: `
292 out: ["out"],
293 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
294 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800295 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 -0700296 },
Colin Cross70c47412021-03-12 17:48:14 -0800297 {
298 name: "$",
299 prop: `
300 out: ["out"],
301 cmd: "echo $$ > $(out)",
302 `,
303 expect: "echo $ > __SBOX_SANDBOX_DIR__/out/out",
304 },
Colin Cross2a076922018-10-04 23:28:25 -0700305
306 {
307 name: "error empty location",
308 prop: `
309 out: ["out"],
310 cmd: "$(location) > $(out)",
311 `,
312 err: "at least one `tools` or `tool_files` is required if $(location) is used",
313 },
314 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700315 name: "error empty location no files",
316 prop: `
317 tool_files: [":empty"],
318 out: ["out"],
319 cmd: "$(location) > $(out)",
320 `,
321 err: `default label ":empty" has no files`,
322 },
323 {
324 name: "error empty location multiple files",
325 prop: `
326 tool_files: [":tool_files"],
327 out: ["out"],
328 cmd: "$(location) > $(out)",
329 `,
330 err: `default label ":tool_files" has multiple files`,
331 },
332 {
Colin Cross2a076922018-10-04 23:28:25 -0700333 name: "error location",
334 prop: `
335 out: ["out"],
336 cmd: "echo foo > $(location missing)",
337 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000338 err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
Colin Cross2a076922018-10-04 23:28:25 -0700339 },
340 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700341 name: "error locations",
342 prop: `
343 out: ["out"],
344 cmd: "echo foo > $(locations missing)",
345 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000346 err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
Colin Cross08f15ab2018-10-04 23:29:14 -0700347 },
348 {
349 name: "error location no files",
350 prop: `
351 out: ["out"],
352 srcs: [":empty"],
353 cmd: "echo $(location :empty) > $(out)",
354 `,
355 err: `label ":empty" has no files`,
356 },
357 {
358 name: "error locations no files",
359 prop: `
360 out: ["out"],
361 srcs: [":empty"],
362 cmd: "echo $(locations :empty) > $(out)",
363 `,
364 err: `label ":empty" has no files`,
365 },
366 {
367 name: "error location multiple files",
368 prop: `
369 out: ["out"],
370 srcs: [":ins"],
371 cmd: "echo $(location :ins) > $(out)",
372 `,
373 err: `label ":ins" has multiple files`,
374 },
375 {
Colin Cross2a076922018-10-04 23:28:25 -0700376 name: "error variable",
377 prop: `
378 out: ["out"],
379 srcs: ["in1"],
380 cmd: "echo $(foo) > $(out)",
381 `,
382 err: `unknown variable '$(foo)'`,
383 },
384 {
Colin Cross2a076922018-10-04 23:28:25 -0700385 name: "error no out",
386 prop: `
387 cmd: "echo foo > $(out)",
388 `,
389 err: "must have at least one output file",
390 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700391 {
392 name: "srcs allow missing dependencies",
393 prop: `
394 srcs: [":missing"],
395 out: ["out"],
396 cmd: "cat $(location :missing) > $(out)",
397 `,
398
399 allowMissingDependencies: true,
400
Jihoon Kangc170af42022-08-20 05:26:38 +0000401 expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700402 },
403 {
404 name: "tool allow missing dependencies",
405 prop: `
406 tools: [":missing"],
407 out: ["out"],
408 cmd: "$(location :missing) > $(out)",
409 `,
410
411 allowMissingDependencies: true,
412
Jihoon Kangc170af42022-08-20 05:26:38 +0000413 expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700414 },
Colin Cross2a076922018-10-04 23:28:25 -0700415 }
416
417 for _, test := range testcases {
418 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700419 moduleName := "gen"
420 if test.moduleName != "" {
421 moduleName = test.moduleName
422 }
423 bp := fmt.Sprintf(`
424 genrule {
425 name: "%s",
426 %s
427 }`, moduleName, test.prop)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000428 var expectedErrors []string
429 if test.err != "" {
430 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700431 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000432
Paul Duffin89648f92021-03-20 00:36:55 +0000433 result := android.GroupFixturePreparers(
434 prepareForGenRuleTest,
Paul Duffin672cb9f2021-03-03 02:30:37 +0000435 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
436 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
437 }),
Yu Liu6a7940c2023-05-09 17:12:22 -0700438 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
439 variables.GenruleSandboxing = proptools.BoolPtr(true)
440 }),
Paul Duffin672cb9f2021-03-03 02:30:37 +0000441 android.FixtureModifyContext(func(ctx *android.TestContext) {
442 ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
443 }),
444 ).
445 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
446 RunTestWithBp(t, testGenruleBp()+bp)
447
448 if expectedErrors != nil {
Colin Cross2a076922018-10-04 23:28:25 -0700449 return
450 }
451
Yu Liu6a7940c2023-05-09 17:12:22 -0700452 gen := result.Module(moduleName, "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000453 android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
Colin Cross2a076922018-10-04 23:28:25 -0700454 })
455 }
Colin Cross1a527682019-09-23 15:55:30 -0700456}
457
Bill Peckhamc087be12020-02-13 15:55:10 -0800458func TestGenruleHashInputs(t *testing.T) {
459
460 // The basic idea here is to verify that the sbox command (which is
461 // in the Command field of the generate rule) contains a hash of the
462 // inputs, but only if $(in) is not referenced in the genrule cmd
463 // property.
464
465 // By including a hash of the inputs, we cause the rule to re-run if
466 // the list of inputs changes (because the sbox command changes).
467
468 // However, if the genrule cmd property already contains $(in), then
469 // the dependency is already expressed, so we don't need to include the
470 // hash in that case.
471
472 bp := `
473 genrule {
474 name: "hash0",
475 srcs: ["in1.txt", "in2.txt"],
476 out: ["out"],
477 cmd: "echo foo > $(out)",
478 }
479 genrule {
480 name: "hash1",
481 srcs: ["*.txt"],
482 out: ["out"],
483 cmd: "echo bar > $(out)",
484 }
485 genrule {
486 name: "hash2",
487 srcs: ["*.txt"],
488 out: ["out"],
489 cmd: "echo $(in) > $(out)",
490 }
491 `
492 testcases := []struct {
493 name string
494 expectedHash string
495 }{
496 {
497 name: "hash0",
Colin Cross3d680512020-11-13 16:23:53 -0800498 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
499 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
Bill Peckhamc087be12020-02-13 15:55:10 -0800500 },
501 {
502 name: "hash1",
Colin Cross3d680512020-11-13 16:23:53 -0800503 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
504 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800505 },
506 {
507 name: "hash2",
Colin Cross3d680512020-11-13 16:23:53 -0800508 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
509 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800510 },
511 }
512
Paul Duffin89648f92021-03-20 00:36:55 +0000513 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Bill Peckhamc087be12020-02-13 15:55:10 -0800514
515 for _, test := range testcases {
516 t.Run(test.name, func(t *testing.T) {
Paul Duffine84b1332021-03-12 11:59:43 +0000517 gen := result.ModuleForTests(test.name, "")
Colin Crossf61d03d2023-11-02 16:56:39 -0700518 manifest := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
Colin Crosse16ce362020-11-12 08:29:30 -0800519 hash := manifest.Commands[0].GetInputHash()
Bill Peckhamc087be12020-02-13 15:55:10 -0800520
Paul Duffine84b1332021-03-12 11:59:43 +0000521 android.AssertStringEquals(t, "hash", test.expectedHash, hash)
Bill Peckhamc087be12020-02-13 15:55:10 -0800522 })
523 }
524}
525
Colin Cross1a527682019-09-23 15:55:30 -0700526func TestGenSrcs(t *testing.T) {
527 testcases := []struct {
528 name string
529 prop string
530
531 allowMissingDependencies bool
532
Liz Kammer796921d2023-07-11 08:21:41 -0400533 err string
534 cmds []string
535 deps []string
536 files []string
537 shards int
538 inputs []string
Colin Cross1a527682019-09-23 15:55:30 -0700539 }{
540 {
541 name: "gensrcs",
542 prop: `
543 tools: ["tool"],
544 srcs: ["in1.txt", "in2.txt"],
545 cmd: "$(location) $(in) > $(out)",
546 `,
547 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800548 "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 -0700549 },
Paul Duffine66946b2021-03-16 12:38:33 +0000550 deps: []string{
551 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
552 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
553 },
554 files: []string{
555 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
556 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
557 },
Colin Cross1a527682019-09-23 15:55:30 -0700558 },
559 {
560 name: "shards",
561 prop: `
562 tools: ["tool"],
563 srcs: ["in1.txt", "in2.txt", "in3.txt"],
564 cmd: "$(location) $(in) > $(out)",
565 shard_size: 2,
566 `,
567 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800568 "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'",
569 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700570 },
Paul Duffine66946b2021-03-16 12:38:33 +0000571 deps: []string{
572 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
573 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
574 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
575 },
576 files: []string{
577 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
578 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
579 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
580 },
Colin Cross1a527682019-09-23 15:55:30 -0700581 },
Liz Kammer81fec182023-06-09 13:33:45 -0400582 {
583 name: "data",
584 prop: `
585 tools: ["tool"],
586 srcs: ["in1.txt", "in2.txt", "in3.txt"],
587 cmd: "$(location) $(in) --extra_input=$(location baz.txt) > $(out)",
588 data: ["baz.txt"],
589 shard_size: 2,
590 `,
591 cmds: []string{
592 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
593 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
594 },
595 deps: []string{
596 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
597 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
598 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
599 },
600 files: []string{
601 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
602 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
603 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
604 },
Liz Kammer796921d2023-07-11 08:21:41 -0400605 shards: 2,
606 inputs: []string{
607 "baz.txt",
608 },
Liz Kammer81fec182023-06-09 13:33:45 -0400609 },
Colin Cross1a527682019-09-23 15:55:30 -0700610 }
611
Liz Kammer796921d2023-07-11 08:21:41 -0400612 checkInputs := func(t *testing.T, rule android.TestingBuildParams, inputs []string) {
613 t.Helper()
614 if len(inputs) == 0 {
615 return
616 }
617 inputBaseNames := map[string]bool{}
618 for _, f := range rule.Implicits {
619 inputBaseNames[f.Base()] = true
620 }
621 for _, f := range inputs {
622 if _, ok := inputBaseNames[f]; !ok {
623 t.Errorf("Expected to find input file %q for %q, but did not", f, rule.Description)
624 }
625 }
626 }
627
Colin Cross1a527682019-09-23 15:55:30 -0700628 for _, test := range testcases {
629 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700630 bp := "gensrcs {\n"
631 bp += `name: "gen",` + "\n"
632 bp += `output_extension: "h",` + "\n"
633 bp += test.prop
634 bp += "}\n"
635
Paul Duffin672cb9f2021-03-03 02:30:37 +0000636 var expectedErrors []string
637 if test.err != "" {
638 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700639 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000640
Paul Duffin89648f92021-03-20 00:36:55 +0000641 result := prepareForGenRuleTest.
Paul Duffin672cb9f2021-03-03 02:30:37 +0000642 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
643 RunTestWithBp(t, testGenruleBp()+bp)
644
Liz Kammer796921d2023-07-11 08:21:41 -0400645 mod := result.ModuleForTests("gen", "")
Paul Duffin672cb9f2021-03-03 02:30:37 +0000646 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700647 return
648 }
649
Liz Kammer796921d2023-07-11 08:21:41 -0400650 if test.shards > 0 {
651 for i := 0; i < test.shards; i++ {
652 r := mod.Rule("generator" + strconv.Itoa(i))
653 checkInputs(t, r, test.inputs)
654 }
655 } else {
656 r := mod.Rule("generator")
657 checkInputs(t, r, test.inputs)
658 }
659
Paul Duffin672cb9f2021-03-03 02:30:37 +0000660 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000661 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700662
Paul Duffine66946b2021-03-16 12:38:33 +0000663 android.AssertPathsRelativeToTopEquals(t, "deps", test.deps, gen.outputDeps)
Colin Cross1a527682019-09-23 15:55:30 -0700664
Paul Duffine66946b2021-03-16 12:38:33 +0000665 android.AssertPathsRelativeToTopEquals(t, "files", test.files, gen.outputFiles)
Colin Cross1a527682019-09-23 15:55:30 -0700666 })
667 }
Colin Cross2a076922018-10-04 23:28:25 -0700668}
669
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800670func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800671 bp := `
672 genrule_defaults {
673 name: "gen_defaults1",
674 cmd: "cp $(in) $(out)",
675 }
676
677 genrule_defaults {
678 name: "gen_defaults2",
679 srcs: ["in1"],
680 }
681
682 genrule {
683 name: "gen",
684 out: ["out"],
685 defaults: ["gen_defaults1", "gen_defaults2"],
686 }
687 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000688
Paul Duffin89648f92021-03-20 00:36:55 +0000689 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000690
691 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800692
Colin Crosse16ce362020-11-12 08:29:30 -0800693 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000694 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800695
696 expectedSrcs := []string{"in1"}
Inseob Kim2f730622024-07-23 14:03:40 +0900697 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.ResolvedSrcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800698}
699
Colin Crossfa65cee2021-03-22 17:05:59 -0700700func TestGenruleAllowMissingDependencies(t *testing.T) {
701 bp := `
702 output {
703 name: "disabled",
704 enabled: false,
705 }
706
707 genrule {
708 name: "gen",
709 srcs: [
710 ":disabled",
711 ],
712 out: ["out"],
713 cmd: "cat $(in) > $(out)",
714 }
715 `
Paul Duffin79abe572021-03-29 02:16:14 +0100716 result := android.GroupFixturePreparers(
717 prepareForGenRuleTest,
Colin Crossfa65cee2021-03-22 17:05:59 -0700718 android.FixtureModifyConfigAndContext(
719 func(config android.Config, ctx *android.TestContext) {
720 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
721 ctx.SetAllowMissingDependencies(true)
722 })).RunTestWithBp(t, bp)
723
724 gen := result.ModuleForTests("gen", "").Output("out")
725 if gen.Rule != android.ErrorRule {
726 t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
727 }
728}
729
Jooyung Han8c7e3ed2021-06-28 17:35:58 +0900730func TestGenruleOutputFiles(t *testing.T) {
731 bp := `
732 genrule {
733 name: "gen",
734 out: ["foo", "sub/bar"],
735 cmd: "echo foo > $(location foo) && echo bar > $(location sub/bar)",
736 }
737 use_source {
738 name: "gen_foo",
739 srcs: [":gen{foo}"],
740 }
741 use_source {
742 name: "gen_bar",
743 srcs: [":gen{sub/bar}"],
744 }
745 use_source {
746 name: "gen_all",
747 srcs: [":gen"],
748 }
749 `
750
751 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
752 android.AssertPathsRelativeToTopEquals(t,
753 "genrule.tag with output",
754 []string{"out/soong/.intermediates/gen/gen/foo"},
755 result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
756 android.AssertPathsRelativeToTopEquals(t,
757 "genrule.tag with output in subdir",
758 []string{"out/soong/.intermediates/gen/gen/sub/bar"},
759 result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
760 android.AssertPathsRelativeToTopEquals(t,
761 "genrule.tag with all",
762 []string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
763 result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
764}
765
Liz Kammerd38c87c2023-07-17 09:58:50 -0400766func TestGenruleInterface(t *testing.T) {
767 result := android.GroupFixturePreparers(
768 prepareForGenRuleTest,
769 android.FixtureMergeMockFs(android.MockFS{
770 "package-dir/Android.bp": []byte(`
771 genrule {
772 name: "module-name",
773 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
774 srcs: [
775 "src/foo.proto",
776 ],
777 out: ["proto.h", "bar/proto.h"],
778 export_include_dirs: [".", "bar"],
779 }
780 `),
781 }),
782 ).RunTest(t)
783
784 exportedIncludeDirs := []string{
785 "out/soong/.intermediates/package-dir/module-name/gen/package-dir",
786 "out/soong/.intermediates/package-dir/module-name/gen",
787 "out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
788 "out/soong/.intermediates/package-dir/module-name/gen/bar",
789 }
790 gen := result.Module("module-name", "").(*Module)
791
792 android.AssertPathsRelativeToTopEquals(
793 t,
794 "include path",
795 exportedIncludeDirs,
796 gen.GeneratedHeaderDirs(),
797 )
798 android.AssertPathsRelativeToTopEquals(
799 t,
800 "files",
801 []string{
802 "out/soong/.intermediates/package-dir/module-name/gen/proto.h",
803 "out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
804 },
805 gen.GeneratedSourceFiles(),
806 )
807}
808
Vinh Tran370e08c2022-09-23 18:09:01 -0400809func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
810 result := android.GroupFixturePreparers(
811 prepareForGenRuleTest,
812 android.FixtureMergeMockFs(android.MockFS{
813 "external-protos/path/Android.bp": []byte(`
814 filegroup {
815 name: "external-protos",
816 srcs: ["baz/baz.proto", "bar.proto"],
817 }
818 `),
819 "package-dir/Android.bp": []byte(`
820 gensrcs {
821 name: "module-name",
822 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
823 srcs: [
824 "src/foo.proto",
825 ":external-protos",
826 ],
827 output_extension: "proto.h",
828 }
829 `),
830 }),
831 ).RunTest(t)
832
833 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
834 gen := result.Module("module-name", "").(*Module)
835
836 android.AssertPathsRelativeToTopEquals(
837 t,
838 "include path",
839 []string{exportedIncludeDir},
840 gen.exportedIncludeDirs,
841 )
842 android.AssertPathsRelativeToTopEquals(
843 t,
844 "files",
845 []string{
846 exportedIncludeDir + "/package-dir/src/foo.proto.h",
847 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
848 exportedIncludeDir + "/external-protos/path/bar.proto.h",
849 },
850 gen.outputFiles,
851 )
852}
853
854func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
855 bp := `
856 gensrcs {
857 name: "module-name",
858 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
859 srcs: [
860 ":external-protos",
861 ],
862 output_extension: "proto.h",
863 }
864 `
865 result := android.GroupFixturePreparers(
866 prepareForGenRuleTest,
867 android.FixtureMergeMockFs(android.MockFS{
868 "external-protos/path/Android.bp": []byte(`
869 filegroup {
870 name: "external-protos",
871 srcs: ["foo/foo.proto", "bar.proto"],
872 }
873 `),
874 }),
875 ).RunTestWithBp(t, bp)
876
877 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
878 gen := result.Module("module-name", "").(*Module)
879
880 android.AssertPathsRelativeToTopEquals(
881 t,
882 "include path",
883 []string{exportedIncludeDir},
884 gen.exportedIncludeDirs,
885 )
886 android.AssertPathsRelativeToTopEquals(
887 t,
888 "files",
889 []string{
890 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
891 exportedIncludeDir + "/external-protos/path/bar.proto.h",
892 },
893 gen.outputFiles,
894 )
895}
896
yangbill6d032dd2024-04-18 03:05:49 +0000897func TestGenSrcsWithTrimExtAndOutpuExtension(t *testing.T) {
898 result := android.GroupFixturePreparers(
899 prepareForGenRuleTest,
900 android.FixtureMergeMockFs(android.MockFS{
901 "external-protos/path/Android.bp": []byte(`
902 filegroup {
903 name: "external-protos",
904 srcs: [
905 "baz.a.b.c.proto/baz.a.b.c.proto",
906 "bar.a.b.c.proto",
907 "qux.ext.a.b.c.proto",
908 ],
909 }
910 `),
911 "package-dir/Android.bp": []byte(`
912 gensrcs {
913 name: "module-name",
914 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
915 srcs: [
916 "src/foo.a.b.c.proto",
917 ":external-protos",
918 ],
919
920 trim_extension: ".a.b.c.proto",
921 output_extension: "proto.h",
922 }
923 `),
924 }),
925 ).RunTest(t)
926
927 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
928 gen := result.Module("module-name", "").(*Module)
929
930 android.AssertPathsRelativeToTopEquals(
931 t,
932 "include path",
933 []string{exportedIncludeDir},
934 gen.exportedIncludeDirs,
935 )
936 android.AssertPathsRelativeToTopEquals(
937 t,
938 "files",
939 []string{
940 exportedIncludeDir + "/package-dir/src/foo.proto.h",
941 exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz.proto.h",
942 exportedIncludeDir + "/external-protos/path/bar.proto.h",
943 exportedIncludeDir + "/external-protos/path/qux.ext.proto.h",
944 },
945 gen.outputFiles,
946 )
947}
948
949func TestGenSrcsWithTrimExtButNoOutpuExtension(t *testing.T) {
950 result := android.GroupFixturePreparers(
951 prepareForGenRuleTest,
952 android.FixtureMergeMockFs(android.MockFS{
953 "external-protos/path/Android.bp": []byte(`
954 filegroup {
955 name: "external-protos",
956 srcs: [
957 "baz.a.b.c.proto/baz.a.b.c.proto",
958 "bar.a.b.c.proto",
959 "qux.ext.a.b.c.proto",
960 ],
961 }
962 `),
963 "package-dir/Android.bp": []byte(`
964 gensrcs {
965 name: "module-name",
966 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
967 srcs: [
968 "src/foo.a.b.c.proto",
969 ":external-protos",
970 ],
971
972 trim_extension: ".a.b.c.proto",
973 }
974 `),
975 }),
976 ).RunTest(t)
977
978 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
979 gen := result.Module("module-name", "").(*Module)
980
981 android.AssertPathsRelativeToTopEquals(
982 t,
983 "include path",
984 []string{exportedIncludeDir},
985 gen.exportedIncludeDirs,
986 )
987 android.AssertPathsRelativeToTopEquals(
988 t,
989 "files",
990 []string{
991 exportedIncludeDir + "/package-dir/src/foo",
992 exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz",
993 exportedIncludeDir + "/external-protos/path/bar",
994 exportedIncludeDir + "/external-protos/path/qux.ext",
995 },
996 gen.outputFiles,
997 )
998}
999
1000func TestGenSrcsWithOutpuExtension(t *testing.T) {
1001 result := android.GroupFixturePreparers(
1002 prepareForGenRuleTest,
1003 android.FixtureMergeMockFs(android.MockFS{
1004 "external-protos/path/Android.bp": []byte(`
1005 filegroup {
1006 name: "external-protos",
1007 srcs: ["baz/baz.a.b.c.proto", "bar.a.b.c.proto"],
1008 }
1009 `),
1010 "package-dir/Android.bp": []byte(`
1011 gensrcs {
1012 name: "module-name",
1013 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
1014 srcs: [
1015 "src/foo.a.b.c.proto",
1016 ":external-protos",
1017 ],
1018
1019 output_extension: "proto.h",
1020 }
1021 `),
1022 }),
1023 ).RunTest(t)
1024
1025 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
1026 gen := result.Module("module-name", "").(*Module)
1027
1028 android.AssertPathsRelativeToTopEquals(
1029 t,
1030 "include path",
1031 []string{exportedIncludeDir},
1032 gen.exportedIncludeDirs,
1033 )
1034 android.AssertPathsRelativeToTopEquals(
1035 t,
1036 "files",
1037 []string{
1038 exportedIncludeDir + "/package-dir/src/foo.a.b.c.proto.h",
1039 exportedIncludeDir + "/external-protos/path/baz/baz.a.b.c.proto.h",
1040 exportedIncludeDir + "/external-protos/path/bar.a.b.c.proto.h",
1041 },
1042 gen.outputFiles,
1043 )
1044}
1045
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001046func TestPrebuiltTool(t *testing.T) {
1047 testcases := []struct {
1048 name string
1049 bp string
1050 expectedToolName string
1051 }{
1052 {
1053 name: "source only",
1054 bp: `
1055 tool { name: "tool" }
1056 `,
1057 expectedToolName: "bin/tool",
1058 },
1059 {
1060 name: "prebuilt only",
1061 bp: `
1062 prebuilt_tool { name: "tool" }
1063 `,
1064 expectedToolName: "prebuilt_bin/tool",
1065 },
1066 {
1067 name: "source preferred",
1068 bp: `
1069 tool { name: "tool" }
1070 prebuilt_tool { name: "tool" }
1071 `,
1072 expectedToolName: "bin/tool",
1073 },
1074 {
1075 name: "prebuilt preferred",
1076 bp: `
1077 tool { name: "tool" }
1078 prebuilt_tool { name: "tool", prefer: true }
1079 `,
1080 expectedToolName: "prebuilt_bin/prebuilt_tool",
1081 },
1082 {
1083 name: "source disabled",
1084 bp: `
1085 tool { name: "tool", enabled: false }
1086 prebuilt_tool { name: "tool" }
1087 `,
1088 expectedToolName: "prebuilt_bin/prebuilt_tool",
1089 },
1090 }
1091
1092 for _, test := range testcases {
1093 t.Run(test.name, func(t *testing.T) {
1094 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
1095 genrule {
1096 name: "gen",
1097 tools: ["tool"],
1098 out: ["foo"],
1099 cmd: "$(location tool)",
1100 }
1101 `)
1102 gen := result.Module("gen", "").(*Module)
1103 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
1104 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
1105 })
1106 }
1107}
1108
Jihoon Kangc170af42022-08-20 05:26:38 +00001109func TestGenruleWithGlobPaths(t *testing.T) {
1110 testcases := []struct {
1111 name string
1112 bp string
1113 additionalFiles android.MockFS
1114 expectedCmd string
1115 }{
1116 {
1117 name: "single file in directory with $ sign",
1118 bp: `
1119 genrule {
1120 name: "gen",
1121 srcs: ["inn*.txt"],
1122 out: ["out.txt"],
1123 cmd: "cp $(in) $(out)",
1124 }
1125 `,
1126 additionalFiles: android.MockFS{"inn$1.txt": nil},
1127 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1128 },
1129 {
1130 name: "multiple file in directory with $ sign",
1131 bp: `
1132 genrule {
1133 name: "gen",
1134 srcs: ["inn*.txt"],
1135 out: ["."],
1136 cmd: "cp $(in) $(out)",
1137 }
1138 `,
1139 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
1140 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
1141 },
1142 {
1143 name: "file in directory with other shell unsafe character",
1144 bp: `
1145 genrule {
1146 name: "gen",
1147 srcs: ["inn*.txt"],
1148 out: ["out.txt"],
1149 cmd: "cp $(in) $(out)",
1150 }
1151 `,
1152 additionalFiles: android.MockFS{"inn@1.txt": nil},
1153 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1154 },
1155 {
1156 name: "glob location param with filepath containing $",
1157 bp: `
1158 genrule {
1159 name: "gen",
1160 srcs: ["**/inn*"],
1161 out: ["."],
1162 cmd: "cp $(in) $(location **/inn*)",
1163 }
1164 `,
1165 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1166 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1167 },
1168 {
1169 name: "glob locations param with filepath containing $",
1170 bp: `
1171 genrule {
1172 name: "gen",
1173 tool_files: ["**/inn*"],
1174 out: ["out.txt"],
1175 cmd: "cp $(locations **/inn*) $(out)",
1176 }
1177 `,
1178 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1179 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1180 },
1181 }
1182
1183 for _, test := range testcases {
1184 t.Run(test.name, func(t *testing.T) {
1185 result := android.GroupFixturePreparers(
1186 prepareForGenRuleTest,
1187 android.FixtureMergeMockFs(test.additionalFiles),
1188 ).RunTestWithBp(t, test.bp)
1189 gen := result.Module("gen", "").(*Module)
1190 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1191 })
1192 }
1193}
1194
Colin Cross2a076922018-10-04 23:28:25 -07001195type testTool struct {
1196 android.ModuleBase
1197 outputFile android.Path
1198}
1199
1200func toolFactory() android.Module {
1201 module := &testTool{}
1202 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1203 return module
1204}
1205
Colin Cross2a076922018-10-04 23:28:25 -07001206func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001207 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001208}
1209
1210func (t *testTool) HostToolPath() android.OptionalPath {
1211 return android.OptionalPathForPath(t.outputFile)
1212}
1213
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001214type prebuiltTestTool struct {
1215 android.ModuleBase
1216 prebuilt android.Prebuilt
1217 testTool
1218}
1219
1220func (p *prebuiltTestTool) Name() string {
1221 return p.prebuilt.Name(p.ModuleBase.Name())
1222}
1223
1224func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1225 return &p.prebuilt
1226}
1227
1228func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1229 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1230}
1231
1232func prebuiltToolFactory() android.Module {
1233 module := &prebuiltTestTool{}
1234 android.InitPrebuiltModuleWithoutSrcs(module)
1235 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1236 return module
1237}
1238
Colin Crossfe17f6f2019-03-28 19:30:56 -07001239var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001240var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001241
1242type testOutputProducer struct {
1243 android.ModuleBase
1244 outputFile android.Path
1245}
1246
1247func outputProducerFactory() android.Module {
1248 module := &testOutputProducer{}
1249 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1250 return module
1251}
1252
1253func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1254 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1255}
1256
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001257type useSource struct {
1258 android.ModuleBase
1259 props struct {
1260 Srcs []string `android:"path"`
1261 }
1262 srcs android.Paths
1263}
1264
1265func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1266 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1267}
1268
1269func useSourceFactory() android.Module {
1270 module := &useSource{}
1271 module.AddProperties(&module.props)
1272 android.InitAndroidModule(module)
1273 return module
1274}