blob: 6301bbf010f11225f567a3e483d04ff23c25a148 [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 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700290 name: "depfile",
291 moduleName: "depfile_allowed_for_test",
Colin Cross2a076922018-10-04 23:28:25 -0700292 prop: `
293 out: ["out"],
294 depfile: true,
295 cmd: "echo foo > $(out) && touch $(depfile)",
296 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800297 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out && touch __SBOX_DEPFILE__",
Colin Cross2a076922018-10-04 23:28:25 -0700298 },
299 {
300 name: "gendir",
301 prop: `
302 out: ["out"],
303 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
304 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800305 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 -0700306 },
Colin Cross70c47412021-03-12 17:48:14 -0800307 {
308 name: "$",
309 prop: `
310 out: ["out"],
311 cmd: "echo $$ > $(out)",
312 `,
313 expect: "echo $ > __SBOX_SANDBOX_DIR__/out/out",
314 },
Colin Cross2a076922018-10-04 23:28:25 -0700315
316 {
317 name: "error empty location",
318 prop: `
319 out: ["out"],
320 cmd: "$(location) > $(out)",
321 `,
322 err: "at least one `tools` or `tool_files` is required if $(location) is used",
323 },
324 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700325 name: "error empty location no files",
326 prop: `
327 tool_files: [":empty"],
328 out: ["out"],
329 cmd: "$(location) > $(out)",
330 `,
331 err: `default label ":empty" has no files`,
332 },
333 {
334 name: "error empty location multiple files",
335 prop: `
336 tool_files: [":tool_files"],
337 out: ["out"],
338 cmd: "$(location) > $(out)",
339 `,
340 err: `default label ":tool_files" has multiple files`,
341 },
342 {
Colin Cross2a076922018-10-04 23:28:25 -0700343 name: "error location",
344 prop: `
345 out: ["out"],
346 cmd: "echo foo > $(location missing)",
347 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000348 err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
Colin Cross2a076922018-10-04 23:28:25 -0700349 },
350 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700351 name: "error locations",
352 prop: `
353 out: ["out"],
354 cmd: "echo foo > $(locations missing)",
355 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000356 err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
Colin Cross08f15ab2018-10-04 23:29:14 -0700357 },
358 {
359 name: "error location no files",
360 prop: `
361 out: ["out"],
362 srcs: [":empty"],
363 cmd: "echo $(location :empty) > $(out)",
364 `,
365 err: `label ":empty" has no files`,
366 },
367 {
368 name: "error locations no files",
369 prop: `
370 out: ["out"],
371 srcs: [":empty"],
372 cmd: "echo $(locations :empty) > $(out)",
373 `,
374 err: `label ":empty" has no files`,
375 },
376 {
377 name: "error location multiple files",
378 prop: `
379 out: ["out"],
380 srcs: [":ins"],
381 cmd: "echo $(location :ins) > $(out)",
382 `,
383 err: `label ":ins" has multiple files`,
384 },
385 {
Colin Cross2a076922018-10-04 23:28:25 -0700386 name: "error variable",
387 prop: `
388 out: ["out"],
389 srcs: ["in1"],
390 cmd: "echo $(foo) > $(out)",
391 `,
392 err: `unknown variable '$(foo)'`,
393 },
394 {
395 name: "error depfile",
396 prop: `
397 out: ["out"],
398 cmd: "echo foo > $(out) && touch $(depfile)",
399 `,
400 err: "$(depfile) used without depfile property",
401 },
402 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700403 name: "error no depfile",
404 moduleName: "depfile_allowed_for_test",
Colin Cross2a076922018-10-04 23:28:25 -0700405 prop: `
406 out: ["out"],
407 depfile: true,
408 cmd: "echo foo > $(out)",
409 `,
410 err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
411 },
412 {
413 name: "error no out",
414 prop: `
415 cmd: "echo foo > $(out)",
416 `,
417 err: "must have at least one output file",
418 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700419 {
420 name: "srcs allow missing dependencies",
421 prop: `
422 srcs: [":missing"],
423 out: ["out"],
424 cmd: "cat $(location :missing) > $(out)",
425 `,
426
427 allowMissingDependencies: true,
428
Jihoon Kangc170af42022-08-20 05:26:38 +0000429 expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700430 },
431 {
432 name: "tool allow missing dependencies",
433 prop: `
434 tools: [":missing"],
435 out: ["out"],
436 cmd: "$(location :missing) > $(out)",
437 `,
438
439 allowMissingDependencies: true,
440
Jihoon Kangc170af42022-08-20 05:26:38 +0000441 expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700442 },
Colin Cross2a076922018-10-04 23:28:25 -0700443 }
444
445 for _, test := range testcases {
446 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700447 moduleName := "gen"
448 if test.moduleName != "" {
449 moduleName = test.moduleName
450 }
451 bp := fmt.Sprintf(`
452 genrule {
453 name: "%s",
454 %s
455 }`, moduleName, test.prop)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000456 var expectedErrors []string
457 if test.err != "" {
458 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700459 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000460
Paul Duffin89648f92021-03-20 00:36:55 +0000461 result := android.GroupFixturePreparers(
462 prepareForGenRuleTest,
Paul Duffin672cb9f2021-03-03 02:30:37 +0000463 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
464 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
465 }),
Yu Liu6a7940c2023-05-09 17:12:22 -0700466 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
467 variables.GenruleSandboxing = proptools.BoolPtr(true)
468 }),
Paul Duffin672cb9f2021-03-03 02:30:37 +0000469 android.FixtureModifyContext(func(ctx *android.TestContext) {
470 ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
471 }),
472 ).
473 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
474 RunTestWithBp(t, testGenruleBp()+bp)
475
476 if expectedErrors != nil {
Colin Cross2a076922018-10-04 23:28:25 -0700477 return
478 }
479
Yu Liu6a7940c2023-05-09 17:12:22 -0700480 gen := result.Module(moduleName, "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000481 android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
Colin Cross2a076922018-10-04 23:28:25 -0700482 })
483 }
Colin Cross1a527682019-09-23 15:55:30 -0700484}
485
Bill Peckhamc087be12020-02-13 15:55:10 -0800486func TestGenruleHashInputs(t *testing.T) {
487
488 // The basic idea here is to verify that the sbox command (which is
489 // in the Command field of the generate rule) contains a hash of the
490 // inputs, but only if $(in) is not referenced in the genrule cmd
491 // property.
492
493 // By including a hash of the inputs, we cause the rule to re-run if
494 // the list of inputs changes (because the sbox command changes).
495
496 // However, if the genrule cmd property already contains $(in), then
497 // the dependency is already expressed, so we don't need to include the
498 // hash in that case.
499
500 bp := `
501 genrule {
502 name: "hash0",
503 srcs: ["in1.txt", "in2.txt"],
504 out: ["out"],
505 cmd: "echo foo > $(out)",
506 }
507 genrule {
508 name: "hash1",
509 srcs: ["*.txt"],
510 out: ["out"],
511 cmd: "echo bar > $(out)",
512 }
513 genrule {
514 name: "hash2",
515 srcs: ["*.txt"],
516 out: ["out"],
517 cmd: "echo $(in) > $(out)",
518 }
519 `
520 testcases := []struct {
521 name string
522 expectedHash string
523 }{
524 {
525 name: "hash0",
Colin Cross3d680512020-11-13 16:23:53 -0800526 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
527 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
Bill Peckhamc087be12020-02-13 15:55:10 -0800528 },
529 {
530 name: "hash1",
Colin Cross3d680512020-11-13 16:23:53 -0800531 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
532 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800533 },
534 {
535 name: "hash2",
Colin Cross3d680512020-11-13 16:23:53 -0800536 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
537 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800538 },
539 }
540
Paul Duffin89648f92021-03-20 00:36:55 +0000541 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Bill Peckhamc087be12020-02-13 15:55:10 -0800542
543 for _, test := range testcases {
544 t.Run(test.name, func(t *testing.T) {
Paul Duffine84b1332021-03-12 11:59:43 +0000545 gen := result.ModuleForTests(test.name, "")
Colin Crosse16ce362020-11-12 08:29:30 -0800546 manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
547 hash := manifest.Commands[0].GetInputHash()
Bill Peckhamc087be12020-02-13 15:55:10 -0800548
Paul Duffine84b1332021-03-12 11:59:43 +0000549 android.AssertStringEquals(t, "hash", test.expectedHash, hash)
Bill Peckhamc087be12020-02-13 15:55:10 -0800550 })
551 }
552}
553
Colin Cross1a527682019-09-23 15:55:30 -0700554func TestGenSrcs(t *testing.T) {
555 testcases := []struct {
556 name string
557 prop string
558
559 allowMissingDependencies bool
560
Liz Kammer796921d2023-07-11 08:21:41 -0400561 err string
562 cmds []string
563 deps []string
564 files []string
565 shards int
566 inputs []string
Colin Cross1a527682019-09-23 15:55:30 -0700567 }{
568 {
569 name: "gensrcs",
570 prop: `
571 tools: ["tool"],
572 srcs: ["in1.txt", "in2.txt"],
573 cmd: "$(location) $(in) > $(out)",
574 `,
575 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800576 "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 -0700577 },
Paul Duffine66946b2021-03-16 12:38:33 +0000578 deps: []string{
579 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
580 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
581 },
582 files: []string{
583 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
584 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
585 },
Colin Cross1a527682019-09-23 15:55:30 -0700586 },
587 {
588 name: "shards",
589 prop: `
590 tools: ["tool"],
591 srcs: ["in1.txt", "in2.txt", "in3.txt"],
592 cmd: "$(location) $(in) > $(out)",
593 shard_size: 2,
594 `,
595 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800596 "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'",
597 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700598 },
Paul Duffine66946b2021-03-16 12:38:33 +0000599 deps: []string{
600 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
601 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
602 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
603 },
604 files: []string{
605 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
606 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
607 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
608 },
Colin Cross1a527682019-09-23 15:55:30 -0700609 },
Liz Kammer81fec182023-06-09 13:33:45 -0400610 {
611 name: "data",
612 prop: `
613 tools: ["tool"],
614 srcs: ["in1.txt", "in2.txt", "in3.txt"],
615 cmd: "$(location) $(in) --extra_input=$(location baz.txt) > $(out)",
616 data: ["baz.txt"],
617 shard_size: 2,
618 `,
619 cmds: []string{
620 "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'",
621 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
622 },
623 deps: []string{
624 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
625 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
626 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
627 },
628 files: []string{
629 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
630 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
631 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
632 },
Liz Kammer796921d2023-07-11 08:21:41 -0400633 shards: 2,
634 inputs: []string{
635 "baz.txt",
636 },
Liz Kammer81fec182023-06-09 13:33:45 -0400637 },
Colin Cross1a527682019-09-23 15:55:30 -0700638 }
639
Liz Kammer796921d2023-07-11 08:21:41 -0400640 checkInputs := func(t *testing.T, rule android.TestingBuildParams, inputs []string) {
641 t.Helper()
642 if len(inputs) == 0 {
643 return
644 }
645 inputBaseNames := map[string]bool{}
646 for _, f := range rule.Implicits {
647 inputBaseNames[f.Base()] = true
648 }
649 for _, f := range inputs {
650 if _, ok := inputBaseNames[f]; !ok {
651 t.Errorf("Expected to find input file %q for %q, but did not", f, rule.Description)
652 }
653 }
654 }
655
Colin Cross1a527682019-09-23 15:55:30 -0700656 for _, test := range testcases {
657 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700658 bp := "gensrcs {\n"
659 bp += `name: "gen",` + "\n"
660 bp += `output_extension: "h",` + "\n"
661 bp += test.prop
662 bp += "}\n"
663
Paul Duffin672cb9f2021-03-03 02:30:37 +0000664 var expectedErrors []string
665 if test.err != "" {
666 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700667 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000668
Paul Duffin89648f92021-03-20 00:36:55 +0000669 result := prepareForGenRuleTest.
Paul Duffin672cb9f2021-03-03 02:30:37 +0000670 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
671 RunTestWithBp(t, testGenruleBp()+bp)
672
Liz Kammer796921d2023-07-11 08:21:41 -0400673 mod := result.ModuleForTests("gen", "")
Paul Duffin672cb9f2021-03-03 02:30:37 +0000674 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700675 return
676 }
677
Liz Kammer796921d2023-07-11 08:21:41 -0400678 if test.shards > 0 {
679 for i := 0; i < test.shards; i++ {
680 r := mod.Rule("generator" + strconv.Itoa(i))
681 checkInputs(t, r, test.inputs)
682 }
683 } else {
684 r := mod.Rule("generator")
685 checkInputs(t, r, test.inputs)
686 }
687
Paul Duffin672cb9f2021-03-03 02:30:37 +0000688 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000689 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700690
Paul Duffine66946b2021-03-16 12:38:33 +0000691 android.AssertPathsRelativeToTopEquals(t, "deps", test.deps, gen.outputDeps)
Colin Cross1a527682019-09-23 15:55:30 -0700692
Paul Duffine66946b2021-03-16 12:38:33 +0000693 android.AssertPathsRelativeToTopEquals(t, "files", test.files, gen.outputFiles)
Colin Cross1a527682019-09-23 15:55:30 -0700694 })
695 }
Colin Cross2a076922018-10-04 23:28:25 -0700696}
697
Yu Liu6a7940c2023-05-09 17:12:22 -0700698func TestGenruleAllowlistingDepfile(t *testing.T) {
Vinh Tran140d5882022-06-10 14:23:27 -0400699 tests := []struct {
Yu Liu6a7940c2023-05-09 17:12:22 -0700700 name string
701 prop string
702 err string
703 moduleName string
Vinh Tran140d5882022-06-10 14:23:27 -0400704 }{
705 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700706 name: `error when module is not allowlisted`,
Vinh Tran140d5882022-06-10 14:23:27 -0400707 prop: `
708 depfile: true,
709 cmd: "cat $(in) > $(out) && cat $(depfile)",
710 `,
Yu Liu6a7940c2023-05-09 17:12:22 -0700711 err: "depfile: Deprecated to ensure the module type is convertible to Bazel",
Vinh Tran140d5882022-06-10 14:23:27 -0400712 },
713 {
Yu Liu6a7940c2023-05-09 17:12:22 -0700714 name: `no error when module is allowlisted`,
Vinh Tran140d5882022-06-10 14:23:27 -0400715 prop: `
716 depfile: true,
717 cmd: "cat $(in) > $(out) && cat $(depfile)",
718 `,
Yu Liu6a7940c2023-05-09 17:12:22 -0700719 moduleName: `depfile_allowed_for_test`,
Vinh Tran140d5882022-06-10 14:23:27 -0400720 },
721 }
722 for _, test := range tests {
723 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700724 moduleName := "foo"
725 if test.moduleName != "" {
726 moduleName = test.moduleName
727 }
Vinh Tran140d5882022-06-10 14:23:27 -0400728 bp := fmt.Sprintf(`
729 gensrcs {
Yu Liu6a7940c2023-05-09 17:12:22 -0700730 name: "%s",
Vinh Tran140d5882022-06-10 14:23:27 -0400731 srcs: ["data.txt"],
732 %s
Yu Liu6a7940c2023-05-09 17:12:22 -0700733 }`, moduleName, test.prop)
Vinh Tran140d5882022-06-10 14:23:27 -0400734
735 var expectedErrors []string
736 if test.err != "" {
737 expectedErrors = append(expectedErrors, test.err)
738 }
739 android.GroupFixturePreparers(
740 prepareForGenRuleTest,
741 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700742 variables.GenruleSandboxing = proptools.BoolPtr(true)
Vinh Tran140d5882022-06-10 14:23:27 -0400743 }),
744 ).
745 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
746 RunTestWithBp(t, bp)
747 })
748
749 }
750}
751
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800752func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800753 bp := `
754 genrule_defaults {
755 name: "gen_defaults1",
756 cmd: "cp $(in) $(out)",
757 }
758
759 genrule_defaults {
760 name: "gen_defaults2",
761 srcs: ["in1"],
762 }
763
764 genrule {
765 name: "gen",
766 out: ["out"],
767 defaults: ["gen_defaults1", "gen_defaults2"],
768 }
769 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000770
Paul Duffin89648f92021-03-20 00:36:55 +0000771 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000772
773 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800774
Colin Crosse16ce362020-11-12 08:29:30 -0800775 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000776 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800777
778 expectedSrcs := []string{"in1"}
Paul Duffine84b1332021-03-12 11:59:43 +0000779 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800780}
781
Colin Crossfa65cee2021-03-22 17:05:59 -0700782func TestGenruleAllowMissingDependencies(t *testing.T) {
783 bp := `
784 output {
785 name: "disabled",
786 enabled: false,
787 }
788
789 genrule {
790 name: "gen",
791 srcs: [
792 ":disabled",
793 ],
794 out: ["out"],
795 cmd: "cat $(in) > $(out)",
796 }
797 `
Paul Duffin79abe572021-03-29 02:16:14 +0100798 result := android.GroupFixturePreparers(
799 prepareForGenRuleTest,
Colin Crossfa65cee2021-03-22 17:05:59 -0700800 android.FixtureModifyConfigAndContext(
801 func(config android.Config, ctx *android.TestContext) {
802 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
803 ctx.SetAllowMissingDependencies(true)
804 })).RunTestWithBp(t, bp)
805
806 gen := result.ModuleForTests("gen", "").Output("out")
807 if gen.Rule != android.ErrorRule {
808 t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
809 }
810}
811
Jooyung Han8c7e3ed2021-06-28 17:35:58 +0900812func TestGenruleOutputFiles(t *testing.T) {
813 bp := `
814 genrule {
815 name: "gen",
816 out: ["foo", "sub/bar"],
817 cmd: "echo foo > $(location foo) && echo bar > $(location sub/bar)",
818 }
819 use_source {
820 name: "gen_foo",
821 srcs: [":gen{foo}"],
822 }
823 use_source {
824 name: "gen_bar",
825 srcs: [":gen{sub/bar}"],
826 }
827 use_source {
828 name: "gen_all",
829 srcs: [":gen"],
830 }
831 `
832
833 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
834 android.AssertPathsRelativeToTopEquals(t,
835 "genrule.tag with output",
836 []string{"out/soong/.intermediates/gen/gen/foo"},
837 result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
838 android.AssertPathsRelativeToTopEquals(t,
839 "genrule.tag with output in subdir",
840 []string{"out/soong/.intermediates/gen/gen/sub/bar"},
841 result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
842 android.AssertPathsRelativeToTopEquals(t,
843 "genrule.tag with all",
844 []string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
845 result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
846}
847
Vinh Tran370e08c2022-09-23 18:09:01 -0400848func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
849 result := android.GroupFixturePreparers(
850 prepareForGenRuleTest,
851 android.FixtureMergeMockFs(android.MockFS{
852 "external-protos/path/Android.bp": []byte(`
853 filegroup {
854 name: "external-protos",
855 srcs: ["baz/baz.proto", "bar.proto"],
856 }
857 `),
858 "package-dir/Android.bp": []byte(`
859 gensrcs {
860 name: "module-name",
861 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
862 srcs: [
863 "src/foo.proto",
864 ":external-protos",
865 ],
866 output_extension: "proto.h",
867 }
868 `),
869 }),
870 ).RunTest(t)
871
872 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
873 gen := result.Module("module-name", "").(*Module)
874
875 android.AssertPathsRelativeToTopEquals(
876 t,
877 "include path",
878 []string{exportedIncludeDir},
879 gen.exportedIncludeDirs,
880 )
881 android.AssertPathsRelativeToTopEquals(
882 t,
883 "files",
884 []string{
885 exportedIncludeDir + "/package-dir/src/foo.proto.h",
886 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
887 exportedIncludeDir + "/external-protos/path/bar.proto.h",
888 },
889 gen.outputFiles,
890 )
891}
892
893func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
894 bp := `
895 gensrcs {
896 name: "module-name",
897 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
898 srcs: [
899 ":external-protos",
900 ],
901 output_extension: "proto.h",
902 }
903 `
904 result := android.GroupFixturePreparers(
905 prepareForGenRuleTest,
906 android.FixtureMergeMockFs(android.MockFS{
907 "external-protos/path/Android.bp": []byte(`
908 filegroup {
909 name: "external-protos",
910 srcs: ["foo/foo.proto", "bar.proto"],
911 }
912 `),
913 }),
914 ).RunTestWithBp(t, bp)
915
916 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
917 gen := result.Module("module-name", "").(*Module)
918
919 android.AssertPathsRelativeToTopEquals(
920 t,
921 "include path",
922 []string{exportedIncludeDir},
923 gen.exportedIncludeDirs,
924 )
925 android.AssertPathsRelativeToTopEquals(
926 t,
927 "files",
928 []string{
929 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
930 exportedIncludeDir + "/external-protos/path/bar.proto.h",
931 },
932 gen.outputFiles,
933 )
934}
935
Martin Stjernholmdbd814d2022-01-12 23:18:30 +0000936func TestPrebuiltTool(t *testing.T) {
937 testcases := []struct {
938 name string
939 bp string
940 expectedToolName string
941 }{
942 {
943 name: "source only",
944 bp: `
945 tool { name: "tool" }
946 `,
947 expectedToolName: "bin/tool",
948 },
949 {
950 name: "prebuilt only",
951 bp: `
952 prebuilt_tool { name: "tool" }
953 `,
954 expectedToolName: "prebuilt_bin/tool",
955 },
956 {
957 name: "source preferred",
958 bp: `
959 tool { name: "tool" }
960 prebuilt_tool { name: "tool" }
961 `,
962 expectedToolName: "bin/tool",
963 },
964 {
965 name: "prebuilt preferred",
966 bp: `
967 tool { name: "tool" }
968 prebuilt_tool { name: "tool", prefer: true }
969 `,
970 expectedToolName: "prebuilt_bin/prebuilt_tool",
971 },
972 {
973 name: "source disabled",
974 bp: `
975 tool { name: "tool", enabled: false }
976 prebuilt_tool { name: "tool" }
977 `,
978 expectedToolName: "prebuilt_bin/prebuilt_tool",
979 },
980 }
981
982 for _, test := range testcases {
983 t.Run(test.name, func(t *testing.T) {
984 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
985 genrule {
986 name: "gen",
987 tools: ["tool"],
988 out: ["foo"],
989 cmd: "$(location tool)",
990 }
991 `)
992 gen := result.Module("gen", "").(*Module)
993 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
994 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
995 })
996 }
997}
998
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400999func TestGenruleWithBazel(t *testing.T) {
1000 bp := `
1001 genrule {
1002 name: "foo",
1003 out: ["one.txt", "two.txt"],
Chris Parsonsaa8be052020-10-14 16:22:37 -04001004 bazel_module: { label: "//foo/bar:bar" },
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001005 }
1006 `
1007
Paul Duffin89648f92021-03-20 00:36:55 +00001008 result := android.GroupFixturePreparers(
1009 prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
1010 config.BazelContext = android.MockBazelContext{
Liz Kammera92e8442021-04-07 20:25:21 -04001011 OutputBaseDir: "outputbase",
1012 LabelToOutputFiles: map[string][]string{
Paul Duffin89648f92021-03-20 00:36:55 +00001013 "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
1014 })).RunTestWithBp(t, testGenruleBp()+bp)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001015
Paul Duffin672cb9f2021-03-03 02:30:37 +00001016 gen := result.Module("foo", "").(*Module)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001017
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -05001018 expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
1019 "outputbase/execroot/__main__/bazeltwo.txt"}
Paul Duffine84b1332021-03-12 11:59:43 +00001020 android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
1021 android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001022}
1023
Jihoon Kangc170af42022-08-20 05:26:38 +00001024func TestGenruleWithGlobPaths(t *testing.T) {
1025 testcases := []struct {
1026 name string
1027 bp string
1028 additionalFiles android.MockFS
1029 expectedCmd string
1030 }{
1031 {
1032 name: "single file in directory with $ sign",
1033 bp: `
1034 genrule {
1035 name: "gen",
1036 srcs: ["inn*.txt"],
1037 out: ["out.txt"],
1038 cmd: "cp $(in) $(out)",
1039 }
1040 `,
1041 additionalFiles: android.MockFS{"inn$1.txt": nil},
1042 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1043 },
1044 {
1045 name: "multiple file in directory with $ sign",
1046 bp: `
1047 genrule {
1048 name: "gen",
1049 srcs: ["inn*.txt"],
1050 out: ["."],
1051 cmd: "cp $(in) $(out)",
1052 }
1053 `,
1054 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
1055 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
1056 },
1057 {
1058 name: "file in directory with other shell unsafe character",
1059 bp: `
1060 genrule {
1061 name: "gen",
1062 srcs: ["inn*.txt"],
1063 out: ["out.txt"],
1064 cmd: "cp $(in) $(out)",
1065 }
1066 `,
1067 additionalFiles: android.MockFS{"inn@1.txt": nil},
1068 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1069 },
1070 {
1071 name: "glob location param with filepath containing $",
1072 bp: `
1073 genrule {
1074 name: "gen",
1075 srcs: ["**/inn*"],
1076 out: ["."],
1077 cmd: "cp $(in) $(location **/inn*)",
1078 }
1079 `,
1080 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1081 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1082 },
1083 {
1084 name: "glob locations param with filepath containing $",
1085 bp: `
1086 genrule {
1087 name: "gen",
1088 tool_files: ["**/inn*"],
1089 out: ["out.txt"],
1090 cmd: "cp $(locations **/inn*) $(out)",
1091 }
1092 `,
1093 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1094 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1095 },
1096 }
1097
1098 for _, test := range testcases {
1099 t.Run(test.name, func(t *testing.T) {
1100 result := android.GroupFixturePreparers(
1101 prepareForGenRuleTest,
1102 android.FixtureMergeMockFs(test.additionalFiles),
1103 ).RunTestWithBp(t, test.bp)
1104 gen := result.Module("gen", "").(*Module)
1105 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1106 })
1107 }
1108}
1109
Colin Cross2a076922018-10-04 23:28:25 -07001110type testTool struct {
1111 android.ModuleBase
1112 outputFile android.Path
1113}
1114
1115func toolFactory() android.Module {
1116 module := &testTool{}
1117 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1118 return module
1119}
1120
Colin Cross2a076922018-10-04 23:28:25 -07001121func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001122 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001123}
1124
1125func (t *testTool) HostToolPath() android.OptionalPath {
1126 return android.OptionalPathForPath(t.outputFile)
1127}
1128
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001129type prebuiltTestTool struct {
1130 android.ModuleBase
1131 prebuilt android.Prebuilt
1132 testTool
1133}
1134
1135func (p *prebuiltTestTool) Name() string {
1136 return p.prebuilt.Name(p.ModuleBase.Name())
1137}
1138
1139func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1140 return &p.prebuilt
1141}
1142
1143func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1144 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1145}
1146
1147func prebuiltToolFactory() android.Module {
1148 module := &prebuiltTestTool{}
1149 android.InitPrebuiltModuleWithoutSrcs(module)
1150 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1151 return module
1152}
1153
Colin Crossfe17f6f2019-03-28 19:30:56 -07001154var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001155var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001156
1157type testOutputProducer struct {
1158 android.ModuleBase
1159 outputFile android.Path
1160}
1161
1162func outputProducerFactory() android.Module {
1163 module := &testOutputProducer{}
1164 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1165 return module
1166}
1167
1168func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1169 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1170}
1171
1172func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) {
1173 return android.Paths{t.outputFile}, nil
1174}
1175
1176var _ android.OutputFileProducer = (*testOutputProducer)(nil)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001177
1178type useSource struct {
1179 android.ModuleBase
1180 props struct {
1181 Srcs []string `android:"path"`
1182 }
1183 srcs android.Paths
1184}
1185
1186func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1187 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1188}
1189
1190func useSourceFactory() android.Module {
1191 module := &useSource{}
1192 module.AddProperties(&module.props)
1193 android.InitAndroidModule(module)
1194 return module
1195}