blob: b4e226f4bfe208232eb040d42cbfad9ae680ba50 [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 {
205 name: "Can't append bools",
206 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 `,
216 expectedError: "my_bool: Cannot append bools",
217 },
218 {
219 name: "Append string",
220 bp: `
221 my_module_type {
222 name: "foo",
223 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
224 "a": "a",
225 "b": "b",
226 _: "c",
227 }) + ".cpp",
228 }
229 `,
230 provider: selectsTestProvider{
231 my_string: proptools.StringPtr("c.cpp"),
232 },
233 },
Cole Faust0aa21cc2024-03-20 12:28:03 -0700234 {
235 name: "Select on variant",
236 bp: `
237 my_module_type {
238 name: "foo",
239 my_string: select(variant("arch"), {
240 "x86": "my_x86",
241 "x86_64": "my_x86_64",
242 "arm": "my_arm",
243 "arm64": "my_arm64",
244 _: "my_default",
245 }),
246 }
247 `,
248 provider: selectsTestProvider{
249 my_string: proptools.StringPtr("my_arm64"),
250 },
251 },
Cole Faust5a231bd2024-02-07 09:43:59 -0800252 }
253
254 for _, tc := range testCases {
255 t.Run(tc.name, func(t *testing.T) {
256 fixtures := GroupFixturePreparers(
Cole Faust0aa21cc2024-03-20 12:28:03 -0700257 PrepareForTestWithArchMutator,
Cole Faust5a231bd2024-02-07 09:43:59 -0800258 FixtureRegisterWithContext(func(ctx RegistrationContext) {
259 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
260 }),
261 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
262 variables.VendorVars = tc.vendorVars
263 }),
264 )
265 if tc.expectedError != "" {
266 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
267 }
268 result := fixtures.RunTestWithBp(t, tc.bp)
269
270 if tc.expectedError == "" {
Cole Faust0aa21cc2024-03-20 12:28:03 -0700271 m := result.ModuleForTests("foo", "android_arm64_armv8-a")
272 p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
Cole Faust5a231bd2024-02-07 09:43:59 -0800273 if !reflect.DeepEqual(p, tc.provider) {
274 t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
275 }
276 }
277 })
278 }
279}
280
281type selectsTestProvider struct {
282 my_bool *bool
283 my_string *string
284 my_string_list *[]string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700285 my_paths *[]string
Cole Faust5a231bd2024-02-07 09:43:59 -0800286}
287
288func (p *selectsTestProvider) String() string {
289 myBoolStr := "nil"
290 if p.my_bool != nil {
291 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
292 }
293 myStringStr := "nil"
294 if p.my_string != nil {
295 myStringStr = *p.my_string
296 }
297 return fmt.Sprintf(`selectsTestProvider {
298 my_bool: %v,
299 my_string: %s,
300 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700301 my_paths: %s,
302}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths)
Cole Faust5a231bd2024-02-07 09:43:59 -0800303}
304
305var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
306
307type selectsMockModuleProperties struct {
308 My_bool proptools.Configurable[bool]
309 My_string proptools.Configurable[string]
310 My_string_list proptools.Configurable[[]string]
Cole Faustbdd8aee2024-03-14 14:33:02 -0700311 My_paths proptools.Configurable[[]string] `android:"path"`
Cole Faust5a231bd2024-02-07 09:43:59 -0800312}
313
314type selectsMockModule struct {
315 ModuleBase
316 DefaultableModuleBase
317 properties selectsMockModuleProperties
318}
319
320func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700321 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust5a231bd2024-02-07 09:43:59 -0800322 my_bool: p.properties.My_bool.Evaluate(ctx),
323 my_string: p.properties.My_string.Evaluate(ctx),
324 my_string_list: p.properties.My_string_list.Evaluate(ctx),
Cole Faustbdd8aee2024-03-14 14:33:02 -0700325 my_paths: p.properties.My_paths.Evaluate(ctx),
Cole Faust5a231bd2024-02-07 09:43:59 -0800326 })
327}
328
329func newSelectsMockModule() Module {
330 m := &selectsMockModule{}
331 m.AddProperties(&m.properties)
Cole Faust0aa21cc2024-03-20 12:28:03 -0700332 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
Cole Faust5a231bd2024-02-07 09:43:59 -0800333 InitDefaultableModule(m)
334 return m
335}