blob: 387a0f94bcf24a7f7e772aada16d55092f8be83f [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"
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
Colin Cross2a076922018-10-04 23:28:25 -070028func TestMain(m *testing.M) {
Paul Duffine66946b2021-03-16 12:38:33 +000029 os.Exit(m.Run())
Colin Cross2a076922018-10-04 23:28:25 -070030}
31
Paul Duffin89648f92021-03-20 00:36:55 +000032var prepareForGenRuleTest = android.GroupFixturePreparers(
Paul Duffin672cb9f2021-03-03 02:30:37 +000033 android.PrepareForTestWithArchMutator,
34 android.PrepareForTestWithDefaults,
Paul Duffin672cb9f2021-03-03 02:30:37 +000035 android.PrepareForTestWithFilegroup,
36 PrepareForTestWithGenRuleBuildComponents,
37 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000038 android.RegisterPrebuiltMutators(ctx)
Paul Duffin672cb9f2021-03-03 02:30:37 +000039 ctx.RegisterModuleType("tool", toolFactory)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000040 ctx.RegisterModuleType("prebuilt_tool", prebuiltToolFactory)
Colin Crossfa65cee2021-03-22 17:05:59 -070041 ctx.RegisterModuleType("output", outputProducerFactory)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +090042 ctx.RegisterModuleType("use_source", useSourceFactory)
Paul Duffin672cb9f2021-03-03 02:30:37 +000043 }),
44 android.FixtureMergeMockFs(android.MockFS{
45 "tool": nil,
46 "tool_file1": nil,
47 "tool_file2": nil,
48 "in1": nil,
49 "in2": nil,
50 "in1.txt": nil,
51 "in2.txt": nil,
52 "in3.txt": nil,
53 }),
54)
Martin Stjernholm710ec3a2020-01-16 15:12:04 +000055
Paul Duffin672cb9f2021-03-03 02:30:37 +000056func testGenruleBp() string {
57 return `
Colin Cross2a076922018-10-04 23:28:25 -070058 tool {
59 name: "tool",
60 }
61
62 filegroup {
63 name: "tool_files",
64 srcs: [
65 "tool_file1",
66 "tool_file2",
67 ],
68 }
69
70 filegroup {
71 name: "1tool_file",
72 srcs: [
73 "tool_file1",
74 ],
75 }
76
77 filegroup {
78 name: "ins",
79 srcs: [
80 "in1",
81 "in2",
82 ],
83 }
84
85 filegroup {
86 name: "1in",
87 srcs: [
88 "in1",
89 ],
90 }
91
92 filegroup {
93 name: "empty",
94 }
95 `
Colin Cross2a076922018-10-04 23:28:25 -070096}
97
98func TestGenruleCmd(t *testing.T) {
99 testcases := []struct {
Yu Liu6a7940c2023-05-09 17:12:22 -0700100 name string
101 moduleName string
102 prop string
Colin Cross2a076922018-10-04 23:28:25 -0700103
Colin Crossba71a3f2019-03-18 12:12:48 -0700104 allowMissingDependencies bool
105
Colin Cross2a076922018-10-04 23:28:25 -0700106 err string
107 expect string
108 }{
109 {
110 name: "empty location tool",
111 prop: `
112 tools: ["tool"],
113 out: ["out"],
114 cmd: "$(location) > $(out)",
115 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800116 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700117 },
118 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700119 name: "empty location tool2",
120 prop: `
121 tools: [":tool"],
122 out: ["out"],
123 cmd: "$(location) > $(out)",
124 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800125 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700126 },
127 {
Colin Cross2a076922018-10-04 23:28:25 -0700128 name: "empty location tool file",
129 prop: `
130 tool_files: ["tool_file1"],
131 out: ["out"],
132 cmd: "$(location) > $(out)",
133 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800134 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700135 },
136 {
137 name: "empty location tool file fg",
138 prop: `
139 tool_files: [":1tool_file"],
140 out: ["out"],
141 cmd: "$(location) > $(out)",
142 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800143 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700144 },
145 {
146 name: "empty location tool and tool file",
147 prop: `
148 tools: ["tool"],
149 tool_files: ["tool_file1"],
150 out: ["out"],
151 cmd: "$(location) > $(out)",
152 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800153 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700154 },
155 {
156 name: "tool",
157 prop: `
158 tools: ["tool"],
159 out: ["out"],
160 cmd: "$(location tool) > $(out)",
161 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800162 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700163 },
164 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700165 name: "tool2",
166 prop: `
167 tools: [":tool"],
168 out: ["out"],
169 cmd: "$(location :tool) > $(out)",
170 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800171 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700172 },
173 {
Colin Cross2a076922018-10-04 23:28:25 -0700174 name: "tool file",
175 prop: `
176 tool_files: ["tool_file1"],
177 out: ["out"],
178 cmd: "$(location tool_file1) > $(out)",
179 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800180 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700181 },
182 {
183 name: "tool file fg",
184 prop: `
185 tool_files: [":1tool_file"],
186 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700187 cmd: "$(location :1tool_file) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700188 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800189 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700190 },
191 {
192 name: "tool files",
193 prop: `
194 tool_files: [":tool_files"],
195 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700196 cmd: "$(locations :tool_files) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700197 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800198 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 -0700199 },
200 {
201 name: "in1",
202 prop: `
203 srcs: ["in1"],
204 out: ["out"],
205 cmd: "cat $(in) > $(out)",
206 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800207 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700208 },
209 {
210 name: "in1 fg",
211 prop: `
212 srcs: [":1in"],
213 out: ["out"],
214 cmd: "cat $(in) > $(out)",
215 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800216 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700217 },
218 {
219 name: "ins",
220 prop: `
221 srcs: ["in1", "in2"],
222 out: ["out"],
223 cmd: "cat $(in) > $(out)",
224 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800225 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700226 },
227 {
228 name: "ins fg",
229 prop: `
230 srcs: [":ins"],
231 out: ["out"],
232 cmd: "cat $(in) > $(out)",
233 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800234 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700235 },
236 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700237 name: "location in1",
238 prop: `
239 srcs: ["in1"],
240 out: ["out"],
241 cmd: "cat $(location in1) > $(out)",
242 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800243 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700244 },
245 {
246 name: "location in1 fg",
247 prop: `
248 srcs: [":1in"],
249 out: ["out"],
250 cmd: "cat $(location :1in) > $(out)",
251 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800252 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700253 },
254 {
255 name: "location ins",
256 prop: `
257 srcs: ["in1", "in2"],
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 ins fg",
265 prop: `
266 srcs: [":ins"],
267 out: ["out"],
268 cmd: "cat $(locations :ins) > $(out)",
269 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800270 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700271 },
272 {
Colin Cross2a076922018-10-04 23:28:25 -0700273 name: "outs",
274 prop: `
275 out: ["out", "out2"],
276 cmd: "echo foo > $(out)",
277 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800278 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross2a076922018-10-04 23:28:25 -0700279 },
280 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700281 name: "location out",
282 prop: `
283 out: ["out", "out2"],
284 cmd: "echo foo > $(location out2)",
285 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800286 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross08f15ab2018-10-04 23:29:14 -0700287 },
288 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700289 name: "depfile",
290 moduleName: "depfile_allowed_for_test",
Colin Cross2a076922018-10-04 23:28:25 -0700291 prop: `
292 out: ["out"],
293 depfile: true,
294 cmd: "echo foo > $(out) && touch $(depfile)",
295 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800296 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out && touch __SBOX_DEPFILE__",
Colin Cross2a076922018-10-04 23:28:25 -0700297 },
298 {
299 name: "gendir",
300 prop: `
301 out: ["out"],
302 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
303 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800304 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 -0700305 },
Colin Cross70c47412021-03-12 17:48:14 -0800306 {
307 name: "$",
308 prop: `
309 out: ["out"],
310 cmd: "echo $$ > $(out)",
311 `,
312 expect: "echo $ > __SBOX_SANDBOX_DIR__/out/out",
313 },
Colin Cross2a076922018-10-04 23:28:25 -0700314
315 {
316 name: "error empty location",
317 prop: `
318 out: ["out"],
319 cmd: "$(location) > $(out)",
320 `,
321 err: "at least one `tools` or `tool_files` is required if $(location) is used",
322 },
323 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700324 name: "error empty location no files",
325 prop: `
326 tool_files: [":empty"],
327 out: ["out"],
328 cmd: "$(location) > $(out)",
329 `,
330 err: `default label ":empty" has no files`,
331 },
332 {
333 name: "error empty location multiple files",
334 prop: `
335 tool_files: [":tool_files"],
336 out: ["out"],
337 cmd: "$(location) > $(out)",
338 `,
339 err: `default label ":tool_files" has multiple files`,
340 },
341 {
Colin Cross2a076922018-10-04 23:28:25 -0700342 name: "error location",
343 prop: `
344 out: ["out"],
345 cmd: "echo foo > $(location missing)",
346 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000347 err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
Colin Cross2a076922018-10-04 23:28:25 -0700348 },
349 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700350 name: "error locations",
351 prop: `
352 out: ["out"],
353 cmd: "echo foo > $(locations missing)",
354 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000355 err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
Colin Cross08f15ab2018-10-04 23:29:14 -0700356 },
357 {
358 name: "error location no files",
359 prop: `
360 out: ["out"],
361 srcs: [":empty"],
362 cmd: "echo $(location :empty) > $(out)",
363 `,
364 err: `label ":empty" has no files`,
365 },
366 {
367 name: "error locations no files",
368 prop: `
369 out: ["out"],
370 srcs: [":empty"],
371 cmd: "echo $(locations :empty) > $(out)",
372 `,
373 err: `label ":empty" has no files`,
374 },
375 {
376 name: "error location multiple files",
377 prop: `
378 out: ["out"],
379 srcs: [":ins"],
380 cmd: "echo $(location :ins) > $(out)",
381 `,
382 err: `label ":ins" has multiple files`,
383 },
384 {
Colin Cross2a076922018-10-04 23:28:25 -0700385 name: "error variable",
386 prop: `
387 out: ["out"],
388 srcs: ["in1"],
389 cmd: "echo $(foo) > $(out)",
390 `,
391 err: `unknown variable '$(foo)'`,
392 },
393 {
394 name: "error depfile",
395 prop: `
396 out: ["out"],
397 cmd: "echo foo > $(out) && touch $(depfile)",
398 `,
399 err: "$(depfile) used without depfile property",
400 },
401 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700402 name: "error no depfile",
403 moduleName: "depfile_allowed_for_test",
Colin Cross2a076922018-10-04 23:28:25 -0700404 prop: `
405 out: ["out"],
406 depfile: true,
407 cmd: "echo foo > $(out)",
408 `,
409 err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
410 },
411 {
412 name: "error no out",
413 prop: `
414 cmd: "echo foo > $(out)",
415 `,
416 err: "must have at least one output file",
417 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700418 {
419 name: "srcs allow missing dependencies",
420 prop: `
421 srcs: [":missing"],
422 out: ["out"],
423 cmd: "cat $(location :missing) > $(out)",
424 `,
425
426 allowMissingDependencies: true,
427
Jihoon Kangc170af42022-08-20 05:26:38 +0000428 expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700429 },
430 {
431 name: "tool allow missing dependencies",
432 prop: `
433 tools: [":missing"],
434 out: ["out"],
435 cmd: "$(location :missing) > $(out)",
436 `,
437
438 allowMissingDependencies: true,
439
Jihoon Kangc170af42022-08-20 05:26:38 +0000440 expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700441 },
Colin Cross2a076922018-10-04 23:28:25 -0700442 }
443
444 for _, test := range testcases {
445 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700446 moduleName := "gen"
447 if test.moduleName != "" {
448 moduleName = test.moduleName
449 }
450 bp := fmt.Sprintf(`
451 genrule {
452 name: "%s",
453 %s
454 }`, moduleName, test.prop)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000455 var expectedErrors []string
456 if test.err != "" {
457 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700458 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000459
Paul Duffin89648f92021-03-20 00:36:55 +0000460 result := android.GroupFixturePreparers(
461 prepareForGenRuleTest,
Paul Duffin672cb9f2021-03-03 02:30:37 +0000462 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
463 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
464 }),
Yu Liu6a7940c2023-05-09 17:12:22 -0700465 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
466 variables.GenruleSandboxing = proptools.BoolPtr(true)
467 }),
Paul Duffin672cb9f2021-03-03 02:30:37 +0000468 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
Yu Liu6a7940c2023-05-09 17:12:22 -0700479 gen := result.Module(moduleName, "").(*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 Duffin89648f92021-03-20 00:36:55 +0000540 result := prepareForGenRuleTest.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 },
Paul Duffine66946b2021-03-16 12:38:33 +0000575 deps: []string{
576 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
577 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
578 },
579 files: []string{
580 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
581 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
582 },
Colin Cross1a527682019-09-23 15:55:30 -0700583 },
584 {
585 name: "shards",
586 prop: `
587 tools: ["tool"],
588 srcs: ["in1.txt", "in2.txt", "in3.txt"],
589 cmd: "$(location) $(in) > $(out)",
590 shard_size: 2,
591 `,
592 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800593 "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'",
594 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700595 },
Paul Duffine66946b2021-03-16 12:38:33 +0000596 deps: []string{
597 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
598 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
599 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
600 },
601 files: []string{
602 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
603 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
604 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
605 },
Colin Cross1a527682019-09-23 15:55:30 -0700606 },
Liz Kammer81fec182023-06-09 13:33:45 -0400607 {
608 name: "data",
609 prop: `
610 tools: ["tool"],
611 srcs: ["in1.txt", "in2.txt", "in3.txt"],
612 cmd: "$(location) $(in) --extra_input=$(location baz.txt) > $(out)",
613 data: ["baz.txt"],
614 shard_size: 2,
615 `,
616 cmds: []string{
617 "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'",
618 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
619 },
620 deps: []string{
621 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
622 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
623 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
624 },
625 files: []string{
626 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
627 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
628 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
629 },
630 },
Colin Cross1a527682019-09-23 15:55:30 -0700631 }
632
633 for _, test := range testcases {
634 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700635 bp := "gensrcs {\n"
636 bp += `name: "gen",` + "\n"
637 bp += `output_extension: "h",` + "\n"
638 bp += test.prop
639 bp += "}\n"
640
Paul Duffin672cb9f2021-03-03 02:30:37 +0000641 var expectedErrors []string
642 if test.err != "" {
643 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700644 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000645
Paul Duffin89648f92021-03-20 00:36:55 +0000646 result := prepareForGenRuleTest.
Paul Duffin672cb9f2021-03-03 02:30:37 +0000647 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
648 RunTestWithBp(t, testGenruleBp()+bp)
649
650 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700651 return
652 }
653
Paul Duffin672cb9f2021-03-03 02:30:37 +0000654 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000655 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700656
Paul Duffine66946b2021-03-16 12:38:33 +0000657 android.AssertPathsRelativeToTopEquals(t, "deps", test.deps, gen.outputDeps)
Colin Cross1a527682019-09-23 15:55:30 -0700658
Paul Duffine66946b2021-03-16 12:38:33 +0000659 android.AssertPathsRelativeToTopEquals(t, "files", test.files, gen.outputFiles)
Colin Cross1a527682019-09-23 15:55:30 -0700660 })
661 }
Colin Cross2a076922018-10-04 23:28:25 -0700662}
663
Yu Liu6a7940c2023-05-09 17:12:22 -0700664func TestGenruleAllowlistingDepfile(t *testing.T) {
Vinh Tran140d5882022-06-10 14:23:27 -0400665 tests := []struct {
Yu Liu6a7940c2023-05-09 17:12:22 -0700666 name string
667 prop string
668 err string
669 moduleName string
Vinh Tran140d5882022-06-10 14:23:27 -0400670 }{
671 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700672 name: `error when module is not allowlisted`,
Vinh Tran140d5882022-06-10 14:23:27 -0400673 prop: `
674 depfile: true,
675 cmd: "cat $(in) > $(out) && cat $(depfile)",
676 `,
Yu Liu6a7940c2023-05-09 17:12:22 -0700677 err: "depfile: Deprecated to ensure the module type is convertible to Bazel",
Vinh Tran140d5882022-06-10 14:23:27 -0400678 },
679 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700680 name: `no error when module is allowlisted`,
Vinh Tran140d5882022-06-10 14:23:27 -0400681 prop: `
682 depfile: true,
683 cmd: "cat $(in) > $(out) && cat $(depfile)",
684 `,
Yu Liu6a7940c2023-05-09 17:12:22 -0700685 moduleName: `depfile_allowed_for_test`,
Vinh Tran140d5882022-06-10 14:23:27 -0400686 },
687 }
688 for _, test := range tests {
689 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700690 moduleName := "foo"
691 if test.moduleName != "" {
692 moduleName = test.moduleName
693 }
Vinh Tran140d5882022-06-10 14:23:27 -0400694 bp := fmt.Sprintf(`
695 gensrcs {
Yu Liu6a7940c2023-05-09 17:12:22 -0700696 name: "%s",
Vinh Tran140d5882022-06-10 14:23:27 -0400697 srcs: ["data.txt"],
698 %s
Yu Liu6a7940c2023-05-09 17:12:22 -0700699 }`, moduleName, test.prop)
Vinh Tran140d5882022-06-10 14:23:27 -0400700
701 var expectedErrors []string
702 if test.err != "" {
703 expectedErrors = append(expectedErrors, test.err)
704 }
705 android.GroupFixturePreparers(
706 prepareForGenRuleTest,
707 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700708 variables.GenruleSandboxing = proptools.BoolPtr(true)
Vinh Tran140d5882022-06-10 14:23:27 -0400709 }),
710 ).
711 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
712 RunTestWithBp(t, bp)
713 })
714
715 }
716}
717
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800718func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800719 bp := `
720 genrule_defaults {
721 name: "gen_defaults1",
722 cmd: "cp $(in) $(out)",
723 }
724
725 genrule_defaults {
726 name: "gen_defaults2",
727 srcs: ["in1"],
728 }
729
730 genrule {
731 name: "gen",
732 out: ["out"],
733 defaults: ["gen_defaults1", "gen_defaults2"],
734 }
735 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000736
Paul Duffin89648f92021-03-20 00:36:55 +0000737 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000738
739 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800740
Colin Crosse16ce362020-11-12 08:29:30 -0800741 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000742 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800743
744 expectedSrcs := []string{"in1"}
Paul Duffine84b1332021-03-12 11:59:43 +0000745 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800746}
747
Colin Crossfa65cee2021-03-22 17:05:59 -0700748func TestGenruleAllowMissingDependencies(t *testing.T) {
749 bp := `
750 output {
751 name: "disabled",
752 enabled: false,
753 }
754
755 genrule {
756 name: "gen",
757 srcs: [
758 ":disabled",
759 ],
760 out: ["out"],
761 cmd: "cat $(in) > $(out)",
762 }
763 `
Paul Duffin79abe572021-03-29 02:16:14 +0100764 result := android.GroupFixturePreparers(
765 prepareForGenRuleTest,
Colin Crossfa65cee2021-03-22 17:05:59 -0700766 android.FixtureModifyConfigAndContext(
767 func(config android.Config, ctx *android.TestContext) {
768 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
769 ctx.SetAllowMissingDependencies(true)
770 })).RunTestWithBp(t, bp)
771
772 gen := result.ModuleForTests("gen", "").Output("out")
773 if gen.Rule != android.ErrorRule {
774 t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
775 }
776}
777
Jooyung Han8c7e3ed2021-06-28 17:35:58 +0900778func TestGenruleOutputFiles(t *testing.T) {
779 bp := `
780 genrule {
781 name: "gen",
782 out: ["foo", "sub/bar"],
783 cmd: "echo foo > $(location foo) && echo bar > $(location sub/bar)",
784 }
785 use_source {
786 name: "gen_foo",
787 srcs: [":gen{foo}"],
788 }
789 use_source {
790 name: "gen_bar",
791 srcs: [":gen{sub/bar}"],
792 }
793 use_source {
794 name: "gen_all",
795 srcs: [":gen"],
796 }
797 `
798
799 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
800 android.AssertPathsRelativeToTopEquals(t,
801 "genrule.tag with output",
802 []string{"out/soong/.intermediates/gen/gen/foo"},
803 result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
804 android.AssertPathsRelativeToTopEquals(t,
805 "genrule.tag with output in subdir",
806 []string{"out/soong/.intermediates/gen/gen/sub/bar"},
807 result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
808 android.AssertPathsRelativeToTopEquals(t,
809 "genrule.tag with all",
810 []string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
811 result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
812}
813
Liz Kammerd38c87c2023-07-17 09:58:50 -0400814func TestGenruleInterface(t *testing.T) {
815 result := android.GroupFixturePreparers(
816 prepareForGenRuleTest,
817 android.FixtureMergeMockFs(android.MockFS{
818 "package-dir/Android.bp": []byte(`
819 genrule {
820 name: "module-name",
821 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
822 srcs: [
823 "src/foo.proto",
824 ],
825 out: ["proto.h", "bar/proto.h"],
826 export_include_dirs: [".", "bar"],
827 }
828 `),
829 }),
830 ).RunTest(t)
831
832 exportedIncludeDirs := []string{
833 "out/soong/.intermediates/package-dir/module-name/gen/package-dir",
834 "out/soong/.intermediates/package-dir/module-name/gen",
835 "out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
836 "out/soong/.intermediates/package-dir/module-name/gen/bar",
837 }
838 gen := result.Module("module-name", "").(*Module)
839
840 android.AssertPathsRelativeToTopEquals(
841 t,
842 "include path",
843 exportedIncludeDirs,
844 gen.GeneratedHeaderDirs(),
845 )
846 android.AssertPathsRelativeToTopEquals(
847 t,
848 "files",
849 []string{
850 "out/soong/.intermediates/package-dir/module-name/gen/proto.h",
851 "out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
852 },
853 gen.GeneratedSourceFiles(),
854 )
855}
856
Vinh Tran370e08c2022-09-23 18:09:01 -0400857func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
858 result := android.GroupFixturePreparers(
859 prepareForGenRuleTest,
860 android.FixtureMergeMockFs(android.MockFS{
861 "external-protos/path/Android.bp": []byte(`
862 filegroup {
863 name: "external-protos",
864 srcs: ["baz/baz.proto", "bar.proto"],
865 }
866 `),
867 "package-dir/Android.bp": []byte(`
868 gensrcs {
869 name: "module-name",
870 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
871 srcs: [
872 "src/foo.proto",
873 ":external-protos",
874 ],
875 output_extension: "proto.h",
876 }
877 `),
878 }),
879 ).RunTest(t)
880
881 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
882 gen := result.Module("module-name", "").(*Module)
883
884 android.AssertPathsRelativeToTopEquals(
885 t,
886 "include path",
887 []string{exportedIncludeDir},
888 gen.exportedIncludeDirs,
889 )
890 android.AssertPathsRelativeToTopEquals(
891 t,
892 "files",
893 []string{
894 exportedIncludeDir + "/package-dir/src/foo.proto.h",
895 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
896 exportedIncludeDir + "/external-protos/path/bar.proto.h",
897 },
898 gen.outputFiles,
899 )
900}
901
902func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
903 bp := `
904 gensrcs {
905 name: "module-name",
906 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
907 srcs: [
908 ":external-protos",
909 ],
910 output_extension: "proto.h",
911 }
912 `
913 result := android.GroupFixturePreparers(
914 prepareForGenRuleTest,
915 android.FixtureMergeMockFs(android.MockFS{
916 "external-protos/path/Android.bp": []byte(`
917 filegroup {
918 name: "external-protos",
919 srcs: ["foo/foo.proto", "bar.proto"],
920 }
921 `),
922 }),
923 ).RunTestWithBp(t, bp)
924
925 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
926 gen := result.Module("module-name", "").(*Module)
927
928 android.AssertPathsRelativeToTopEquals(
929 t,
930 "include path",
931 []string{exportedIncludeDir},
932 gen.exportedIncludeDirs,
933 )
934 android.AssertPathsRelativeToTopEquals(
935 t,
936 "files",
937 []string{
938 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
939 exportedIncludeDir + "/external-protos/path/bar.proto.h",
940 },
941 gen.outputFiles,
942 )
943}
944
Martin Stjernholmdbd814d2022-01-12 23:18:30 +0000945func TestPrebuiltTool(t *testing.T) {
946 testcases := []struct {
947 name string
948 bp string
949 expectedToolName string
950 }{
951 {
952 name: "source only",
953 bp: `
954 tool { name: "tool" }
955 `,
956 expectedToolName: "bin/tool",
957 },
958 {
959 name: "prebuilt only",
960 bp: `
961 prebuilt_tool { name: "tool" }
962 `,
963 expectedToolName: "prebuilt_bin/tool",
964 },
965 {
966 name: "source preferred",
967 bp: `
968 tool { name: "tool" }
969 prebuilt_tool { name: "tool" }
970 `,
971 expectedToolName: "bin/tool",
972 },
973 {
974 name: "prebuilt preferred",
975 bp: `
976 tool { name: "tool" }
977 prebuilt_tool { name: "tool", prefer: true }
978 `,
979 expectedToolName: "prebuilt_bin/prebuilt_tool",
980 },
981 {
982 name: "source disabled",
983 bp: `
984 tool { name: "tool", enabled: false }
985 prebuilt_tool { name: "tool" }
986 `,
987 expectedToolName: "prebuilt_bin/prebuilt_tool",
988 },
989 }
990
991 for _, test := range testcases {
992 t.Run(test.name, func(t *testing.T) {
993 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
994 genrule {
995 name: "gen",
996 tools: ["tool"],
997 out: ["foo"],
998 cmd: "$(location tool)",
999 }
1000 `)
1001 gen := result.Module("gen", "").(*Module)
1002 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
1003 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
1004 })
1005 }
1006}
1007
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001008func TestGenruleWithBazel(t *testing.T) {
1009 bp := `
1010 genrule {
1011 name: "foo",
1012 out: ["one.txt", "two.txt"],
Chris Parsonsaa8be052020-10-14 16:22:37 -04001013 bazel_module: { label: "//foo/bar:bar" },
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001014 }
1015 `
1016
Paul Duffin89648f92021-03-20 00:36:55 +00001017 result := android.GroupFixturePreparers(
1018 prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
1019 config.BazelContext = android.MockBazelContext{
Liz Kammera92e8442021-04-07 20:25:21 -04001020 OutputBaseDir: "outputbase",
1021 LabelToOutputFiles: map[string][]string{
Paul Duffin89648f92021-03-20 00:36:55 +00001022 "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
1023 })).RunTestWithBp(t, testGenruleBp()+bp)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001024
Paul Duffin672cb9f2021-03-03 02:30:37 +00001025 gen := result.Module("foo", "").(*Module)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001026
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -05001027 expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
1028 "outputbase/execroot/__main__/bazeltwo.txt"}
Paul Duffine84b1332021-03-12 11:59:43 +00001029 android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
1030 android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001031}
1032
Jihoon Kangc170af42022-08-20 05:26:38 +00001033func TestGenruleWithGlobPaths(t *testing.T) {
1034 testcases := []struct {
1035 name string
1036 bp string
1037 additionalFiles android.MockFS
1038 expectedCmd string
1039 }{
1040 {
1041 name: "single file in directory with $ sign",
1042 bp: `
1043 genrule {
1044 name: "gen",
1045 srcs: ["inn*.txt"],
1046 out: ["out.txt"],
1047 cmd: "cp $(in) $(out)",
1048 }
1049 `,
1050 additionalFiles: android.MockFS{"inn$1.txt": nil},
1051 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1052 },
1053 {
1054 name: "multiple file in directory with $ sign",
1055 bp: `
1056 genrule {
1057 name: "gen",
1058 srcs: ["inn*.txt"],
1059 out: ["."],
1060 cmd: "cp $(in) $(out)",
1061 }
1062 `,
1063 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
1064 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
1065 },
1066 {
1067 name: "file in directory with other shell unsafe character",
1068 bp: `
1069 genrule {
1070 name: "gen",
1071 srcs: ["inn*.txt"],
1072 out: ["out.txt"],
1073 cmd: "cp $(in) $(out)",
1074 }
1075 `,
1076 additionalFiles: android.MockFS{"inn@1.txt": nil},
1077 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1078 },
1079 {
1080 name: "glob location param with filepath containing $",
1081 bp: `
1082 genrule {
1083 name: "gen",
1084 srcs: ["**/inn*"],
1085 out: ["."],
1086 cmd: "cp $(in) $(location **/inn*)",
1087 }
1088 `,
1089 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1090 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1091 },
1092 {
1093 name: "glob locations param with filepath containing $",
1094 bp: `
1095 genrule {
1096 name: "gen",
1097 tool_files: ["**/inn*"],
1098 out: ["out.txt"],
1099 cmd: "cp $(locations **/inn*) $(out)",
1100 }
1101 `,
1102 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1103 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1104 },
1105 }
1106
1107 for _, test := range testcases {
1108 t.Run(test.name, func(t *testing.T) {
1109 result := android.GroupFixturePreparers(
1110 prepareForGenRuleTest,
1111 android.FixtureMergeMockFs(test.additionalFiles),
1112 ).RunTestWithBp(t, test.bp)
1113 gen := result.Module("gen", "").(*Module)
1114 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1115 })
1116 }
1117}
1118
Colin Cross2a076922018-10-04 23:28:25 -07001119type testTool struct {
1120 android.ModuleBase
1121 outputFile android.Path
1122}
1123
1124func toolFactory() android.Module {
1125 module := &testTool{}
1126 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1127 return module
1128}
1129
Colin Cross2a076922018-10-04 23:28:25 -07001130func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001131 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001132}
1133
1134func (t *testTool) HostToolPath() android.OptionalPath {
1135 return android.OptionalPathForPath(t.outputFile)
1136}
1137
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001138type prebuiltTestTool struct {
1139 android.ModuleBase
1140 prebuilt android.Prebuilt
1141 testTool
1142}
1143
1144func (p *prebuiltTestTool) Name() string {
1145 return p.prebuilt.Name(p.ModuleBase.Name())
1146}
1147
1148func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1149 return &p.prebuilt
1150}
1151
1152func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1153 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1154}
1155
1156func prebuiltToolFactory() android.Module {
1157 module := &prebuiltTestTool{}
1158 android.InitPrebuiltModuleWithoutSrcs(module)
1159 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1160 return module
1161}
1162
Colin Crossfe17f6f2019-03-28 19:30:56 -07001163var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001164var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001165
1166type testOutputProducer struct {
1167 android.ModuleBase
1168 outputFile android.Path
1169}
1170
1171func outputProducerFactory() android.Module {
1172 module := &testOutputProducer{}
1173 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1174 return module
1175}
1176
1177func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1178 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1179}
1180
1181func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) {
1182 return android.Paths{t.outputFile}, nil
1183}
1184
1185var _ android.OutputFileProducer = (*testOutputProducer)(nil)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001186
1187type useSource struct {
1188 android.ModuleBase
1189 props struct {
1190 Srcs []string `android:"path"`
1191 }
1192 srcs android.Paths
1193}
1194
1195func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1196 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1197}
1198
1199func useSourceFactory() android.Module {
1200 module := &useSource{}
1201 module.AddProperties(&module.props)
1202 android.InitAndroidModule(module)
1203 return module
1204}