blob: adbe59a70eee7a79617b6003432a2b11e08bcdf0 [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"],
42 _: ["c.cpp"],
43 }),
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",
58 _: "c.cpp",
59 }),
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,
74 _: true,
75 }),
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"],
90 _: ["baz.txt"],
91 }),
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"],
106 _: [":c"],
107 }),
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,
120 _: "c.cpp",
121 }),
122 }
123 `,
124 expectedError: `can't assign bool value to string property "my_string\[1\]"`,
125 },
126 {
127 name: "String list non-default",
128 bp: `
129 my_module_type {
130 name: "foo",
131 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
132 "a": ["a.cpp"],
133 "b": ["b.cpp"],
134 _: ["c.cpp"],
135 }),
136 }
137 `,
138 provider: selectsTestProvider{
139 my_string_list: &[]string{"a.cpp"},
140 },
141 vendorVars: map[string]map[string]string{
142 "my_namespace": {
143 "my_variable": "a",
144 },
145 },
146 },
147 {
148 name: "String list append",
149 bp: `
150 my_module_type {
151 name: "foo",
152 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
153 "a": ["a.cpp"],
154 "b": ["b.cpp"],
155 _: ["c.cpp"],
156 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
157 "a2": ["a2.cpp"],
158 "b2": ["b2.cpp"],
159 _: ["c2.cpp"],
160 }),
161 }
162 `,
163 provider: selectsTestProvider{
164 my_string_list: &[]string{"a.cpp", "c2.cpp"},
165 },
166 vendorVars: map[string]map[string]string{
167 "my_namespace": {
168 "my_variable": "a",
169 },
170 },
171 },
172 {
173 name: "String list prepend literal",
174 bp: `
175 my_module_type {
176 name: "foo",
177 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
178 "a2": ["a2.cpp"],
179 "b2": ["b2.cpp"],
180 _: ["c2.cpp"],
181 }),
182 }
183 `,
184 provider: selectsTestProvider{
185 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
186 },
187 },
188 {
189 name: "String list append literal",
190 bp: `
191 my_module_type {
192 name: "foo",
193 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
194 "a2": ["a2.cpp"],
195 "b2": ["b2.cpp"],
196 _: ["c2.cpp"],
197 }) + ["literal.cpp"],
198 }
199 `,
200 provider: selectsTestProvider{
201 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
202 },
203 },
204 {
Cole Faust74ef4652024-03-27 16:45:41 -0700205 name: "true + false = true",
Cole Faust5a231bd2024-02-07 09:43:59 -0800206 bp: `
207 my_module_type {
208 name: "foo",
209 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
210 "a": true,
211 "b": false,
212 _: true,
213 }) + false,
214 }
215 `,
Cole Faust74ef4652024-03-27 16:45:41 -0700216 provider: selectsTestProvider{
217 my_bool: proptools.BoolPtr(true),
218 },
219 },
220 {
221 name: "false + false = false",
222 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,
228 _: true,
229 }) + false,
230 }
231 `,
232 vendorVars: map[string]map[string]string{
233 "my_namespace": {
234 "my_variable": "b",
235 },
236 },
237 provider: selectsTestProvider{
238 my_bool: proptools.BoolPtr(false),
239 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800240 },
241 {
242 name: "Append string",
243 bp: `
244 my_module_type {
245 name: "foo",
246 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
247 "a": "a",
248 "b": "b",
249 _: "c",
250 }) + ".cpp",
251 }
252 `,
253 provider: selectsTestProvider{
254 my_string: proptools.StringPtr("c.cpp"),
255 },
256 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700257 {
258 name: "Select on variant",
259 bp: `
260 my_module_type {
261 name: "foo",
262 my_string: select(variant("arch"), {
263 "x86": "my_x86",
264 "x86_64": "my_x86_64",
265 "arm": "my_arm",
266 "arm64": "my_arm64",
267 _: "my_default",
268 }),
269 }
270 `,
271 provider: selectsTestProvider{
272 my_string: proptools.StringPtr("my_arm64"),
273 },
274 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800275 }
276
277 for _, tc := range testCases {
278 t.Run(tc.name, func(t *testing.T) {
279 fixtures := GroupFixturePreparers(
Cole Faust0aa21cc2024-03-20 12:28:03 -0700280 PrepareForTestWithArchMutator,
Cole Faust5a231bd2024-02-07 09:43:59 -0800281 FixtureRegisterWithContext(func(ctx RegistrationContext) {
282 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
283 }),
284 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
285 variables.VendorVars = tc.vendorVars
286 }),
287 )
288 if tc.expectedError != "" {
289 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
290 }
291 result := fixtures.RunTestWithBp(t, tc.bp)
292
293 if tc.expectedError == "" {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700294 m := result.ModuleForTests("foo", "android_arm64_armv8-a")
295 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
Cole Faust5a231bd2024-02-07 09:43:59 -0800296 if !reflect.DeepEqual(p, tc.provider) {
297 t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
298 }
299 }
300 })
301 }
302}
303
304type selectsTestProvider struct {
305 my_bool *bool
306 my_string *string
307 my_string_list *[]string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700308 my_paths *[]string
Cole Faust5a231bd2024-02-07 09:43:59 -0800309}
310
311func (p *selectsTestProvider) String() string {
312 myBoolStr := "nil"
313 if p.my_bool != nil {
314 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
315 }
316 myStringStr := "nil"
317 if p.my_string != nil {
318 myStringStr = *p.my_string
319 }
320 return fmt.Sprintf(`selectsTestProvider {
321 my_bool: %v,
322 my_string: %s,
323 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700324 my_paths: %s,
325}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths)
Cole Faust5a231bd2024-02-07 09:43:59 -0800326}
327
328var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
329
330type selectsMockModuleProperties struct {
331 My_bool proptools.Configurable[bool]
332 My_string proptools.Configurable[string]
333 My_string_list proptools.Configurable[[]string]
Cole Faustbdd8aee2024-03-14 14:33:02 -0700334 My_paths proptools.Configurable[[]string] `android:"path"`
Cole Faust5a231bd2024-02-07 09:43:59 -0800335}
336
337type selectsMockModule struct {
338 ModuleBase
339 DefaultableModuleBase
340 properties selectsMockModuleProperties
341}
342
343func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700344 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust5a231bd2024-02-07 09:43:59 -0800345 my_bool: p.properties.My_bool.Evaluate(ctx),
346 my_string: p.properties.My_string.Evaluate(ctx),
347 my_string_list: p.properties.My_string_list.Evaluate(ctx),
Cole Faustbdd8aee2024-03-14 14:33:02 -0700348 my_paths: p.properties.My_paths.Evaluate(ctx),
Cole Faust5a231bd2024-02-07 09:43:59 -0800349 })
350}
351
352func newSelectsMockModule() Module {
353 m := &selectsMockModule{}
354 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700355 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800356 InitDefaultableModule(m)
357 return m
358}