blob: e2dc4035d244ff3ea7c64af14aab56b71f98f895 [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 {
101 name: "paths with module references",
102 bp: `
103 my_module_type {
104 name: "foo",
105 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
106 "a": [":a"],
107 "b": [":b"],
Cole Faust683316a2024-04-02 16:45:54 -0700108 default: [":c"],
Cole Faustbdd8aee2024-03-14 14:33:02 -0700109 }),
110 }
111 `,
112 expectedError: `"foo" depends on undefined module "c"`,
113 },
114 {
Cole Faust5a231bd2024-02-07 09:43:59 -0800115 name: "Differing types",
116 bp: `
117 my_module_type {
118 name: "foo",
119 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
120 "a": "a.cpp",
121 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700122 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -0800123 }),
124 }
125 `,
Cole Faust12c8ed42024-03-28 16:26:59 -0700126 expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`,
127 },
128 {
129 name: "Select type doesn't match property type",
130 bp: `
131 my_module_type {
132 name: "foo",
133 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
134 "a": false,
135 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700136 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700137 }),
138 }
139 `,
140 expectedError: `can't assign bool value to string property "my_string\[0\]"`,
Cole Faust5a231bd2024-02-07 09:43:59 -0800141 },
142 {
143 name: "String list non-default",
144 bp: `
145 my_module_type {
146 name: "foo",
147 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
148 "a": ["a.cpp"],
149 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700150 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800151 }),
152 }
153 `,
154 provider: selectsTestProvider{
155 my_string_list: &[]string{"a.cpp"},
156 },
157 vendorVars: map[string]map[string]string{
158 "my_namespace": {
159 "my_variable": "a",
160 },
161 },
162 },
163 {
164 name: "String list append",
165 bp: `
166 my_module_type {
167 name: "foo",
168 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
169 "a": ["a.cpp"],
170 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700171 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800172 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
173 "a2": ["a2.cpp"],
174 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700175 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800176 }),
177 }
178 `,
179 provider: selectsTestProvider{
180 my_string_list: &[]string{"a.cpp", "c2.cpp"},
181 },
182 vendorVars: map[string]map[string]string{
183 "my_namespace": {
184 "my_variable": "a",
185 },
186 },
187 },
188 {
189 name: "String list prepend literal",
190 bp: `
191 my_module_type {
192 name: "foo",
193 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
194 "a2": ["a2.cpp"],
195 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700196 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800197 }),
198 }
199 `,
200 provider: selectsTestProvider{
201 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
202 },
203 },
204 {
205 name: "String list append literal",
206 bp: `
207 my_module_type {
208 name: "foo",
209 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
210 "a2": ["a2.cpp"],
211 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700212 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800213 }) + ["literal.cpp"],
214 }
215 `,
216 provider: selectsTestProvider{
217 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
218 },
219 },
220 {
Cole Faust74ef4652024-03-27 16:45:41 -0700221 name: "true + false = true",
Cole Faust5a231bd2024-02-07 09:43:59 -0800222 bp: `
223 my_module_type {
224 name: "foo",
225 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
226 "a": true,
227 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700228 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -0800229 }) + false,
230 }
231 `,
Cole Faust74ef4652024-03-27 16:45:41 -0700232 provider: selectsTestProvider{
233 my_bool: proptools.BoolPtr(true),
234 },
235 },
236 {
237 name: "false + false = false",
238 bp: `
239 my_module_type {
240 name: "foo",
241 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
242 "a": true,
243 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700244 default: true,
Cole Faust74ef4652024-03-27 16:45:41 -0700245 }) + false,
246 }
247 `,
248 vendorVars: map[string]map[string]string{
249 "my_namespace": {
250 "my_variable": "b",
251 },
252 },
253 provider: selectsTestProvider{
254 my_bool: proptools.BoolPtr(false),
255 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800256 },
257 {
258 name: "Append string",
259 bp: `
260 my_module_type {
261 name: "foo",
262 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
263 "a": "a",
264 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700265 default: "c",
Cole Faust5a231bd2024-02-07 09:43:59 -0800266 }) + ".cpp",
267 }
268 `,
269 provider: selectsTestProvider{
270 my_string: proptools.StringPtr("c.cpp"),
271 },
272 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700273 {
Cole Faustfc57d402024-04-11 12:09:44 -0700274 name: "Select on arch",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700275 bp: `
276 my_module_type {
277 name: "foo",
Cole Faustfc57d402024-04-11 12:09:44 -0700278 my_string: select(arch(), {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700279 "x86": "my_x86",
280 "x86_64": "my_x86_64",
281 "arm": "my_arm",
282 "arm64": "my_arm64",
Cole Faust683316a2024-04-02 16:45:54 -0700283 default: "my_default",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700284 }),
285 }
286 `,
287 provider: selectsTestProvider{
288 my_string: proptools.StringPtr("my_arm64"),
289 },
290 },
Cole Faust12c8ed42024-03-28 16:26:59 -0700291 {
Cole Faustfc57d402024-04-11 12:09:44 -0700292 name: "Select on os",
293 bp: `
294 my_module_type {
295 name: "foo",
296 my_string: select(os(), {
297 "android": "my_android",
298 "linux": "my_linux",
299 default: "my_default",
300 }),
301 }
302 `,
303 provider: selectsTestProvider{
304 my_string: proptools.StringPtr("my_android"),
305 },
306 },
307 {
Cole Faust12c8ed42024-03-28 16:26:59 -0700308 name: "Unset value",
309 bp: `
310 my_module_type {
311 name: "foo",
312 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
313 "a": unset,
314 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700315 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700316 })
317 }
318 `,
319 vendorVars: map[string]map[string]string{
320 "my_namespace": {
321 "my_variable": "a",
322 },
323 },
324 provider: selectsTestProvider{},
325 },
326 {
327 name: "Unset value on different branch",
328 bp: `
329 my_module_type {
330 name: "foo",
331 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
332 "a": unset,
333 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700334 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700335 })
336 }
337 `,
338 provider: selectsTestProvider{
339 my_string: proptools.StringPtr("c"),
340 },
341 },
342 {
343 name: "unset + unset = unset",
344 bp: `
345 my_module_type {
346 name: "foo",
347 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700348 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700349 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700350 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700351 "baz": "qux",
Cole Faust683316a2024-04-02 16:45:54 -0700352 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700353 })
354 }
355 `,
356 provider: selectsTestProvider{},
357 },
358 {
359 name: "unset + string = string",
360 bp: `
361 my_module_type {
362 name: "foo",
363 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700364 "foo": "bar",
Cole Faust683316a2024-04-02 16:45:54 -0700365 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700366 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700367 default: "a",
Cole Faust12c8ed42024-03-28 16:26:59 -0700368 })
369 }
370 `,
371 provider: selectsTestProvider{
372 my_string: proptools.StringPtr("a"),
373 },
374 },
375 {
376 name: "unset + bool = bool",
377 bp: `
378 my_module_type {
379 name: "foo",
380 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
381 "a": true,
Cole Faust683316a2024-04-02 16:45:54 -0700382 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700383 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700384 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700385 })
386 }
387 `,
388 provider: selectsTestProvider{
389 my_bool: proptools.BoolPtr(true),
390 },
391 },
Cole Faust02dd6e52024-04-03 17:04:57 -0700392 {
393 name: "defaults with lists are appended",
394 bp: `
395 my_module_type {
396 name: "foo",
397 defaults: ["bar"],
398 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
399 "a": ["a1"],
400 default: ["b1"],
401 }),
402 }
403 my_defaults {
404 name: "bar",
405 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
406 "a": ["a2"],
407 default: ["b2"],
408 }),
409 }
410 `,
411 provider: selectsTestProvider{
412 my_string_list: &[]string{"b2", "b1"},
413 },
414 },
415 {
Cole Faust69349462024-04-25 16:02:15 -0700416 name: "defaults applied to multiple modules",
417 bp: `
418 my_module_type {
419 name: "foo2",
420 defaults: ["bar"],
421 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
422 "a": ["a1"],
423 default: ["b1"],
424 }),
425 }
426 my_module_type {
427 name: "foo",
428 defaults: ["bar"],
429 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
430 "a": ["a1"],
431 default: ["b1"],
432 }),
433 }
434 my_defaults {
435 name: "bar",
436 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
437 "a": ["a2"],
438 default: ["b2"],
439 }),
440 }
441 `,
442 providers: map[string]selectsTestProvider{
443 "foo": {
444 my_string_list: &[]string{"b2", "b1"},
445 },
446 "foo2": {
447 my_string_list: &[]string{"b2", "b1"},
448 },
449 },
450 },
451 {
Cole Faust02dd6e52024-04-03 17:04:57 -0700452 name: "Replacing string list",
453 bp: `
454 my_module_type {
455 name: "foo",
456 defaults: ["bar"],
457 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
458 "a": ["a1"],
459 default: ["b1"],
460 }),
461 }
462 my_defaults {
463 name: "bar",
464 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
465 "a": ["a2"],
466 default: ["b2"],
467 }),
468 }
469 `,
470 provider: selectsTestProvider{
471 replacing_string_list: &[]string{"b1"},
472 },
473 },
Cole Faustfdbf5d42024-04-10 15:01:23 -0700474 {
475 name: "Multi-condition string 1",
476 bp: `
477 my_module_type {
478 name: "foo",
479 my_string: select((
480 soong_config_variable("my_namespace", "my_variable"),
481 soong_config_variable("my_namespace", "my_variable2"),
482 ), {
483 ("a", "b"): "a+b",
484 ("a", default): "a+default",
485 (default, default): "default",
486 }),
487 }
488 `,
489 vendorVars: map[string]map[string]string{
490 "my_namespace": {
491 "my_variable": "a",
492 "my_variable2": "b",
493 },
494 },
495 provider: selectsTestProvider{
496 my_string: proptools.StringPtr("a+b"),
497 },
498 },
499 {
500 name: "Multi-condition string 2",
501 bp: `
502 my_module_type {
503 name: "foo",
504 my_string: select((
505 soong_config_variable("my_namespace", "my_variable"),
506 soong_config_variable("my_namespace", "my_variable2"),
507 ), {
508 ("a", "b"): "a+b",
509 ("a", default): "a+default",
510 (default, default): "default",
511 }),
512 }
513 `,
514 vendorVars: map[string]map[string]string{
515 "my_namespace": {
516 "my_variable": "a",
517 "my_variable2": "c",
518 },
519 },
520 provider: selectsTestProvider{
521 my_string: proptools.StringPtr("a+default"),
522 },
523 },
524 {
525 name: "Multi-condition string 3",
526 bp: `
527 my_module_type {
528 name: "foo",
529 my_string: select((
530 soong_config_variable("my_namespace", "my_variable"),
531 soong_config_variable("my_namespace", "my_variable2"),
532 ), {
533 ("a", "b"): "a+b",
534 ("a", default): "a+default",
535 (default, default): "default",
536 }),
537 }
538 `,
539 vendorVars: map[string]map[string]string{
540 "my_namespace": {
541 "my_variable": "c",
542 "my_variable2": "b",
543 },
544 },
545 provider: selectsTestProvider{
546 my_string: proptools.StringPtr("default"),
547 },
548 },
549 {
Cole Faustb81dc0e2024-05-09 15:51:52 -0700550 name: "Unhandled string value",
551 bp: `
552 my_module_type {
553 name: "foo",
554 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
555 "foo": "a",
556 "bar": "b",
557 }),
558 }
559 `,
560 vendorVars: map[string]map[string]string{
561 "my_namespace": {
562 "my_variable": "baz",
563 },
564 },
565 expectedError: `my_string: soong_config_variable\("my_namespace", "my_variable"\) had value "baz", which was not handled by the select statement`,
566 },
567 {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700568 name: "Select on boolean",
569 bp: `
570 my_module_type {
571 name: "foo",
572 my_string: select(boolean_var_for_testing(), {
573 true: "t",
574 false: "f",
575 }),
576 }
577 `,
578 vendorVars: map[string]map[string]string{
579 "boolean_var": {
580 "for_testing": "true",
581 },
582 },
583 provider: selectsTestProvider{
584 my_string: proptools.StringPtr("t"),
585 },
586 },
587 {
Cole Faust46f6e2f2024-06-20 12:57:43 -0700588 name: "Select on boolean soong config variable",
589 bp: `
590 my_module_type {
591 name: "foo",
592 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
593 true: "t",
594 false: "f",
595 }),
596 }
597 `,
598 vendorVars: map[string]map[string]string{
599 "my_namespace": {
600 "my_variable": "true",
601 },
602 },
603 vendorVarTypes: map[string]map[string]string{
604 "my_namespace": {
605 "my_variable": "bool",
606 },
607 },
608 provider: selectsTestProvider{
609 my_string: proptools.StringPtr("t"),
610 },
611 },
612 {
Cole Faustfdbf5d42024-04-10 15:01:23 -0700613 name: "Select on boolean false",
614 bp: `
615 my_module_type {
616 name: "foo",
617 my_string: select(boolean_var_for_testing(), {
618 true: "t",
619 false: "f",
620 }),
621 }
622 `,
623 vendorVars: map[string]map[string]string{
624 "boolean_var": {
625 "for_testing": "false",
626 },
627 },
628 provider: selectsTestProvider{
629 my_string: proptools.StringPtr("f"),
630 },
631 },
632 {
633 name: "Select on boolean undefined",
634 bp: `
635 my_module_type {
636 name: "foo",
637 my_string: select(boolean_var_for_testing(), {
638 true: "t",
639 false: "f",
640 }),
641 }
642 `,
Cole Faustb81dc0e2024-05-09 15:51:52 -0700643 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 -0700644 },
645 {
646 name: "Select on boolean undefined with default",
647 bp: `
648 my_module_type {
649 name: "foo",
650 my_string: select(boolean_var_for_testing(), {
651 true: "t",
652 false: "f",
653 default: "default",
654 }),
655 }
656 `,
657 provider: selectsTestProvider{
658 my_string: proptools.StringPtr("default"),
659 },
660 },
661 {
662 name: "Mismatched condition types",
663 bp: `
664 my_module_type {
665 name: "foo",
666 my_string: select(boolean_var_for_testing(), {
667 "true": "t",
668 "false": "f",
669 default: "default",
670 }),
671 }
672 `,
673 vendorVars: map[string]map[string]string{
674 "boolean_var": {
675 "for_testing": "false",
676 },
677 },
678 expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
679 },
Cole Faust60f6bb22024-04-30 13:58:55 -0700680 {
681 name: "Assigning select to nonconfigurable bool",
682 bp: `
683 my_module_type {
684 name: "foo",
685 my_nonconfigurable_bool: select(arch(), {
686 "x86_64": true,
687 default: false,
688 }),
689 }
690 `,
691 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
692 },
693 {
694 name: "Assigning select to nonconfigurable string",
695 bp: `
696 my_module_type {
697 name: "foo",
698 my_nonconfigurable_string: select(arch(), {
699 "x86_64": "x86!",
700 default: "unknown!",
701 }),
702 }
703 `,
704 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
705 },
706 {
707 name: "Assigning appended selects to nonconfigurable string",
708 bp: `
709 my_module_type {
710 name: "foo",
711 my_nonconfigurable_string: select(arch(), {
712 "x86_64": "x86!",
713 default: "unknown!",
714 }) + select(os(), {
715 "darwin": "_darwin!",
716 default: "unknown!",
717 }),
718 }
719 `,
720 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
721 },
722 {
723 name: "Assigning select to nonconfigurable string list",
724 bp: `
725 my_module_type {
726 name: "foo",
727 my_nonconfigurable_string_list: select(arch(), {
728 "x86_64": ["foo", "bar"],
729 default: ["baz", "qux"],
730 }),
731 }
732 `,
733 expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
734 },
Cole Faustb9519092024-05-21 11:20:15 -0700735 {
736 name: "Select in variable",
737 bp: `
738 my_second_variable = ["after.cpp"]
739 my_variable = select(soong_config_variable("my_namespace", "my_variable"), {
740 "a": ["a.cpp"],
741 "b": ["b.cpp"],
742 default: ["c.cpp"],
743 }) + my_second_variable
744 my_module_type {
745 name: "foo",
746 my_string_list: ["before.cpp"] + my_variable,
747 }
748 `,
749 provider: selectsTestProvider{
750 my_string_list: &[]string{"before.cpp", "a.cpp", "after.cpp"},
751 },
752 vendorVars: map[string]map[string]string{
753 "my_namespace": {
754 "my_variable": "a",
755 },
756 },
757 },
Cole Faust5f297062024-05-22 14:30:16 -0700758 {
759 name: "Soong config value variable on configurable property",
760 bp: `
761 soong_config_module_type {
762 name: "soong_config_my_module_type",
763 module_type: "my_module_type",
764 config_namespace: "my_namespace",
765 value_variables: ["my_variable"],
766 properties: ["my_string", "my_string_list"],
767 }
768
769 soong_config_my_module_type {
770 name: "foo",
771 my_string_list: ["before.cpp"],
772 soong_config_variables: {
773 my_variable: {
774 my_string_list: ["after_%s.cpp"],
775 my_string: "%s.cpp",
776 },
777 },
778 }
779 `,
780 provider: selectsTestProvider{
781 my_string: proptools.StringPtr("foo.cpp"),
782 my_string_list: &[]string{"before.cpp", "after_foo.cpp"},
783 },
784 vendorVars: map[string]map[string]string{
785 "my_namespace": {
786 "my_variable": "foo",
787 },
788 },
789 },
Cole Faustaeecb752024-05-22 13:41:35 -0700790 {
791 name: "Property appending with variable",
792 bp: `
793 my_variable = ["b.cpp"]
794 my_module_type {
795 name: "foo",
796 my_string_list: ["a.cpp"] + my_variable + select(soong_config_variable("my_namespace", "my_variable"), {
797 "a": ["a.cpp"],
798 "b": ["b.cpp"],
799 default: ["c.cpp"],
800 }),
801 }
802 `,
803 provider: selectsTestProvider{
804 my_string_list: &[]string{"a.cpp", "b.cpp", "c.cpp"},
805 },
806 },
Cole Faustfee6fde2024-06-13 15:35:17 -0700807 {
808 name: "Test AppendSimpleValue",
809 bp: `
810 my_module_type {
811 name: "foo",
812 my_string_list: ["a.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
813 "a": ["a.cpp"],
814 "b": ["b.cpp"],
815 default: ["c.cpp"],
816 }),
817 }
818 `,
819 vendorVars: map[string]map[string]string{
820 "selects_test": {
821 "append_to_string_list": "foo.cpp",
822 },
823 },
824 provider: selectsTestProvider{
825 my_string_list: &[]string{"a.cpp", "c.cpp", "foo.cpp"},
826 },
827 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800828 }
829
830 for _, tc := range testCases {
831 t.Run(tc.name, func(t *testing.T) {
832 fixtures := GroupFixturePreparers(
Cole Faust02dd6e52024-04-03 17:04:57 -0700833 PrepareForTestWithDefaults,
Cole Faust0aa21cc2024-03-20 12:28:03 -0700834 PrepareForTestWithArchMutator,
Cole Faust5f297062024-05-22 14:30:16 -0700835 PrepareForTestWithSoongConfigModuleBuildComponents,
Cole Faust5a231bd2024-02-07 09:43:59 -0800836 FixtureRegisterWithContext(func(ctx RegistrationContext) {
837 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
Cole Faust02dd6e52024-04-03 17:04:57 -0700838 ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults)
Cole Faust5a231bd2024-02-07 09:43:59 -0800839 }),
840 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
841 variables.VendorVars = tc.vendorVars
Cole Faust46f6e2f2024-06-20 12:57:43 -0700842 variables.VendorVarTypes = tc.vendorVarTypes
Cole Faust5a231bd2024-02-07 09:43:59 -0800843 }),
844 )
845 if tc.expectedError != "" {
846 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
847 }
848 result := fixtures.RunTestWithBp(t, tc.bp)
849
850 if tc.expectedError == "" {
Cole Faust69349462024-04-25 16:02:15 -0700851 if len(tc.providers) == 0 {
852 tc.providers = map[string]selectsTestProvider{
853 "foo": tc.provider,
854 }
855 }
856
857 for moduleName := range tc.providers {
858 expected := tc.providers[moduleName]
859 m := result.ModuleForTests(moduleName, "android_arm64_armv8-a")
860 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
861 if !reflect.DeepEqual(p, expected) {
862 t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String())
863 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800864 }
865 }
866 })
867 }
868}
869
870type selectsTestProvider struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700871 my_bool *bool
872 my_string *string
873 my_string_list *[]string
874 my_paths *[]string
875 replacing_string_list *[]string
876 my_nonconfigurable_bool *bool
877 my_nonconfigurable_string *string
878 my_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800879}
880
881func (p *selectsTestProvider) String() string {
882 myBoolStr := "nil"
883 if p.my_bool != nil {
884 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
885 }
886 myStringStr := "nil"
887 if p.my_string != nil {
888 myStringStr = *p.my_string
889 }
Cole Faust60f6bb22024-04-30 13:58:55 -0700890 myNonconfigurableStringStr := "nil"
Cole Faust5f297062024-05-22 14:30:16 -0700891 if p.my_nonconfigurable_string != nil {
Cole Faust60f6bb22024-04-30 13:58:55 -0700892 myNonconfigurableStringStr = *p.my_nonconfigurable_string
893 }
Cole Faust5a231bd2024-02-07 09:43:59 -0800894 return fmt.Sprintf(`selectsTestProvider {
895 my_bool: %v,
896 my_string: %s,
897 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700898 my_paths: %s,
Cole Faust02dd6e52024-04-03 17:04:57 -0700899 replacing_string_list %s,
Cole Faust60f6bb22024-04-30 13:58:55 -0700900 my_nonconfigurable_bool: %v,
901 my_nonconfigurable_string: %s,
902 my_nonconfigurable_string_list: %s,
903}`,
904 myBoolStr,
905 myStringStr,
906 p.my_string_list,
907 p.my_paths,
908 p.replacing_string_list,
909 p.my_nonconfigurable_bool,
910 myNonconfigurableStringStr,
911 p.my_nonconfigurable_string_list,
912 )
Cole Faust5a231bd2024-02-07 09:43:59 -0800913}
914
915var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
916
917type selectsMockModuleProperties struct {
Cole Faust60f6bb22024-04-30 13:58:55 -0700918 My_bool proptools.Configurable[bool]
919 My_string proptools.Configurable[string]
920 My_string_list proptools.Configurable[[]string]
921 My_paths proptools.Configurable[[]string] `android:"path"`
922 Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
923 My_nonconfigurable_bool *bool
924 My_nonconfigurable_string *string
925 My_nonconfigurable_string_list []string
Cole Faust5a231bd2024-02-07 09:43:59 -0800926}
927
928type selectsMockModule struct {
929 ModuleBase
930 DefaultableModuleBase
931 properties selectsMockModuleProperties
932}
933
Cole Faust749eeaa2024-05-21 14:19:05 -0700934func optionalToPtr[T any](o proptools.ConfigurableOptional[T]) *T {
935 if o.IsEmpty() {
936 return nil
937 }
938 x := o.Get()
939 return &x
940}
941
Cole Faust5a231bd2024-02-07 09:43:59 -0800942func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustfee6fde2024-06-13 15:35:17 -0700943 toAppend := ctx.Config().VendorConfig("selects_test").String("append_to_string_list")
944 if toAppend != "" {
945 p.properties.My_string_list.AppendSimpleValue([]string{toAppend})
946 }
Cole Faustbdd8aee2024-03-14 14:33:02 -0700947 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust749eeaa2024-05-21 14:19:05 -0700948 my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)),
949 my_string: optionalToPtr(p.properties.My_string.Get(ctx)),
950 my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)),
951 my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)),
952 replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)),
Cole Faust60f6bb22024-04-30 13:58:55 -0700953 my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool,
954 my_nonconfigurable_string: p.properties.My_nonconfigurable_string,
955 my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
Cole Faust5a231bd2024-02-07 09:43:59 -0800956 })
957}
958
959func newSelectsMockModule() Module {
960 m := &selectsMockModule{}
961 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700962 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800963 InitDefaultableModule(m)
964 return m
965}
Cole Faust02dd6e52024-04-03 17:04:57 -0700966
967type selectsMockModuleDefaults struct {
968 ModuleBase
969 DefaultsModuleBase
970}
971
972func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
973}
974
975func newSelectsMockModuleDefaults() Module {
976 module := &selectsMockModuleDefaults{}
977
978 module.AddProperties(
979 &selectsMockModuleProperties{},
980 )
981
982 InitDefaultsModule(module)
983
984 return module
985}