blob: 6f980ce4c7e9ebed412581ca0ed0dbabc720a82b [file] [log] [blame]
Cole Faust5a231bd2024-02-07 09:43:59 -08001// Copyright 2024 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 android
16
17import (
18 "fmt"
19 "reflect"
20 "testing"
21
22 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24)
25
26func TestSelects(t *testing.T) {
27 testCases := []struct {
28 name string
29 bp string
30 provider selectsTestProvider
Cole Faust69349462024-04-25 16:02:15 -070031 providers map[string]selectsTestProvider
Cole Faust5a231bd2024-02-07 09:43:59 -080032 vendorVars map[string]map[string]string
33 expectedError string
34 }{
35 {
36 name: "basic string list",
37 bp: `
38 my_module_type {
39 name: "foo",
40 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
41 "a": ["a.cpp"],
42 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -070043 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -080044 }),
45 }
46 `,
47 provider: selectsTestProvider{
48 my_string_list: &[]string{"c.cpp"},
49 },
50 },
51 {
52 name: "basic string",
53 bp: `
54 my_module_type {
55 name: "foo",
56 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
57 "a": "a.cpp",
58 "b": "b.cpp",
Cole Faust683316a2024-04-02 16:45:54 -070059 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -080060 }),
61 }
62 `,
63 provider: selectsTestProvider{
64 my_string: proptools.StringPtr("c.cpp"),
65 },
66 },
67 {
68 name: "basic bool",
69 bp: `
70 my_module_type {
71 name: "foo",
72 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
73 "a": true,
74 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -070075 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -080076 }),
77 }
78 `,
79 provider: selectsTestProvider{
80 my_bool: proptools.BoolPtr(true),
81 },
82 },
83 {
Cole Faustbdd8aee2024-03-14 14:33:02 -070084 name: "basic paths",
85 bp: `
86 my_module_type {
87 name: "foo",
88 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
89 "a": ["foo.txt"],
90 "b": ["bar.txt"],
Cole Faust683316a2024-04-02 16:45:54 -070091 default: ["baz.txt"],
Cole Faustbdd8aee2024-03-14 14:33:02 -070092 }),
93 }
94 `,
95 provider: selectsTestProvider{
96 my_paths: &[]string{"baz.txt"},
97 },
98 },
99 {
100 name: "paths with module references",
101 bp: `
102 my_module_type {
103 name: "foo",
104 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
105 "a": [":a"],
106 "b": [":b"],
Cole Faust683316a2024-04-02 16:45:54 -0700107 default: [":c"],
Cole Faustbdd8aee2024-03-14 14:33:02 -0700108 }),
109 }
110 `,
111 expectedError: `"foo" depends on undefined module "c"`,
112 },
113 {
Cole Faust5a231bd2024-02-07 09:43:59 -0800114 name: "Differing types",
115 bp: `
116 my_module_type {
117 name: "foo",
118 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
119 "a": "a.cpp",
120 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700121 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -0800122 }),
123 }
124 `,
Cole Faust12c8ed42024-03-28 16:26:59 -0700125 expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`,
126 },
127 {
128 name: "Select type doesn't match property type",
129 bp: `
130 my_module_type {
131 name: "foo",
132 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
133 "a": false,
134 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700135 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700136 }),
137 }
138 `,
139 expectedError: `can't assign bool value to string property "my_string\[0\]"`,
Cole Faust5a231bd2024-02-07 09:43:59 -0800140 },
141 {
142 name: "String list non-default",
143 bp: `
144 my_module_type {
145 name: "foo",
146 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
147 "a": ["a.cpp"],
148 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700149 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800150 }),
151 }
152 `,
153 provider: selectsTestProvider{
154 my_string_list: &[]string{"a.cpp"},
155 },
156 vendorVars: map[string]map[string]string{
157 "my_namespace": {
158 "my_variable": "a",
159 },
160 },
161 },
162 {
163 name: "String list append",
164 bp: `
165 my_module_type {
166 name: "foo",
167 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
168 "a": ["a.cpp"],
169 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700170 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800171 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
172 "a2": ["a2.cpp"],
173 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700174 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800175 }),
176 }
177 `,
178 provider: selectsTestProvider{
179 my_string_list: &[]string{"a.cpp", "c2.cpp"},
180 },
181 vendorVars: map[string]map[string]string{
182 "my_namespace": {
183 "my_variable": "a",
184 },
185 },
186 },
187 {
188 name: "String list prepend literal",
189 bp: `
190 my_module_type {
191 name: "foo",
192 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
193 "a2": ["a2.cpp"],
194 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700195 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800196 }),
197 }
198 `,
199 provider: selectsTestProvider{
200 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
201 },
202 },
203 {
204 name: "String list append literal",
205 bp: `
206 my_module_type {
207 name: "foo",
208 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
209 "a2": ["a2.cpp"],
210 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700211 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800212 }) + ["literal.cpp"],
213 }
214 `,
215 provider: selectsTestProvider{
216 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
217 },
218 },
219 {
Cole Faust74ef4652024-03-27 16:45:41 -0700220 name: "true + false = true",
Cole Faust5a231bd2024-02-07 09:43:59 -0800221 bp: `
222 my_module_type {
223 name: "foo",
224 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
225 "a": true,
226 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700227 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -0800228 }) + false,
229 }
230 `,
Cole Faust74ef4652024-03-27 16:45:41 -0700231 provider: selectsTestProvider{
232 my_bool: proptools.BoolPtr(true),
233 },
234 },
235 {
236 name: "false + false = false",
237 bp: `
238 my_module_type {
239 name: "foo",
240 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
241 "a": true,
242 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700243 default: true,
Cole Faust74ef4652024-03-27 16:45:41 -0700244 }) + false,
245 }
246 `,
247 vendorVars: map[string]map[string]string{
248 "my_namespace": {
249 "my_variable": "b",
250 },
251 },
252 provider: selectsTestProvider{
253 my_bool: proptools.BoolPtr(false),
254 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800255 },
256 {
257 name: "Append string",
258 bp: `
259 my_module_type {
260 name: "foo",
261 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
262 "a": "a",
263 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700264 default: "c",
Cole Faust5a231bd2024-02-07 09:43:59 -0800265 }) + ".cpp",
266 }
267 `,
268 provider: selectsTestProvider{
269 my_string: proptools.StringPtr("c.cpp"),
270 },
271 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700272 {
Cole Faustfc57d402024-04-11 12:09:44 -0700273 name: "Select on arch",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700274 bp: `
275 my_module_type {
276 name: "foo",
Cole Faustfc57d402024-04-11 12:09:44 -0700277 my_string: select(arch(), {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700278 "x86": "my_x86",
279 "x86_64": "my_x86_64",
280 "arm": "my_arm",
281 "arm64": "my_arm64",
Cole Faust683316a2024-04-02 16:45:54 -0700282 default: "my_default",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700283 }),
284 }
285 `,
286 provider: selectsTestProvider{
287 my_string: proptools.StringPtr("my_arm64"),
288 },
289 },
Cole Faust12c8ed42024-03-28 16:26:59 -0700290 {
Cole Faustfc57d402024-04-11 12:09:44 -0700291 name: "Select on os",
292 bp: `
293 my_module_type {
294 name: "foo",
295 my_string: select(os(), {
296 "android": "my_android",
297 "linux": "my_linux",
298 default: "my_default",
299 }),
300 }
301 `,
302 provider: selectsTestProvider{
303 my_string: proptools.StringPtr("my_android"),
304 },
305 },
306 {
Cole Faust12c8ed42024-03-28 16:26:59 -0700307 name: "Unset value",
308 bp: `
309 my_module_type {
310 name: "foo",
311 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
312 "a": unset,
313 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700314 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700315 })
316 }
317 `,
318 vendorVars: map[string]map[string]string{
319 "my_namespace": {
320 "my_variable": "a",
321 },
322 },
323 provider: selectsTestProvider{},
324 },
325 {
326 name: "Unset value on different branch",
327 bp: `
328 my_module_type {
329 name: "foo",
330 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
331 "a": unset,
332 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700333 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700334 })
335 }
336 `,
337 provider: selectsTestProvider{
338 my_string: proptools.StringPtr("c"),
339 },
340 },
341 {
342 name: "unset + unset = unset",
343 bp: `
344 my_module_type {
345 name: "foo",
346 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700347 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700348 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700349 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700350 "baz": "qux",
Cole Faust683316a2024-04-02 16:45:54 -0700351 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700352 })
353 }
354 `,
355 provider: selectsTestProvider{},
356 },
357 {
358 name: "unset + string = string",
359 bp: `
360 my_module_type {
361 name: "foo",
362 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700363 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700364 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700365 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700366 default: "a",
Cole Faust12c8ed42024-03-28 16:26:59 -0700367 })
368 }
369 `,
370 provider: selectsTestProvider{
371 my_string: proptools.StringPtr("a"),
372 },
373 },
374 {
375 name: "unset + bool = bool",
376 bp: `
377 my_module_type {
378 name: "foo",
379 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
380 "a": true,
Cole Faust683316a2024-04-02 16:45:54 -0700381 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700382 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700383 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700384 })
385 }
386 `,
387 provider: selectsTestProvider{
388 my_bool: proptools.BoolPtr(true),
389 },
390 },
Cole Faust02dd6e52024-04-03 17:04:57 -0700391 {
392 name: "defaults with lists are appended",
393 bp: `
394 my_module_type {
395 name: "foo",
396 defaults: ["bar"],
397 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
398 "a": ["a1"],
399 default: ["b1"],
400 }),
401 }
402 my_defaults {
403 name: "bar",
404 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
405 "a": ["a2"],
406 default: ["b2"],
407 }),
408 }
409 `,
410 provider: selectsTestProvider{
411 my_string_list: &[]string{"b2", "b1"},
412 },
413 },
414 {
Cole Faust69349462024-04-25 16:02:15 -0700415 name: "defaults applied to multiple modules",
416 bp: `
417 my_module_type {
418 name: "foo2",
419 defaults: ["bar"],
420 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
421 "a": ["a1"],
422 default: ["b1"],
423 }),
424 }
425 my_module_type {
426 name: "foo",
427 defaults: ["bar"],
428 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
429 "a": ["a1"],
430 default: ["b1"],
431 }),
432 }
433 my_defaults {
434 name: "bar",
435 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
436 "a": ["a2"],
437 default: ["b2"],
438 }),
439 }
440 `,
441 providers: map[string]selectsTestProvider{
442 "foo": {
443 my_string_list: &[]string{"b2", "b1"},
444 },
445 "foo2": {
446 my_string_list: &[]string{"b2", "b1"},
447 },
448 },
449 },
450 {
Cole Faust02dd6e52024-04-03 17:04:57 -0700451 name: "Replacing string list",
452 bp: `
453 my_module_type {
454 name: "foo",
455 defaults: ["bar"],
456 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
457 "a": ["a1"],
458 default: ["b1"],
459 }),
460 }
461 my_defaults {
462 name: "bar",
463 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
464 "a": ["a2"],
465 default: ["b2"],
466 }),
467 }
468 `,
469 provider: selectsTestProvider{
470 replacing_string_list: &[]string{"b1"},
471 },
472 },
Cole Faustfdbf5d42024-04-10 15:01:23 -0700473 {
474 name: "Multi-condition string 1",
475 bp: `
476 my_module_type {
477 name: "foo",
478 my_string: select((
479 soong_config_variable("my_namespace", "my_variable"),
480 soong_config_variable("my_namespace", "my_variable2"),
481 ), {
482 ("a", "b"): "a+b",
483 ("a", default): "a+default",
484 (default, default): "default",
485 }),
486 }
487 `,
488 vendorVars: map[string]map[string]string{
489 "my_namespace": {
490 "my_variable": "a",
491 "my_variable2": "b",
492 },
493 },
494 provider: selectsTestProvider{
495 my_string: proptools.StringPtr("a+b"),
496 },
497 },
498 {
499 name: "Multi-condition string 2",
500 bp: `
501 my_module_type {
502 name: "foo",
503 my_string: select((
504 soong_config_variable("my_namespace", "my_variable"),
505 soong_config_variable("my_namespace", "my_variable2"),
506 ), {
507 ("a", "b"): "a+b",
508 ("a", default): "a+default",
509 (default, default): "default",
510 }),
511 }
512 `,
513 vendorVars: map[string]map[string]string{
514 "my_namespace": {
515 "my_variable": "a",
516 "my_variable2": "c",
517 },
518 },
519 provider: selectsTestProvider{
520 my_string: proptools.StringPtr("a+default"),
521 },
522 },
523 {
524 name: "Multi-condition string 3",
525 bp: `
526 my_module_type {
527 name: "foo",
528 my_string: select((
529 soong_config_variable("my_namespace", "my_variable"),
530 soong_config_variable("my_namespace", "my_variable2"),
531 ), {
532 ("a", "b"): "a+b",
533 ("a", default): "a+default",
534 (default, default): "default",
535 }),
536 }
537 `,
538 vendorVars: map[string]map[string]string{
539 "my_namespace": {
540 "my_variable": "c",
541 "my_variable2": "b",
542 },
543 },
544 provider: selectsTestProvider{
545 my_string: proptools.StringPtr("default"),
546 },
547 },
548 {
Cole Faustb81dc0e2024-05-09 15:51:52 -0700549 name: "Unhandled string value",
550 bp: `
551 my_module_type {
552 name: "foo",
553 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
554 "foo": "a",
555 "bar": "b",
556 }),
557 }
558 `,
559 vendorVars: map[string]map[string]string{
560 "my_namespace": {
561 "my_variable": "baz",
562 },
563 },
564 expectedError: `my_string: soong_config_variable\("my_namespace", "my_variable"\) had value "baz", which was not handled by the select statement`,
565 },
566 {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700567 name: "Select on boolean",
568 bp: `
569 my_module_type {
570 name: "foo",
571 my_string: select(boolean_var_for_testing(), {
572 true: "t",
573 false: "f",
574 }),
575 }
576 `,
577 vendorVars: map[string]map[string]string{
578 "boolean_var": {
579 "for_testing": "true",
580 },
581 },
582 provider: selectsTestProvider{
583 my_string: proptools.StringPtr("t"),
584 },
585 },
586 {
587 name: "Select on boolean false",
588 bp: `
589 my_module_type {
590 name: "foo",
591 my_string: select(boolean_var_for_testing(), {
592 true: "t",
593 false: "f",
594 }),
595 }
596 `,
597 vendorVars: map[string]map[string]string{
598 "boolean_var": {
599 "for_testing": "false",
600 },
601 },
602 provider: selectsTestProvider{
603 my_string: proptools.StringPtr("f"),
604 },
605 },
606 {
607 name: "Select on boolean undefined",
608 bp: `
609 my_module_type {
610 name: "foo",
611 my_string: select(boolean_var_for_testing(), {
612 true: "t",
613 false: "f",
614 }),
615 }
616 `,
Cole Faustb81dc0e2024-05-09 15:51:52 -0700617 expectedError: `my_string: boolean_var_for_testing\(\) had value undefined, which was not handled by the select statement`,
Cole Faustfdbf5d42024-04-10 15:01:23 -0700618 },
619 {
620 name: "Select on boolean undefined with default",
621 bp: `
622 my_module_type {
623 name: "foo",
624 my_string: select(boolean_var_for_testing(), {
625 true: "t",
626 false: "f",
627 default: "default",
628 }),
629 }
630 `,
631 provider: selectsTestProvider{
632 my_string: proptools.StringPtr("default"),
633 },
634 },
635 {
636 name: "Mismatched condition types",
637 bp: `
638 my_module_type {
639 name: "foo",
640 my_string: select(boolean_var_for_testing(), {
641 "true": "t",
642 "false": "f",
643 default: "default",
644 }),
645 }
646 `,
647 vendorVars: map[string]map[string]string{
648 "boolean_var": {
649 "for_testing": "false",
650 },
651 },
652 expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
653 },
Cole Faust60f6bb22024-04-30 13:58:55 -0700654 {
655 name: "Assigning select to nonconfigurable bool",
656 bp: `
657 my_module_type {
658 name: "foo",
659 my_nonconfigurable_bool: select(arch(), {
660 "x86_64": true,
661 default: false,
662 }),
663 }
664 `,
665 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
666 },
667 {
668 name: "Assigning select to nonconfigurable string",
669 bp: `
670 my_module_type {
671 name: "foo",
672 my_nonconfigurable_string: select(arch(), {
673 "x86_64": "x86!",
674 default: "unknown!",
675 }),
676 }
677 `,
678 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
679 },
680 {
681 name: "Assigning appended selects to nonconfigurable string",
682 bp: `
683 my_module_type {
684 name: "foo",
685 my_nonconfigurable_string: select(arch(), {
686 "x86_64": "x86!",
687 default: "unknown!",
688 }) + select(os(), {
689 "darwin": "_darwin!",
690 default: "unknown!",
691 }),
692 }
693 `,
694 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
695 },
696 {
697 name: "Assigning select to nonconfigurable string list",
698 bp: `
699 my_module_type {
700 name: "foo",
701 my_nonconfigurable_string_list: select(arch(), {
702 "x86_64": ["foo", "bar"],
703 default: ["baz", "qux"],
704 }),
705 }
706 `,
707 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
708 },
Cole Faustb9519092024-05-21 11:20:15 -0700709 {
710 name: "Select in variable",
711 bp: `
712 my_second_variable = ["after.cpp"]
713 my_variable = select(soong_config_variable("my_namespace", "my_variable"), {
714 "a": ["a.cpp"],
715 "b": ["b.cpp"],
716 default: ["c.cpp"],
717 }) + my_second_variable
718 my_module_type {
719 name: "foo",
720 my_string_list: ["before.cpp"] + my_variable,
721 }
722 `,
723 provider: selectsTestProvider{
724 my_string_list: &[]string{"before.cpp", "a.cpp", "after.cpp"},
725 },
726 vendorVars: map[string]map[string]string{
727 "my_namespace": {
728 "my_variable": "a",
729 },
730 },
731 },
Cole Faust5f297062024-05-22 14:30:16 -0700732 {
733 name: "Soong config value variable on configurable property",
734 bp: `
735 soong_config_module_type {
736 name: "soong_config_my_module_type",
737 module_type: "my_module_type",
738 config_namespace: "my_namespace",
739 value_variables: ["my_variable"],
740 properties: ["my_string", "my_string_list"],
741 }
742
743 soong_config_my_module_type {
744 name: "foo",
745 my_string_list: ["before.cpp"],
746 soong_config_variables: {
747 my_variable: {
748 my_string_list: ["after_%s.cpp"],
749 my_string: "%s.cpp",
750 },
751 },
752 }
753 `,
754 provider: selectsTestProvider{
755 my_string: proptools.StringPtr("foo.cpp"),
756 my_string_list: &[]string{"before.cpp", "after_foo.cpp"},
757 },
758 vendorVars: map[string]map[string]string{
759 "my_namespace": {
760 "my_variable": "foo",
761 },
762 },
763 },
Cole Faustaeecb752024-05-22 13:41:35 -0700764 {
765 name: "Property appending with variable",
766 bp: `
767 my_variable = ["b.cpp"]
768 my_module_type {
769 name: "foo",
770 my_string_list: ["a.cpp"] + my_variable + select(soong_config_variable("my_namespace", "my_variable"), {
771 "a": ["a.cpp"],
772 "b": ["b.cpp"],
773 default: ["c.cpp"],
774 }),
775 }
776 `,
777 provider: selectsTestProvider{
778 my_string_list: &[]string{"a.cpp", "b.cpp", "c.cpp"},
779 },
780 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800781 }
782
783 for _, tc := range testCases {
784 t.Run(tc.name, func(t *testing.T) {
785 fixtures := GroupFixturePreparers(
Cole Faust02dd6e52024-04-03 17:04:57 -0700786 PrepareForTestWithDefaults,
Cole Faust0aa21cc2024-03-20 12:28:03 -0700787 PrepareForTestWithArchMutator,
Cole Faust5f297062024-05-22 14:30:16 -0700788 PrepareForTestWithSoongConfigModuleBuildComponents,
Cole Faust5a231bd2024-02-07 09:43:59 -0800789 FixtureRegisterWithContext(func(ctx RegistrationContext) {
790 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
Cole Faust02dd6e52024-04-03 17:04:57 -0700791 ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults)
Cole Faust5a231bd2024-02-07 09:43:59 -0800792 }),
793 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
794 variables.VendorVars = tc.vendorVars
795 }),
796 )
797 if tc.expectedError != "" {
798 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
799 }
800 result := fixtures.RunTestWithBp(t, tc.bp)
801
802 if tc.expectedError == "" {
Cole Faust69349462024-04-25 16:02:15 -0700803 if len(tc.providers) == 0 {
804 tc.providers = map[string]selectsTestProvider{
805 "foo": tc.provider,
806 }
807 }
808
809 for moduleName := range tc.providers {
810 expected := tc.providers[moduleName]
811 m := result.ModuleForTests(moduleName, "android_arm64_armv8-a")
812 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
813 if !reflect.DeepEqual(p, expected) {
814 t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String())
815 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800816 }
817 }
818 })
819 }
820}
821
822type selectsTestProvider struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700823 my_bool *bool
824 my_string *string
825 my_string_list *[]string
826 my_paths *[]string
827 replacing_string_list *[]string
828 my_nonconfigurable_bool *bool
829 my_nonconfigurable_string *string
830 my_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800831}
832
833func (p *selectsTestProvider) String() string {
834 myBoolStr := "nil"
835 if p.my_bool != nil {
836 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
837 }
838 myStringStr := "nil"
839 if p.my_string != nil {
840 myStringStr = *p.my_string
841 }
Cole Faust60f6bb22024-04-30 13:58:55 -0700842 myNonconfigurableStringStr := "nil"
Cole Faust5f297062024-05-22 14:30:16 -0700843 if p.my_nonconfigurable_string != nil {
Cole Faust60f6bb22024-04-30 13:58:55 -0700844 myNonconfigurableStringStr = *p.my_nonconfigurable_string
845 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800846 return fmt.Sprintf(`selectsTestProvider {
847 my_bool: %v,
848 my_string: %s,
849 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700850 my_paths: %s,
Cole Faust02dd6e52024-04-03 17:04:57 -0700851 replacing_string_list %s,
Cole Faust60f6bb22024-04-30 13:58:55 -0700852 my_nonconfigurable_bool: %v,
853 my_nonconfigurable_string: %s,
854 my_nonconfigurable_string_list: %s,
855}`,
856 myBoolStr,
857 myStringStr,
858 p.my_string_list,
859 p.my_paths,
860 p.replacing_string_list,
861 p.my_nonconfigurable_bool,
862 myNonconfigurableStringStr,
863 p.my_nonconfigurable_string_list,
864 )
Cole Faust5a231bd2024-02-07 09:43:59 -0800865}
866
867var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
868
869type selectsMockModuleProperties struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700870 My_bool proptools.Configurable[bool]
871 My_string proptools.Configurable[string]
872 My_string_list proptools.Configurable[[]string]
873 My_paths proptools.Configurable[[]string] `android:"path"`
874 Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
875 My_nonconfigurable_bool *bool
876 My_nonconfigurable_string *string
877 My_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800878}
879
880type selectsMockModule struct {
881 ModuleBase
882 DefaultableModuleBase
883 properties selectsMockModuleProperties
884}
885
Cole Faust749eeaa2024-05-21 14:19:05 -0700886func optionalToPtr[T any](o proptools.ConfigurableOptional[T]) *T {
887 if o.IsEmpty() {
888 return nil
889 }
890 x := o.Get()
891 return &x
892}
893
Cole Faust5a231bd2024-02-07 09:43:59 -0800894func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700895 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust749eeaa2024-05-21 14:19:05 -0700896 my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)),
897 my_string: optionalToPtr(p.properties.My_string.Get(ctx)),
898 my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)),
899 my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)),
900 replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)),
Cole Faust60f6bb22024-04-30 13:58:55 -0700901 my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool,
902 my_nonconfigurable_string: p.properties.My_nonconfigurable_string,
903 my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
Cole Faust5a231bd2024-02-07 09:43:59 -0800904 })
905}
906
907func newSelectsMockModule() Module {
908 m := &selectsMockModule{}
909 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700910 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800911 InitDefaultableModule(m)
912 return m
913}
Cole Faust02dd6e52024-04-03 17:04:57 -0700914
915type selectsMockModuleDefaults struct {
916 ModuleBase
917 DefaultsModuleBase
918}
919
920func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
921}
922
923func newSelectsMockModuleDefaults() Module {
924 module := &selectsMockModuleDefaults{}
925
926 module.AddProperties(
927 &selectsMockModuleProperties{},
928 )
929
930 InitDefaultsModule(module)
931
932 return module
933}