blob: bfaabd1eb1796506eae69dbe4e1fdbad093599a4 [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 {
Cole Faust46f6e2f2024-06-20 12:57:43 -070028 name string
29 bp string
30 provider selectsTestProvider
31 providers map[string]selectsTestProvider
32 vendorVars map[string]map[string]string
33 vendorVarTypes map[string]map[string]string
34 expectedError string
Cole Faust5a231bd2024-02-07 09:43:59 -080035 }{
36 {
37 name: "basic string list",
38 bp: `
39 my_module_type {
40 name: "foo",
41 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
42 "a": ["a.cpp"],
43 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -070044 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -080045 }),
46 }
47 `,
48 provider: selectsTestProvider{
49 my_string_list: &[]string{"c.cpp"},
50 },
51 },
52 {
53 name: "basic string",
54 bp: `
55 my_module_type {
56 name: "foo",
57 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
58 "a": "a.cpp",
59 "b": "b.cpp",
Cole Faust683316a2024-04-02 16:45:54 -070060 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -080061 }),
62 }
63 `,
64 provider: selectsTestProvider{
65 my_string: proptools.StringPtr("c.cpp"),
66 },
67 },
68 {
69 name: "basic bool",
70 bp: `
71 my_module_type {
72 name: "foo",
73 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
74 "a": true,
75 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -070076 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -080077 }),
78 }
79 `,
80 provider: selectsTestProvider{
81 my_bool: proptools.BoolPtr(true),
82 },
83 },
84 {
Cole Faustbdd8aee2024-03-14 14:33:02 -070085 name: "basic paths",
86 bp: `
87 my_module_type {
88 name: "foo",
89 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
90 "a": ["foo.txt"],
91 "b": ["bar.txt"],
Cole Faust683316a2024-04-02 16:45:54 -070092 default: ["baz.txt"],
Cole Faustbdd8aee2024-03-14 14:33:02 -070093 }),
94 }
95 `,
96 provider: selectsTestProvider{
97 my_paths: &[]string{"baz.txt"},
98 },
99 },
100 {
Cole Faustba483662024-06-17 15:03:33 -0700101 name: "Expression in select",
102 bp: `
103 my_module_type {
104 name: "foo",
105 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
106 "a": "foo" + "bar",
107 default: "baz",
108 }),
109 }
110 `,
111 provider: selectsTestProvider{
112 my_string: proptools.StringPtr("foobar"),
113 },
114 vendorVars: map[string]map[string]string{
115 "my_namespace": {
116 "my_variable": "a",
117 },
118 },
119 },
120 {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700121 name: "paths with module references",
122 bp: `
123 my_module_type {
124 name: "foo",
125 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
126 "a": [":a"],
127 "b": [":b"],
Cole Faust683316a2024-04-02 16:45:54 -0700128 default: [":c"],
Cole Faustbdd8aee2024-03-14 14:33:02 -0700129 }),
130 }
131 `,
132 expectedError: `"foo" depends on undefined module "c"`,
133 },
134 {
Cole Faust12c8ed42024-03-28 16:26:59 -0700135 name: "Select type doesn't match property type",
136 bp: `
137 my_module_type {
138 name: "foo",
139 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
140 "a": false,
141 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700142 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700143 }),
144 }
145 `,
Cole Faustba483662024-06-17 15:03:33 -0700146 expectedError: `can't assign bool value to string property`,
Cole Faust5a231bd2024-02-07 09:43:59 -0800147 },
148 {
149 name: "String list non-default",
150 bp: `
151 my_module_type {
152 name: "foo",
153 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
154 "a": ["a.cpp"],
155 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700156 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800157 }),
158 }
159 `,
160 provider: selectsTestProvider{
161 my_string_list: &[]string{"a.cpp"},
162 },
163 vendorVars: map[string]map[string]string{
164 "my_namespace": {
165 "my_variable": "a",
166 },
167 },
168 },
169 {
170 name: "String list append",
171 bp: `
172 my_module_type {
173 name: "foo",
174 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
175 "a": ["a.cpp"],
176 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700177 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800178 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
179 "a2": ["a2.cpp"],
180 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700181 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800182 }),
183 }
184 `,
185 provider: selectsTestProvider{
186 my_string_list: &[]string{"a.cpp", "c2.cpp"},
187 },
188 vendorVars: map[string]map[string]string{
189 "my_namespace": {
190 "my_variable": "a",
191 },
192 },
193 },
194 {
195 name: "String list prepend literal",
196 bp: `
197 my_module_type {
198 name: "foo",
199 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
200 "a2": ["a2.cpp"],
201 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700202 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800203 }),
204 }
205 `,
206 provider: selectsTestProvider{
207 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
208 },
209 },
210 {
211 name: "String list append literal",
212 bp: `
213 my_module_type {
214 name: "foo",
215 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
216 "a2": ["a2.cpp"],
217 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700218 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800219 }) + ["literal.cpp"],
220 }
221 `,
222 provider: selectsTestProvider{
223 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
224 },
225 },
226 {
Cole Faust74ef4652024-03-27 16:45:41 -0700227 name: "true + false = true",
Cole Faust5a231bd2024-02-07 09:43:59 -0800228 bp: `
229 my_module_type {
230 name: "foo",
231 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
232 "a": true,
233 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700234 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -0800235 }) + false,
236 }
237 `,
Cole Faust74ef4652024-03-27 16:45:41 -0700238 provider: selectsTestProvider{
239 my_bool: proptools.BoolPtr(true),
240 },
241 },
242 {
243 name: "false + false = false",
244 bp: `
245 my_module_type {
246 name: "foo",
247 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
248 "a": true,
249 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700250 default: true,
Cole Faust74ef4652024-03-27 16:45:41 -0700251 }) + false,
252 }
253 `,
254 vendorVars: map[string]map[string]string{
255 "my_namespace": {
256 "my_variable": "b",
257 },
258 },
259 provider: selectsTestProvider{
260 my_bool: proptools.BoolPtr(false),
261 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800262 },
263 {
264 name: "Append string",
265 bp: `
266 my_module_type {
267 name: "foo",
268 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
269 "a": "a",
270 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700271 default: "c",
Cole Faust5a231bd2024-02-07 09:43:59 -0800272 }) + ".cpp",
273 }
274 `,
275 provider: selectsTestProvider{
276 my_string: proptools.StringPtr("c.cpp"),
277 },
278 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700279 {
Cole Faustfc57d402024-04-11 12:09:44 -0700280 name: "Select on arch",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700281 bp: `
282 my_module_type {
283 name: "foo",
Cole Faustfc57d402024-04-11 12:09:44 -0700284 my_string: select(arch(), {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700285 "x86": "my_x86",
286 "x86_64": "my_x86_64",
287 "arm": "my_arm",
288 "arm64": "my_arm64",
Cole Faust683316a2024-04-02 16:45:54 -0700289 default: "my_default",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700290 }),
291 }
292 `,
293 provider: selectsTestProvider{
294 my_string: proptools.StringPtr("my_arm64"),
295 },
296 },
Cole Faust12c8ed42024-03-28 16:26:59 -0700297 {
Cole Faustfc57d402024-04-11 12:09:44 -0700298 name: "Select on os",
299 bp: `
300 my_module_type {
301 name: "foo",
302 my_string: select(os(), {
303 "android": "my_android",
304 "linux": "my_linux",
305 default: "my_default",
306 }),
307 }
308 `,
309 provider: selectsTestProvider{
310 my_string: proptools.StringPtr("my_android"),
311 },
312 },
313 {
Cole Faust12c8ed42024-03-28 16:26:59 -0700314 name: "Unset value",
315 bp: `
316 my_module_type {
317 name: "foo",
318 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
319 "a": unset,
320 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700321 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700322 })
323 }
324 `,
325 vendorVars: map[string]map[string]string{
326 "my_namespace": {
327 "my_variable": "a",
328 },
329 },
330 provider: selectsTestProvider{},
331 },
332 {
333 name: "Unset value on different branch",
334 bp: `
335 my_module_type {
336 name: "foo",
337 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
338 "a": unset,
339 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700340 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700341 })
342 }
343 `,
344 provider: selectsTestProvider{
345 my_string: proptools.StringPtr("c"),
346 },
347 },
348 {
349 name: "unset + unset = unset",
350 bp: `
351 my_module_type {
352 name: "foo",
353 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700354 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700355 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700356 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700357 "baz": "qux",
Cole Faust683316a2024-04-02 16:45:54 -0700358 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700359 })
360 }
361 `,
362 provider: selectsTestProvider{},
363 },
364 {
365 name: "unset + string = string",
366 bp: `
367 my_module_type {
368 name: "foo",
369 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700370 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700371 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700372 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700373 default: "a",
Cole Faust12c8ed42024-03-28 16:26:59 -0700374 })
375 }
376 `,
377 provider: selectsTestProvider{
378 my_string: proptools.StringPtr("a"),
379 },
380 },
381 {
382 name: "unset + bool = bool",
383 bp: `
384 my_module_type {
385 name: "foo",
386 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
387 "a": true,
Cole Faust683316a2024-04-02 16:45:54 -0700388 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700389 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700390 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700391 })
392 }
393 `,
394 provider: selectsTestProvider{
395 my_bool: proptools.BoolPtr(true),
396 },
397 },
Cole Faust02dd6e52024-04-03 17:04:57 -0700398 {
399 name: "defaults with lists are appended",
400 bp: `
401 my_module_type {
402 name: "foo",
403 defaults: ["bar"],
404 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
405 "a": ["a1"],
406 default: ["b1"],
407 }),
408 }
409 my_defaults {
410 name: "bar",
411 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
412 "a": ["a2"],
413 default: ["b2"],
414 }),
415 }
416 `,
417 provider: selectsTestProvider{
418 my_string_list: &[]string{"b2", "b1"},
419 },
420 },
421 {
Cole Faust69349462024-04-25 16:02:15 -0700422 name: "defaults applied to multiple modules",
423 bp: `
424 my_module_type {
425 name: "foo2",
426 defaults: ["bar"],
427 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
428 "a": ["a1"],
429 default: ["b1"],
430 }),
431 }
432 my_module_type {
433 name: "foo",
434 defaults: ["bar"],
435 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
436 "a": ["a1"],
437 default: ["b1"],
438 }),
439 }
440 my_defaults {
441 name: "bar",
442 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
443 "a": ["a2"],
444 default: ["b2"],
445 }),
446 }
447 `,
448 providers: map[string]selectsTestProvider{
449 "foo": {
450 my_string_list: &[]string{"b2", "b1"},
451 },
452 "foo2": {
453 my_string_list: &[]string{"b2", "b1"},
454 },
455 },
456 },
457 {
Cole Faust02dd6e52024-04-03 17:04:57 -0700458 name: "Replacing string list",
459 bp: `
460 my_module_type {
461 name: "foo",
462 defaults: ["bar"],
463 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
464 "a": ["a1"],
465 default: ["b1"],
466 }),
467 }
468 my_defaults {
469 name: "bar",
470 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
471 "a": ["a2"],
472 default: ["b2"],
473 }),
474 }
475 `,
476 provider: selectsTestProvider{
477 replacing_string_list: &[]string{"b1"},
478 },
479 },
Cole Faustfdbf5d42024-04-10 15:01:23 -0700480 {
481 name: "Multi-condition string 1",
482 bp: `
483 my_module_type {
484 name: "foo",
485 my_string: select((
486 soong_config_variable("my_namespace", "my_variable"),
487 soong_config_variable("my_namespace", "my_variable2"),
488 ), {
489 ("a", "b"): "a+b",
490 ("a", default): "a+default",
491 (default, default): "default",
492 }),
493 }
494 `,
495 vendorVars: map[string]map[string]string{
496 "my_namespace": {
497 "my_variable": "a",
498 "my_variable2": "b",
499 },
500 },
501 provider: selectsTestProvider{
502 my_string: proptools.StringPtr("a+b"),
503 },
504 },
505 {
506 name: "Multi-condition string 2",
507 bp: `
508 my_module_type {
509 name: "foo",
510 my_string: select((
511 soong_config_variable("my_namespace", "my_variable"),
512 soong_config_variable("my_namespace", "my_variable2"),
513 ), {
514 ("a", "b"): "a+b",
515 ("a", default): "a+default",
516 (default, default): "default",
517 }),
518 }
519 `,
520 vendorVars: map[string]map[string]string{
521 "my_namespace": {
522 "my_variable": "a",
523 "my_variable2": "c",
524 },
525 },
526 provider: selectsTestProvider{
527 my_string: proptools.StringPtr("a+default"),
528 },
529 },
530 {
531 name: "Multi-condition string 3",
532 bp: `
533 my_module_type {
534 name: "foo",
535 my_string: select((
536 soong_config_variable("my_namespace", "my_variable"),
537 soong_config_variable("my_namespace", "my_variable2"),
538 ), {
539 ("a", "b"): "a+b",
540 ("a", default): "a+default",
541 (default, default): "default",
542 }),
543 }
544 `,
545 vendorVars: map[string]map[string]string{
546 "my_namespace": {
547 "my_variable": "c",
548 "my_variable2": "b",
549 },
550 },
551 provider: selectsTestProvider{
552 my_string: proptools.StringPtr("default"),
553 },
554 },
555 {
Cole Faustb81dc0e2024-05-09 15:51:52 -0700556 name: "Unhandled string value",
557 bp: `
558 my_module_type {
559 name: "foo",
560 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
561 "foo": "a",
562 "bar": "b",
563 }),
564 }
565 `,
566 vendorVars: map[string]map[string]string{
567 "my_namespace": {
568 "my_variable": "baz",
569 },
570 },
571 expectedError: `my_string: soong_config_variable\("my_namespace", "my_variable"\) had value "baz", which was not handled by the select statement`,
572 },
573 {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700574 name: "Select on boolean",
575 bp: `
576 my_module_type {
577 name: "foo",
578 my_string: select(boolean_var_for_testing(), {
579 true: "t",
580 false: "f",
581 }),
582 }
583 `,
584 vendorVars: map[string]map[string]string{
585 "boolean_var": {
586 "for_testing": "true",
587 },
588 },
589 provider: selectsTestProvider{
590 my_string: proptools.StringPtr("t"),
591 },
592 },
593 {
Cole Faust46f6e2f2024-06-20 12:57:43 -0700594 name: "Select on boolean soong config variable",
595 bp: `
596 my_module_type {
597 name: "foo",
598 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
599 true: "t",
600 false: "f",
601 }),
602 }
603 `,
604 vendorVars: map[string]map[string]string{
605 "my_namespace": {
606 "my_variable": "true",
607 },
608 },
609 vendorVarTypes: map[string]map[string]string{
610 "my_namespace": {
611 "my_variable": "bool",
612 },
613 },
614 provider: selectsTestProvider{
615 my_string: proptools.StringPtr("t"),
616 },
617 },
618 {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700619 name: "Select on boolean false",
620 bp: `
621 my_module_type {
622 name: "foo",
623 my_string: select(boolean_var_for_testing(), {
624 true: "t",
625 false: "f",
626 }),
627 }
628 `,
629 vendorVars: map[string]map[string]string{
630 "boolean_var": {
631 "for_testing": "false",
632 },
633 },
634 provider: selectsTestProvider{
635 my_string: proptools.StringPtr("f"),
636 },
637 },
638 {
639 name: "Select on boolean undefined",
640 bp: `
641 my_module_type {
642 name: "foo",
643 my_string: select(boolean_var_for_testing(), {
644 true: "t",
645 false: "f",
646 }),
647 }
648 `,
Cole Faustb81dc0e2024-05-09 15:51:52 -0700649 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 -0700650 },
651 {
652 name: "Select on boolean undefined with default",
653 bp: `
654 my_module_type {
655 name: "foo",
656 my_string: select(boolean_var_for_testing(), {
657 true: "t",
658 false: "f",
659 default: "default",
660 }),
661 }
662 `,
663 provider: selectsTestProvider{
664 my_string: proptools.StringPtr("default"),
665 },
666 },
667 {
668 name: "Mismatched condition types",
669 bp: `
670 my_module_type {
671 name: "foo",
672 my_string: select(boolean_var_for_testing(), {
673 "true": "t",
674 "false": "f",
675 default: "default",
676 }),
677 }
678 `,
679 vendorVars: map[string]map[string]string{
680 "boolean_var": {
681 "for_testing": "false",
682 },
683 },
684 expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
685 },
Cole Faust60f6bb22024-04-30 13:58:55 -0700686 {
687 name: "Assigning select to nonconfigurable bool",
688 bp: `
689 my_module_type {
690 name: "foo",
691 my_nonconfigurable_bool: select(arch(), {
692 "x86_64": true,
693 default: false,
694 }),
695 }
696 `,
697 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
698 },
699 {
700 name: "Assigning select to nonconfigurable string",
701 bp: `
702 my_module_type {
703 name: "foo",
704 my_nonconfigurable_string: select(arch(), {
705 "x86_64": "x86!",
706 default: "unknown!",
707 }),
708 }
709 `,
710 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
711 },
712 {
713 name: "Assigning appended selects to nonconfigurable string",
714 bp: `
715 my_module_type {
716 name: "foo",
717 my_nonconfigurable_string: select(arch(), {
718 "x86_64": "x86!",
719 default: "unknown!",
720 }) + select(os(), {
721 "darwin": "_darwin!",
722 default: "unknown!",
723 }),
724 }
725 `,
726 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
727 },
728 {
729 name: "Assigning select to nonconfigurable string list",
730 bp: `
731 my_module_type {
732 name: "foo",
733 my_nonconfigurable_string_list: select(arch(), {
734 "x86_64": ["foo", "bar"],
735 default: ["baz", "qux"],
736 }),
737 }
738 `,
739 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
740 },
Cole Faustb9519092024-05-21 11:20:15 -0700741 {
742 name: "Select in variable",
743 bp: `
744 my_second_variable = ["after.cpp"]
745 my_variable = select(soong_config_variable("my_namespace", "my_variable"), {
746 "a": ["a.cpp"],
747 "b": ["b.cpp"],
748 default: ["c.cpp"],
749 }) + my_second_variable
750 my_module_type {
751 name: "foo",
752 my_string_list: ["before.cpp"] + my_variable,
753 }
754 `,
755 provider: selectsTestProvider{
756 my_string_list: &[]string{"before.cpp", "a.cpp", "after.cpp"},
757 },
758 vendorVars: map[string]map[string]string{
759 "my_namespace": {
760 "my_variable": "a",
761 },
762 },
763 },
Cole Faust5f297062024-05-22 14:30:16 -0700764 {
765 name: "Soong config value variable on configurable property",
766 bp: `
767 soong_config_module_type {
768 name: "soong_config_my_module_type",
769 module_type: "my_module_type",
770 config_namespace: "my_namespace",
771 value_variables: ["my_variable"],
772 properties: ["my_string", "my_string_list"],
773 }
774
775 soong_config_my_module_type {
776 name: "foo",
777 my_string_list: ["before.cpp"],
778 soong_config_variables: {
779 my_variable: {
780 my_string_list: ["after_%s.cpp"],
781 my_string: "%s.cpp",
782 },
783 },
784 }
785 `,
786 provider: selectsTestProvider{
787 my_string: proptools.StringPtr("foo.cpp"),
788 my_string_list: &[]string{"before.cpp", "after_foo.cpp"},
789 },
790 vendorVars: map[string]map[string]string{
791 "my_namespace": {
792 "my_variable": "foo",
793 },
794 },
795 },
Cole Faustaeecb752024-05-22 13:41:35 -0700796 {
797 name: "Property appending with variable",
798 bp: `
799 my_variable = ["b.cpp"]
800 my_module_type {
801 name: "foo",
802 my_string_list: ["a.cpp"] + my_variable + select(soong_config_variable("my_namespace", "my_variable"), {
803 "a": ["a.cpp"],
804 "b": ["b.cpp"],
805 default: ["c.cpp"],
806 }),
807 }
808 `,
809 provider: selectsTestProvider{
810 my_string_list: &[]string{"a.cpp", "b.cpp", "c.cpp"},
811 },
812 },
Cole Faustfee6fde2024-06-13 15:35:17 -0700813 {
814 name: "Test AppendSimpleValue",
815 bp: `
816 my_module_type {
817 name: "foo",
818 my_string_list: ["a.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
819 "a": ["a.cpp"],
820 "b": ["b.cpp"],
821 default: ["c.cpp"],
822 }),
823 }
824 `,
825 vendorVars: map[string]map[string]string{
826 "selects_test": {
827 "append_to_string_list": "foo.cpp",
828 },
829 },
830 provider: selectsTestProvider{
831 my_string_list: &[]string{"a.cpp", "c.cpp", "foo.cpp"},
832 },
833 },
Cole Faustba483662024-06-17 15:03:33 -0700834 {
835 name: "Arch variant bool",
836 bp: `
837 my_variable = ["b.cpp"]
838 my_module_type {
839 name: "foo",
840 arch_variant_configurable_bool: false,
841 target: {
842 bionic_arm64: {
843 enabled: true,
844 },
845 },
846 }
847 `,
848 provider: selectsTestProvider{
849 arch_variant_configurable_bool: proptools.BoolPtr(false),
850 },
851 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800852 }
853
854 for _, tc := range testCases {
855 t.Run(tc.name, func(t *testing.T) {
856 fixtures := GroupFixturePreparers(
Cole Faust02dd6e52024-04-03 17:04:57 -0700857 PrepareForTestWithDefaults,
Cole Faust0aa21cc2024-03-20 12:28:03 -0700858 PrepareForTestWithArchMutator,
Cole Faust5f297062024-05-22 14:30:16 -0700859 PrepareForTestWithSoongConfigModuleBuildComponents,
Cole Faust5a231bd2024-02-07 09:43:59 -0800860 FixtureRegisterWithContext(func(ctx RegistrationContext) {
861 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
Cole Faust02dd6e52024-04-03 17:04:57 -0700862 ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults)
Cole Faust5a231bd2024-02-07 09:43:59 -0800863 }),
864 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
865 variables.VendorVars = tc.vendorVars
Cole Faust46f6e2f2024-06-20 12:57:43 -0700866 variables.VendorVarTypes = tc.vendorVarTypes
Cole Faust5a231bd2024-02-07 09:43:59 -0800867 }),
868 )
869 if tc.expectedError != "" {
870 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
871 }
872 result := fixtures.RunTestWithBp(t, tc.bp)
873
874 if tc.expectedError == "" {
Cole Faust69349462024-04-25 16:02:15 -0700875 if len(tc.providers) == 0 {
876 tc.providers = map[string]selectsTestProvider{
877 "foo": tc.provider,
878 }
879 }
880
881 for moduleName := range tc.providers {
882 expected := tc.providers[moduleName]
883 m := result.ModuleForTests(moduleName, "android_arm64_armv8-a")
884 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
885 if !reflect.DeepEqual(p, expected) {
886 t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String())
887 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800888 }
889 }
890 })
891 }
892}
893
894type selectsTestProvider struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700895 my_bool *bool
896 my_string *string
897 my_string_list *[]string
898 my_paths *[]string
899 replacing_string_list *[]string
Cole Faustba483662024-06-17 15:03:33 -0700900 arch_variant_configurable_bool *bool
Cole Faust60f6bb22024-04-30 13:58:55 -0700901 my_nonconfigurable_bool *bool
902 my_nonconfigurable_string *string
903 my_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800904}
905
906func (p *selectsTestProvider) String() string {
907 myBoolStr := "nil"
908 if p.my_bool != nil {
909 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
910 }
911 myStringStr := "nil"
912 if p.my_string != nil {
913 myStringStr = *p.my_string
914 }
Cole Faust60f6bb22024-04-30 13:58:55 -0700915 myNonconfigurableStringStr := "nil"
Cole Faust5f297062024-05-22 14:30:16 -0700916 if p.my_nonconfigurable_string != nil {
Cole Faust60f6bb22024-04-30 13:58:55 -0700917 myNonconfigurableStringStr = *p.my_nonconfigurable_string
918 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800919 return fmt.Sprintf(`selectsTestProvider {
920 my_bool: %v,
921 my_string: %s,
922 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700923 my_paths: %s,
Cole Faust02dd6e52024-04-03 17:04:57 -0700924 replacing_string_list %s,
Cole Faustba483662024-06-17 15:03:33 -0700925 arch_variant_configurable_bool %v
Cole Faust60f6bb22024-04-30 13:58:55 -0700926 my_nonconfigurable_bool: %v,
927 my_nonconfigurable_string: %s,
928 my_nonconfigurable_string_list: %s,
929}`,
930 myBoolStr,
931 myStringStr,
932 p.my_string_list,
933 p.my_paths,
934 p.replacing_string_list,
Cole Faustba483662024-06-17 15:03:33 -0700935 p.arch_variant_configurable_bool,
Cole Faust60f6bb22024-04-30 13:58:55 -0700936 p.my_nonconfigurable_bool,
937 myNonconfigurableStringStr,
938 p.my_nonconfigurable_string_list,
939 )
Cole Faust5a231bd2024-02-07 09:43:59 -0800940}
941
942var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
943
944type selectsMockModuleProperties struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700945 My_bool proptools.Configurable[bool]
946 My_string proptools.Configurable[string]
947 My_string_list proptools.Configurable[[]string]
948 My_paths proptools.Configurable[[]string] `android:"path"`
949 Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
Cole Faustba483662024-06-17 15:03:33 -0700950 Arch_variant_configurable_bool proptools.Configurable[bool] `android:"replace_instead_of_append,arch_variant"`
Cole Faust60f6bb22024-04-30 13:58:55 -0700951 My_nonconfigurable_bool *bool
952 My_nonconfigurable_string *string
953 My_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800954}
955
956type selectsMockModule struct {
957 ModuleBase
958 DefaultableModuleBase
959 properties selectsMockModuleProperties
960}
961
Cole Faust749eeaa2024-05-21 14:19:05 -0700962func optionalToPtr[T any](o proptools.ConfigurableOptional[T]) *T {
963 if o.IsEmpty() {
964 return nil
965 }
966 x := o.Get()
967 return &x
968}
969
Cole Faust5a231bd2024-02-07 09:43:59 -0800970func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustfee6fde2024-06-13 15:35:17 -0700971 toAppend := ctx.Config().VendorConfig("selects_test").String("append_to_string_list")
972 if toAppend != "" {
973 p.properties.My_string_list.AppendSimpleValue([]string{toAppend})
974 }
Cole Faustbdd8aee2024-03-14 14:33:02 -0700975 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust749eeaa2024-05-21 14:19:05 -0700976 my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)),
977 my_string: optionalToPtr(p.properties.My_string.Get(ctx)),
978 my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)),
979 my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)),
980 replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)),
Cole Faustba483662024-06-17 15:03:33 -0700981 arch_variant_configurable_bool: optionalToPtr(p.properties.Arch_variant_configurable_bool.Get(ctx)),
Cole Faust60f6bb22024-04-30 13:58:55 -0700982 my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool,
983 my_nonconfigurable_string: p.properties.My_nonconfigurable_string,
984 my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
Cole Faust5a231bd2024-02-07 09:43:59 -0800985 })
986}
987
988func newSelectsMockModule() Module {
989 m := &selectsMockModule{}
990 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700991 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800992 InitDefaultableModule(m)
993 return m
994}
Cole Faust02dd6e52024-04-03 17:04:57 -0700995
996type selectsMockModuleDefaults struct {
997 ModuleBase
998 DefaultsModuleBase
999}
1000
1001func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
1002}
1003
1004func newSelectsMockModuleDefaults() Module {
1005 module := &selectsMockModuleDefaults{}
1006
1007 module.AddProperties(
1008 &selectsMockModuleProperties{},
1009 )
1010
1011 InitDefaultsModule(module)
1012
1013 return module
1014}