blob: e59b3e65dde33f9a2a7365bd0c9dd50da7f3885e [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
31 vendorVars map[string]map[string]string
32 expectedError string
33 }{
34 {
35 name: "basic string list",
36 bp: `
37 my_module_type {
38 name: "foo",
39 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
40 "a": ["a.cpp"],
41 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -070042 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -080043 }),
44 }
45 `,
46 provider: selectsTestProvider{
47 my_string_list: &[]string{"c.cpp"},
48 },
49 },
50 {
51 name: "basic string",
52 bp: `
53 my_module_type {
54 name: "foo",
55 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
56 "a": "a.cpp",
57 "b": "b.cpp",
Cole Faust683316a2024-04-02 16:45:54 -070058 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -080059 }),
60 }
61 `,
62 provider: selectsTestProvider{
63 my_string: proptools.StringPtr("c.cpp"),
64 },
65 },
66 {
67 name: "basic bool",
68 bp: `
69 my_module_type {
70 name: "foo",
71 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
72 "a": true,
73 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -070074 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -080075 }),
76 }
77 `,
78 provider: selectsTestProvider{
79 my_bool: proptools.BoolPtr(true),
80 },
81 },
82 {
Cole Faustbdd8aee2024-03-14 14:33:02 -070083 name: "basic paths",
84 bp: `
85 my_module_type {
86 name: "foo",
87 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
88 "a": ["foo.txt"],
89 "b": ["bar.txt"],
Cole Faust683316a2024-04-02 16:45:54 -070090 default: ["baz.txt"],
Cole Faustbdd8aee2024-03-14 14:33:02 -070091 }),
92 }
93 `,
94 provider: selectsTestProvider{
95 my_paths: &[]string{"baz.txt"},
96 },
97 },
98 {
99 name: "paths with module references",
100 bp: `
101 my_module_type {
102 name: "foo",
103 my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
104 "a": [":a"],
105 "b": [":b"],
Cole Faust683316a2024-04-02 16:45:54 -0700106 default: [":c"],
Cole Faustbdd8aee2024-03-14 14:33:02 -0700107 }),
108 }
109 `,
110 expectedError: `"foo" depends on undefined module "c"`,
111 },
112 {
Cole Faust5a231bd2024-02-07 09:43:59 -0800113 name: "Differing types",
114 bp: `
115 my_module_type {
116 name: "foo",
117 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
118 "a": "a.cpp",
119 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700120 default: "c.cpp",
Cole Faust5a231bd2024-02-07 09:43:59 -0800121 }),
122 }
123 `,
Cole Faust12c8ed42024-03-28 16:26:59 -0700124 expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`,
125 },
126 {
127 name: "Select type doesn't match property type",
128 bp: `
129 my_module_type {
130 name: "foo",
131 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
132 "a": false,
133 "b": true,
Cole Faust683316a2024-04-02 16:45:54 -0700134 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700135 }),
136 }
137 `,
138 expectedError: `can't assign bool value to string property "my_string\[0\]"`,
Cole Faust5a231bd2024-02-07 09:43:59 -0800139 },
140 {
141 name: "String list non-default",
142 bp: `
143 my_module_type {
144 name: "foo",
145 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
146 "a": ["a.cpp"],
147 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700148 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800149 }),
150 }
151 `,
152 provider: selectsTestProvider{
153 my_string_list: &[]string{"a.cpp"},
154 },
155 vendorVars: map[string]map[string]string{
156 "my_namespace": {
157 "my_variable": "a",
158 },
159 },
160 },
161 {
162 name: "String list append",
163 bp: `
164 my_module_type {
165 name: "foo",
166 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
167 "a": ["a.cpp"],
168 "b": ["b.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700169 default: ["c.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800170 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
171 "a2": ["a2.cpp"],
172 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700173 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800174 }),
175 }
176 `,
177 provider: selectsTestProvider{
178 my_string_list: &[]string{"a.cpp", "c2.cpp"},
179 },
180 vendorVars: map[string]map[string]string{
181 "my_namespace": {
182 "my_variable": "a",
183 },
184 },
185 },
186 {
187 name: "String list prepend literal",
188 bp: `
189 my_module_type {
190 name: "foo",
191 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
192 "a2": ["a2.cpp"],
193 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700194 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800195 }),
196 }
197 `,
198 provider: selectsTestProvider{
199 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
200 },
201 },
202 {
203 name: "String list append literal",
204 bp: `
205 my_module_type {
206 name: "foo",
207 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
208 "a2": ["a2.cpp"],
209 "b2": ["b2.cpp"],
Cole Faust683316a2024-04-02 16:45:54 -0700210 default: ["c2.cpp"],
Cole Faust5a231bd2024-02-07 09:43:59 -0800211 }) + ["literal.cpp"],
212 }
213 `,
214 provider: selectsTestProvider{
215 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
216 },
217 },
218 {
Cole Faust74ef4652024-03-27 16:45:41 -0700219 name: "true + false = true",
Cole Faust5a231bd2024-02-07 09:43:59 -0800220 bp: `
221 my_module_type {
222 name: "foo",
223 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
224 "a": true,
225 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700226 default: true,
Cole Faust5a231bd2024-02-07 09:43:59 -0800227 }) + false,
228 }
229 `,
Cole Faust74ef4652024-03-27 16:45:41 -0700230 provider: selectsTestProvider{
231 my_bool: proptools.BoolPtr(true),
232 },
233 },
234 {
235 name: "false + false = false",
236 bp: `
237 my_module_type {
238 name: "foo",
239 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
240 "a": true,
241 "b": false,
Cole Faust683316a2024-04-02 16:45:54 -0700242 default: true,
Cole Faust74ef4652024-03-27 16:45:41 -0700243 }) + false,
244 }
245 `,
246 vendorVars: map[string]map[string]string{
247 "my_namespace": {
248 "my_variable": "b",
249 },
250 },
251 provider: selectsTestProvider{
252 my_bool: proptools.BoolPtr(false),
253 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800254 },
255 {
256 name: "Append string",
257 bp: `
258 my_module_type {
259 name: "foo",
260 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
261 "a": "a",
262 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700263 default: "c",
Cole Faust5a231bd2024-02-07 09:43:59 -0800264 }) + ".cpp",
265 }
266 `,
267 provider: selectsTestProvider{
268 my_string: proptools.StringPtr("c.cpp"),
269 },
270 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700271 {
272 name: "Select on variant",
273 bp: `
274 my_module_type {
275 name: "foo",
276 my_string: select(variant("arch"), {
277 "x86": "my_x86",
278 "x86_64": "my_x86_64",
279 "arm": "my_arm",
280 "arm64": "my_arm64",
Cole Faust683316a2024-04-02 16:45:54 -0700281 default: "my_default",
Cole Faust0aa21cc2024-03-20 12:28:03 -0700282 }),
283 }
284 `,
285 provider: selectsTestProvider{
286 my_string: proptools.StringPtr("my_arm64"),
287 },
288 },
Cole Faust12c8ed42024-03-28 16:26:59 -0700289 {
290 name: "Unset value",
291 bp: `
292 my_module_type {
293 name: "foo",
294 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
295 "a": unset,
296 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700297 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700298 })
299 }
300 `,
301 vendorVars: map[string]map[string]string{
302 "my_namespace": {
303 "my_variable": "a",
304 },
305 },
306 provider: selectsTestProvider{},
307 },
308 {
309 name: "Unset value on different branch",
310 bp: `
311 my_module_type {
312 name: "foo",
313 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
314 "a": unset,
315 "b": "b",
Cole Faust683316a2024-04-02 16:45:54 -0700316 default: "c",
Cole Faust12c8ed42024-03-28 16:26:59 -0700317 })
318 }
319 `,
320 provider: selectsTestProvider{
321 my_string: proptools.StringPtr("c"),
322 },
323 },
324 {
325 name: "unset + unset = unset",
326 bp: `
327 my_module_type {
328 name: "foo",
329 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faust683316a2024-04-02 16:45:54 -0700330 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700331 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700332 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700333 })
334 }
335 `,
336 provider: selectsTestProvider{},
337 },
338 {
339 name: "unset + string = string",
340 bp: `
341 my_module_type {
342 name: "foo",
343 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
Cole Faust683316a2024-04-02 16:45:54 -0700344 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700345 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700346 default: "a",
Cole Faust12c8ed42024-03-28 16:26:59 -0700347 })
348 }
349 `,
350 provider: selectsTestProvider{
351 my_string: proptools.StringPtr("a"),
352 },
353 },
354 {
355 name: "unset + bool = bool",
356 bp: `
357 my_module_type {
358 name: "foo",
359 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
360 "a": true,
Cole Faust683316a2024-04-02 16:45:54 -0700361 default: unset,
Cole Faust12c8ed42024-03-28 16:26:59 -0700362 }) + select(soong_config_variable("my_namespace", "my_variable2"), {
Cole Faust683316a2024-04-02 16:45:54 -0700363 default: true,
Cole Faust12c8ed42024-03-28 16:26:59 -0700364 })
365 }
366 `,
367 provider: selectsTestProvider{
368 my_bool: proptools.BoolPtr(true),
369 },
370 },
Cole Faust02dd6e52024-04-03 17:04:57 -0700371 {
372 name: "defaults with lists are appended",
373 bp: `
374 my_module_type {
375 name: "foo",
376 defaults: ["bar"],
377 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
378 "a": ["a1"],
379 default: ["b1"],
380 }),
381 }
382 my_defaults {
383 name: "bar",
384 my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
385 "a": ["a2"],
386 default: ["b2"],
387 }),
388 }
389 `,
390 provider: selectsTestProvider{
391 my_string_list: &[]string{"b2", "b1"},
392 },
393 },
394 {
395 name: "Replacing string list",
396 bp: `
397 my_module_type {
398 name: "foo",
399 defaults: ["bar"],
400 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
401 "a": ["a1"],
402 default: ["b1"],
403 }),
404 }
405 my_defaults {
406 name: "bar",
407 replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
408 "a": ["a2"],
409 default: ["b2"],
410 }),
411 }
412 `,
413 provider: selectsTestProvider{
414 replacing_string_list: &[]string{"b1"},
415 },
416 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800417 }
418
419 for _, tc := range testCases {
420 t.Run(tc.name, func(t *testing.T) {
421 fixtures := GroupFixturePreparers(
Cole Faust02dd6e52024-04-03 17:04:57 -0700422 PrepareForTestWithDefaults,
Cole Faust0aa21cc2024-03-20 12:28:03 -0700423 PrepareForTestWithArchMutator,
Cole Faust5a231bd2024-02-07 09:43:59 -0800424 FixtureRegisterWithContext(func(ctx RegistrationContext) {
425 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
Cole Faust02dd6e52024-04-03 17:04:57 -0700426 ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults)
Cole Faust5a231bd2024-02-07 09:43:59 -0800427 }),
428 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
429 variables.VendorVars = tc.vendorVars
430 }),
431 )
432 if tc.expectedError != "" {
433 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
434 }
435 result := fixtures.RunTestWithBp(t, tc.bp)
436
437 if tc.expectedError == "" {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700438 m := result.ModuleForTests("foo", "android_arm64_armv8-a")
439 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
Cole Faust5a231bd2024-02-07 09:43:59 -0800440 if !reflect.DeepEqual(p, tc.provider) {
441 t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
442 }
443 }
444 })
445 }
446}
447
448type selectsTestProvider struct {
Cole Faust02dd6e52024-04-03 17:04:57 -0700449 my_bool *bool
450 my_string *string
451 my_string_list *[]string
452 my_paths *[]string
453 replacing_string_list *[]string
Cole Faust5a231bd2024-02-07 09:43:59 -0800454}
455
456func (p *selectsTestProvider) String() string {
457 myBoolStr := "nil"
458 if p.my_bool != nil {
459 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
460 }
461 myStringStr := "nil"
462 if p.my_string != nil {
463 myStringStr = *p.my_string
464 }
465 return fmt.Sprintf(`selectsTestProvider {
466 my_bool: %v,
467 my_string: %s,
468 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700469 my_paths: %s,
Cole Faust02dd6e52024-04-03 17:04:57 -0700470 replacing_string_list %s,
471}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_string_list)
Cole Faust5a231bd2024-02-07 09:43:59 -0800472}
473
474var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
475
476type selectsMockModuleProperties struct {
Cole Faust02dd6e52024-04-03 17:04:57 -0700477 My_bool proptools.Configurable[bool]
478 My_string proptools.Configurable[string]
479 My_string_list proptools.Configurable[[]string]
480 My_paths proptools.Configurable[[]string] `android:"path"`
481 Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
Cole Faust5a231bd2024-02-07 09:43:59 -0800482}
483
484type selectsMockModule struct {
485 ModuleBase
486 DefaultableModuleBase
487 properties selectsMockModuleProperties
488}
489
490func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700491 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faustb78ce432024-04-04 10:55:19 -0700492 my_bool: p.properties.My_bool.Get(ctx),
493 my_string: p.properties.My_string.Get(ctx),
494 my_string_list: p.properties.My_string_list.Get(ctx),
495 my_paths: p.properties.My_paths.Get(ctx),
496 replacing_string_list: p.properties.Replacing_string_list.Get(ctx),
Cole Faust5a231bd2024-02-07 09:43:59 -0800497 })
498}
499
500func newSelectsMockModule() Module {
501 m := &selectsMockModule{}
502 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700503 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800504 InitDefaultableModule(m)
505 return m
506}
Cole Faust02dd6e52024-04-03 17:04:57 -0700507
508type selectsMockModuleDefaults struct {
509 ModuleBase
510 DefaultsModuleBase
511}
512
513func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
514}
515
516func newSelectsMockModuleDefaults() Module {
517 module := &selectsMockModuleDefaults{}
518
519 module.AddProperties(
520 &selectsMockModuleProperties{},
521 )
522
523 InitDefaultsModule(module)
524
525 return module
526}