blob: 4cff4b886564c2a274cbf2b7ed158e11127e58d4 [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 Crossf61d03d2023-11-02 16:56:39 -0700546 manifest := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
Colin Crosse16ce362020-11-12 08:29:30 -0800547 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
Liz Kammerd38c87c2023-07-17 09:58:50 -0400848func TestGenruleInterface(t *testing.T) {
849 result := android.GroupFixturePreparers(
850 prepareForGenRuleTest,
851 android.FixtureMergeMockFs(android.MockFS{
852 "package-dir/Android.bp": []byte(`
853 genrule {
854 name: "module-name",
855 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
856 srcs: [
857 "src/foo.proto",
858 ],
859 out: ["proto.h", "bar/proto.h"],
860 export_include_dirs: [".", "bar"],
861 }
862 `),
863 }),
864 ).RunTest(t)
865
866 exportedIncludeDirs := []string{
867 "out/soong/.intermediates/package-dir/module-name/gen/package-dir",
868 "out/soong/.intermediates/package-dir/module-name/gen",
869 "out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
870 "out/soong/.intermediates/package-dir/module-name/gen/bar",
871 }
872 gen := result.Module("module-name", "").(*Module)
873
874 android.AssertPathsRelativeToTopEquals(
875 t,
876 "include path",
877 exportedIncludeDirs,
878 gen.GeneratedHeaderDirs(),
879 )
880 android.AssertPathsRelativeToTopEquals(
881 t,
882 "files",
883 []string{
884 "out/soong/.intermediates/package-dir/module-name/gen/proto.h",
885 "out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
886 },
887 gen.GeneratedSourceFiles(),
888 )
889}
890
Vinh Tran370e08c2022-09-23 18:09:01 -0400891func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
892 result := android.GroupFixturePreparers(
893 prepareForGenRuleTest,
894 android.FixtureMergeMockFs(android.MockFS{
895 "external-protos/path/Android.bp": []byte(`
896 filegroup {
897 name: "external-protos",
898 srcs: ["baz/baz.proto", "bar.proto"],
899 }
900 `),
901 "package-dir/Android.bp": []byte(`
902 gensrcs {
903 name: "module-name",
904 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
905 srcs: [
906 "src/foo.proto",
907 ":external-protos",
908 ],
909 output_extension: "proto.h",
910 }
911 `),
912 }),
913 ).RunTest(t)
914
915 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
916 gen := result.Module("module-name", "").(*Module)
917
918 android.AssertPathsRelativeToTopEquals(
919 t,
920 "include path",
921 []string{exportedIncludeDir},
922 gen.exportedIncludeDirs,
923 )
924 android.AssertPathsRelativeToTopEquals(
925 t,
926 "files",
927 []string{
928 exportedIncludeDir + "/package-dir/src/foo.proto.h",
929 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
930 exportedIncludeDir + "/external-protos/path/bar.proto.h",
931 },
932 gen.outputFiles,
933 )
934}
935
936func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
937 bp := `
938 gensrcs {
939 name: "module-name",
940 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
941 srcs: [
942 ":external-protos",
943 ],
944 output_extension: "proto.h",
945 }
946 `
947 result := android.GroupFixturePreparers(
948 prepareForGenRuleTest,
949 android.FixtureMergeMockFs(android.MockFS{
950 "external-protos/path/Android.bp": []byte(`
951 filegroup {
952 name: "external-protos",
953 srcs: ["foo/foo.proto", "bar.proto"],
954 }
955 `),
956 }),
957 ).RunTestWithBp(t, bp)
958
959 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
960 gen := result.Module("module-name", "").(*Module)
961
962 android.AssertPathsRelativeToTopEquals(
963 t,
964 "include path",
965 []string{exportedIncludeDir},
966 gen.exportedIncludeDirs,
967 )
968 android.AssertPathsRelativeToTopEquals(
969 t,
970 "files",
971 []string{
972 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
973 exportedIncludeDir + "/external-protos/path/bar.proto.h",
974 },
975 gen.outputFiles,
976 )
977}
978
Martin Stjernholmdbd814d2022-01-12 23:18:30 +0000979func TestPrebuiltTool(t *testing.T) {
980 testcases := []struct {
981 name string
982 bp string
983 expectedToolName string
984 }{
985 {
986 name: "source only",
987 bp: `
988 tool { name: "tool" }
989 `,
990 expectedToolName: "bin/tool",
991 },
992 {
993 name: "prebuilt only",
994 bp: `
995 prebuilt_tool { name: "tool" }
996 `,
997 expectedToolName: "prebuilt_bin/tool",
998 },
999 {
1000 name: "source preferred",
1001 bp: `
1002 tool { name: "tool" }
1003 prebuilt_tool { name: "tool" }
1004 `,
1005 expectedToolName: "bin/tool",
1006 },
1007 {
1008 name: "prebuilt preferred",
1009 bp: `
1010 tool { name: "tool" }
1011 prebuilt_tool { name: "tool", prefer: true }
1012 `,
1013 expectedToolName: "prebuilt_bin/prebuilt_tool",
1014 },
1015 {
1016 name: "source disabled",
1017 bp: `
1018 tool { name: "tool", enabled: false }
1019 prebuilt_tool { name: "tool" }
1020 `,
1021 expectedToolName: "prebuilt_bin/prebuilt_tool",
1022 },
1023 }
1024
1025 for _, test := range testcases {
1026 t.Run(test.name, func(t *testing.T) {
1027 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
1028 genrule {
1029 name: "gen",
1030 tools: ["tool"],
1031 out: ["foo"],
1032 cmd: "$(location tool)",
1033 }
1034 `)
1035 gen := result.Module("gen", "").(*Module)
1036 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
1037 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
1038 })
1039 }
1040}
1041
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001042func TestGenruleWithBazel(t *testing.T) {
1043 bp := `
1044 genrule {
1045 name: "foo",
1046 out: ["one.txt", "two.txt"],
Chris Parsonsaa8be052020-10-14 16:22:37 -04001047 bazel_module: { label: "//foo/bar:bar" },
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001048 }
1049 `
1050
Paul Duffin89648f92021-03-20 00:36:55 +00001051 result := android.GroupFixturePreparers(
1052 prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
1053 config.BazelContext = android.MockBazelContext{
Liz Kammera92e8442021-04-07 20:25:21 -04001054 OutputBaseDir: "outputbase",
1055 LabelToOutputFiles: map[string][]string{
Paul Duffin89648f92021-03-20 00:36:55 +00001056 "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
1057 })).RunTestWithBp(t, testGenruleBp()+bp)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001058
Paul Duffin672cb9f2021-03-03 02:30:37 +00001059 gen := result.Module("foo", "").(*Module)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001060
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -05001061 expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
1062 "outputbase/execroot/__main__/bazeltwo.txt"}
Paul Duffine84b1332021-03-12 11:59:43 +00001063 android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
1064 android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001065}
1066
Jihoon Kangc170af42022-08-20 05:26:38 +00001067func TestGenruleWithGlobPaths(t *testing.T) {
1068 testcases := []struct {
1069 name string
1070 bp string
1071 additionalFiles android.MockFS
1072 expectedCmd string
1073 }{
1074 {
1075 name: "single file in directory with $ sign",
1076 bp: `
1077 genrule {
1078 name: "gen",
1079 srcs: ["inn*.txt"],
1080 out: ["out.txt"],
1081 cmd: "cp $(in) $(out)",
1082 }
1083 `,
1084 additionalFiles: android.MockFS{"inn$1.txt": nil},
1085 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1086 },
1087 {
1088 name: "multiple file in directory with $ sign",
1089 bp: `
1090 genrule {
1091 name: "gen",
1092 srcs: ["inn*.txt"],
1093 out: ["."],
1094 cmd: "cp $(in) $(out)",
1095 }
1096 `,
1097 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
1098 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
1099 },
1100 {
1101 name: "file in directory with other shell unsafe character",
1102 bp: `
1103 genrule {
1104 name: "gen",
1105 srcs: ["inn*.txt"],
1106 out: ["out.txt"],
1107 cmd: "cp $(in) $(out)",
1108 }
1109 `,
1110 additionalFiles: android.MockFS{"inn@1.txt": nil},
1111 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1112 },
1113 {
1114 name: "glob location param with filepath containing $",
1115 bp: `
1116 genrule {
1117 name: "gen",
1118 srcs: ["**/inn*"],
1119 out: ["."],
1120 cmd: "cp $(in) $(location **/inn*)",
1121 }
1122 `,
1123 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1124 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1125 },
1126 {
1127 name: "glob locations param with filepath containing $",
1128 bp: `
1129 genrule {
1130 name: "gen",
1131 tool_files: ["**/inn*"],
1132 out: ["out.txt"],
1133 cmd: "cp $(locations **/inn*) $(out)",
1134 }
1135 `,
1136 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1137 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1138 },
1139 }
1140
1141 for _, test := range testcases {
1142 t.Run(test.name, func(t *testing.T) {
1143 result := android.GroupFixturePreparers(
1144 prepareForGenRuleTest,
1145 android.FixtureMergeMockFs(test.additionalFiles),
1146 ).RunTestWithBp(t, test.bp)
1147 gen := result.Module("gen", "").(*Module)
1148 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1149 })
1150 }
1151}
1152
Colin Cross2a076922018-10-04 23:28:25 -07001153type testTool struct {
1154 android.ModuleBase
1155 outputFile android.Path
1156}
1157
1158func toolFactory() android.Module {
1159 module := &testTool{}
1160 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1161 return module
1162}
1163
Colin Cross2a076922018-10-04 23:28:25 -07001164func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001165 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001166}
1167
1168func (t *testTool) HostToolPath() android.OptionalPath {
1169 return android.OptionalPathForPath(t.outputFile)
1170}
1171
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001172type prebuiltTestTool struct {
1173 android.ModuleBase
1174 prebuilt android.Prebuilt
1175 testTool
1176}
1177
1178func (p *prebuiltTestTool) Name() string {
1179 return p.prebuilt.Name(p.ModuleBase.Name())
1180}
1181
1182func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1183 return &p.prebuilt
1184}
1185
1186func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1187 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1188}
1189
1190func prebuiltToolFactory() android.Module {
1191 module := &prebuiltTestTool{}
1192 android.InitPrebuiltModuleWithoutSrcs(module)
1193 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1194 return module
1195}
1196
Colin Crossfe17f6f2019-03-28 19:30:56 -07001197var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001198var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001199
1200type testOutputProducer struct {
1201 android.ModuleBase
1202 outputFile android.Path
1203}
1204
1205func outputProducerFactory() android.Module {
1206 module := &testOutputProducer{}
1207 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1208 return module
1209}
1210
1211func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1212 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1213}
1214
1215func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) {
1216 return android.Paths{t.outputFile}, nil
1217}
1218
1219var _ android.OutputFileProducer = (*testOutputProducer)(nil)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001220
1221type useSource struct {
1222 android.ModuleBase
1223 props struct {
1224 Srcs []string `android:"path"`
1225 }
1226 srcs android.Paths
1227}
1228
1229func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1230 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1231}
1232
1233func useSourceFactory() android.Module {
1234 module := &useSource{}
1235 module.AddProperties(&module.props)
1236 android.InitAndroidModule(module)
1237 return module
1238}