blob: aa9c521a2c44cb783c4d7e644d2f8ae723e8cdd4 [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 },
234 }
235
236 for _, tc := range testCases {
237 t.Run(tc.name, func(t *testing.T) {
238 fixtures := GroupFixturePreparers(
239 FixtureRegisterWithContext(func(ctx RegistrationContext) {
240 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
241 }),
242 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
243 variables.VendorVars = tc.vendorVars
244 }),
245 )
246 if tc.expectedError != "" {
247 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
248 }
249 result := fixtures.RunTestWithBp(t, tc.bp)
250
251 if tc.expectedError == "" {
252 m := result.ModuleForTests("foo", "")
253 p, _ := OtherModuleProvider[selectsTestProvider](result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
254 if !reflect.DeepEqual(p, tc.provider) {
255 t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
256 }
257 }
258 })
259 }
260}
261
262type selectsTestProvider struct {
263 my_bool *bool
264 my_string *string
265 my_string_list *[]string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700266 my_paths *[]string
Cole Faust5a231bd2024-02-07 09:43:59 -0800267}
268
269func (p *selectsTestProvider) String() string {
270 myBoolStr := "nil"
271 if p.my_bool != nil {
272 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
273 }
274 myStringStr := "nil"
275 if p.my_string != nil {
276 myStringStr = *p.my_string
277 }
278 return fmt.Sprintf(`selectsTestProvider {
279 my_bool: %v,
280 my_string: %s,
281 my_string_list: %s,
Cole Faustbdd8aee2024-03-14 14:33:02 -0700282 my_paths: %s,
283}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths)
Cole Faust5a231bd2024-02-07 09:43:59 -0800284}
285
286var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
287
288type selectsMockModuleProperties struct {
289 My_bool proptools.Configurable[bool]
290 My_string proptools.Configurable[string]
291 My_string_list proptools.Configurable[[]string]
Cole Faustbdd8aee2024-03-14 14:33:02 -0700292 My_paths proptools.Configurable[[]string] `android:"path"`
Cole Faust5a231bd2024-02-07 09:43:59 -0800293}
294
295type selectsMockModule struct {
296 ModuleBase
297 DefaultableModuleBase
298 properties selectsMockModuleProperties
299}
300
301func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Cole Faustbdd8aee2024-03-14 14:33:02 -0700302 SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
Cole Faust5a231bd2024-02-07 09:43:59 -0800303 my_bool: p.properties.My_bool.Evaluate(ctx),
304 my_string: p.properties.My_string.Evaluate(ctx),
305 my_string_list: p.properties.My_string_list.Evaluate(ctx),
Cole Faustbdd8aee2024-03-14 14:33:02 -0700306 my_paths: p.properties.My_paths.Evaluate(ctx),
Cole Faust5a231bd2024-02-07 09:43:59 -0800307 })
308}
309
310func newSelectsMockModule() Module {
311 m := &selectsMockModule{}
312 m.AddProperties(&m.properties)
313 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
314 InitDefaultableModule(m)
315 return m
316}