blob: dca3789333ff357db8c4b60e9b33ba12e02a6b0e [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 {
83 name: "Differing types",
84 bp: `
85 my_module_type {
86 name: "foo",
87 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
88 "a": "a.cpp",
89 "b": true,
90 _: "c.cpp",
91 }),
92 }
93 `,
94 expectedError: `can't assign bool value to string property "my_string\[1\]"`,
95 },
96 {
97 name: "String list non-default",
98 bp: `
99 my_module_type {
100 name: "foo",
101 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
102 "a": ["a.cpp"],
103 "b": ["b.cpp"],
104 _: ["c.cpp"],
105 }),
106 }
107 `,
108 provider: selectsTestProvider{
109 my_string_list: &[]string{"a.cpp"},
110 },
111 vendorVars: map[string]map[string]string{
112 "my_namespace": {
113 "my_variable": "a",
114 },
115 },
116 },
117 {
118 name: "String list append",
119 bp: `
120 my_module_type {
121 name: "foo",
122 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
123 "a": ["a.cpp"],
124 "b": ["b.cpp"],
125 _: ["c.cpp"],
126 }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
127 "a2": ["a2.cpp"],
128 "b2": ["b2.cpp"],
129 _: ["c2.cpp"],
130 }),
131 }
132 `,
133 provider: selectsTestProvider{
134 my_string_list: &[]string{"a.cpp", "c2.cpp"},
135 },
136 vendorVars: map[string]map[string]string{
137 "my_namespace": {
138 "my_variable": "a",
139 },
140 },
141 },
142 {
143 name: "String list prepend literal",
144 bp: `
145 my_module_type {
146 name: "foo",
147 my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
148 "a2": ["a2.cpp"],
149 "b2": ["b2.cpp"],
150 _: ["c2.cpp"],
151 }),
152 }
153 `,
154 provider: selectsTestProvider{
155 my_string_list: &[]string{"literal.cpp", "c2.cpp"},
156 },
157 },
158 {
159 name: "String list append literal",
160 bp: `
161 my_module_type {
162 name: "foo",
163 my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
164 "a2": ["a2.cpp"],
165 "b2": ["b2.cpp"],
166 _: ["c2.cpp"],
167 }) + ["literal.cpp"],
168 }
169 `,
170 provider: selectsTestProvider{
171 my_string_list: &[]string{"c2.cpp", "literal.cpp"},
172 },
173 },
174 {
175 name: "Can't append bools",
176 bp: `
177 my_module_type {
178 name: "foo",
179 my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
180 "a": true,
181 "b": false,
182 _: true,
183 }) + false,
184 }
185 `,
186 expectedError: "my_bool: Cannot append bools",
187 },
188 {
189 name: "Append string",
190 bp: `
191 my_module_type {
192 name: "foo",
193 my_string: select(soong_config_variable("my_namespace", "my_variable"), {
194 "a": "a",
195 "b": "b",
196 _: "c",
197 }) + ".cpp",
198 }
199 `,
200 provider: selectsTestProvider{
201 my_string: proptools.StringPtr("c.cpp"),
202 },
203 },
204 }
205
206 for _, tc := range testCases {
207 t.Run(tc.name, func(t *testing.T) {
208 fixtures := GroupFixturePreparers(
209 FixtureRegisterWithContext(func(ctx RegistrationContext) {
210 ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
211 }),
212 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
213 variables.VendorVars = tc.vendorVars
214 }),
215 )
216 if tc.expectedError != "" {
217 fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
218 }
219 result := fixtures.RunTestWithBp(t, tc.bp)
220
221 if tc.expectedError == "" {
222 m := result.ModuleForTests("foo", "")
223 p, _ := OtherModuleProvider[selectsTestProvider](result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
224 if !reflect.DeepEqual(p, tc.provider) {
225 t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
226 }
227 }
228 })
229 }
230}
231
232type selectsTestProvider struct {
233 my_bool *bool
234 my_string *string
235 my_string_list *[]string
236}
237
238func (p *selectsTestProvider) String() string {
239 myBoolStr := "nil"
240 if p.my_bool != nil {
241 myBoolStr = fmt.Sprintf("%t", *p.my_bool)
242 }
243 myStringStr := "nil"
244 if p.my_string != nil {
245 myStringStr = *p.my_string
246 }
247 return fmt.Sprintf(`selectsTestProvider {
248 my_bool: %v,
249 my_string: %s,
250 my_string_list: %s,
251}`, myBoolStr, myStringStr, p.my_string_list)
252}
253
254var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
255
256type selectsMockModuleProperties struct {
257 My_bool proptools.Configurable[bool]
258 My_string proptools.Configurable[string]
259 My_string_list proptools.Configurable[[]string]
260}
261
262type selectsMockModule struct {
263 ModuleBase
264 DefaultableModuleBase
265 properties selectsMockModuleProperties
266}
267
268func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
269 SetProvider[selectsTestProvider](ctx, selectsTestProviderKey, selectsTestProvider{
270 my_bool: p.properties.My_bool.Evaluate(ctx),
271 my_string: p.properties.My_string.Evaluate(ctx),
272 my_string_list: p.properties.My_string_list.Evaluate(ctx),
273 })
274}
275
276func newSelectsMockModule() Module {
277 m := &selectsMockModule{}
278 m.AddProperties(&m.properties)
279 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
280 InitDefaultableModule(m)
281 return m
282}