blob: 9ee01e92f3a848eb980c9fadb4816e686386d666 [file] [log] [blame]
Colin Cross9d34f352019-11-22 16:03:51 -08001// Copyright 2019 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 (
Paul Duffinf1e6a042023-01-09 15:43:29 +000018 "fmt"
Colin Cross9d34f352019-11-22 16:03:51 -080019 "testing"
20)
21
Liz Kammerdbd48092020-09-21 22:24:17 +000022type soongConfigTestDefaultsModule struct {
23 ModuleBase
24 DefaultsModuleBase
25}
26
27func soongConfigTestDefaultsModuleFactory() Module {
28 m := &soongConfigTestDefaultsModule{}
29 m.AddProperties(&soongConfigTestModuleProperties{})
30 InitDefaultsModule(m)
31 return m
32}
33
Colin Cross9d34f352019-11-22 16:03:51 -080034type soongConfigTestModule struct {
35 ModuleBase
Liz Kammerdbd48092020-09-21 22:24:17 +000036 DefaultableModuleBase
Colin Cross9d34f352019-11-22 16:03:51 -080037 props soongConfigTestModuleProperties
38}
39
40type soongConfigTestModuleProperties struct {
41 Cflags []string
42}
43
44func soongConfigTestModuleFactory() Module {
45 m := &soongConfigTestModule{}
46 m.AddProperties(&m.props)
47 InitAndroidModule(m)
Liz Kammerdbd48092020-09-21 22:24:17 +000048 InitDefaultableModule(m)
Colin Cross9d34f352019-11-22 16:03:51 -080049 return m
50}
51
52func (t soongConfigTestModule) GenerateAndroidBuildActions(ModuleContext) {}
53
Paul Duffin32299982023-01-09 14:02:06 +000054var prepareForSoongConfigTestModule = FixtureRegisterWithContext(func(ctx RegistrationContext) {
55 ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
56 ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
57})
58
Colin Cross9d34f352019-11-22 16:03:51 -080059func TestSoongConfigModule(t *testing.T) {
60 configBp := `
61 soong_config_module_type {
Liz Kammerdbd48092020-09-21 22:24:17 +000062 name: "acme_test",
63 module_type: "test",
Colin Cross9d34f352019-11-22 16:03:51 -080064 config_namespace: "acme",
Liz Kammer432bd592020-12-16 12:42:02 -080065 variables: ["board", "feature1", "FEATURE3", "unused_string_var"],
Liz Kammerbdce0df2021-10-15 13:34:27 -040066 bool_variables: ["feature2", "unused_feature", "always_true"],
Liz Kammer432bd592020-12-16 12:42:02 -080067 value_variables: ["size", "unused_size"],
Liz Kammerdbd48092020-09-21 22:24:17 +000068 properties: ["cflags", "srcs", "defaults"],
Colin Cross9d34f352019-11-22 16:03:51 -080069 }
70
71 soong_config_string_variable {
72 name: "board",
Liz Kammer432bd592020-12-16 12:42:02 -080073 values: ["soc_a", "soc_b", "soc_c", "soc_d"],
74 }
75
76 soong_config_string_variable {
77 name: "unused_string_var",
78 values: ["a", "b"],
Colin Cross9d34f352019-11-22 16:03:51 -080079 }
80
81 soong_config_bool_variable {
82 name: "feature1",
83 }
84
85 soong_config_bool_variable {
Colin Cross3beeb1e2020-02-05 16:27:47 -080086 name: "FEATURE3",
Colin Cross9d34f352019-11-22 16:03:51 -080087 }
88 `
89
90 importBp := `
91 soong_config_module_type_import {
92 from: "SoongConfig.bp",
Liz Kammerdbd48092020-09-21 22:24:17 +000093 module_types: ["acme_test"],
Colin Cross9d34f352019-11-22 16:03:51 -080094 }
95 `
96
97 bp := `
Liz Kammerdbd48092020-09-21 22:24:17 +000098 test_defaults {
99 name: "foo_defaults",
100 cflags: ["DEFAULT"],
101 }
102
103 acme_test {
Colin Cross9d34f352019-11-22 16:03:51 -0800104 name: "foo",
105 cflags: ["-DGENERIC"],
Liz Kammerdbd48092020-09-21 22:24:17 +0000106 defaults: ["foo_defaults"],
Colin Cross9d34f352019-11-22 16:03:51 -0800107 soong_config_variables: {
108 board: {
109 soc_a: {
110 cflags: ["-DSOC_A"],
111 },
112 soc_b: {
113 cflags: ["-DSOC_B"],
114 },
Liz Kammer432bd592020-12-16 12:42:02 -0800115 soc_c: {},
116 conditions_default: {
117 cflags: ["-DSOC_CONDITIONS_DEFAULT"],
118 },
Colin Cross9d34f352019-11-22 16:03:51 -0800119 },
Dan Willemsenb0935db2020-03-23 19:42:18 -0700120 size: {
121 cflags: ["-DSIZE=%s"],
Liz Kammer432bd592020-12-16 12:42:02 -0800122 conditions_default: {
123 cflags: ["-DSIZE=CONDITIONS_DEFAULT"],
124 },
Dan Willemsenb0935db2020-03-23 19:42:18 -0700125 },
Colin Cross9d34f352019-11-22 16:03:51 -0800126 feature1: {
Liz Kammer432bd592020-12-16 12:42:02 -0800127 conditions_default: {
128 cflags: ["-DF1_CONDITIONS_DEFAULT"],
129 },
Colin Cross9d34f352019-11-22 16:03:51 -0800130 cflags: ["-DFEATURE1"],
131 },
132 feature2: {
133 cflags: ["-DFEATURE2"],
Liz Kammer432bd592020-12-16 12:42:02 -0800134 conditions_default: {
135 cflags: ["-DF2_CONDITIONS_DEFAULT"],
136 },
Colin Cross9d34f352019-11-22 16:03:51 -0800137 },
Colin Cross3beeb1e2020-02-05 16:27:47 -0800138 FEATURE3: {
Colin Cross9d34f352019-11-22 16:03:51 -0800139 cflags: ["-DFEATURE3"],
140 },
141 },
142 }
Liz Kammerdbd48092020-09-21 22:24:17 +0000143
144 test_defaults {
145 name: "foo_defaults_a",
146 cflags: ["DEFAULT_A"],
147 }
148
149 test_defaults {
150 name: "foo_defaults_b",
151 cflags: ["DEFAULT_B"],
152 }
153
Liz Kammerbdce0df2021-10-15 13:34:27 -0400154 test_defaults {
155 name: "foo_defaults_always_true",
156 cflags: ["DEFAULT_ALWAYS_TRUE"],
157 }
158
Liz Kammerdbd48092020-09-21 22:24:17 +0000159 acme_test {
160 name: "foo_with_defaults",
161 cflags: ["-DGENERIC"],
162 defaults: ["foo_defaults"],
163 soong_config_variables: {
164 board: {
165 soc_a: {
166 cflags: ["-DSOC_A"],
167 defaults: ["foo_defaults_a"],
168 },
169 soc_b: {
170 cflags: ["-DSOC_B"],
171 defaults: ["foo_defaults_b"],
172 },
Liz Kammer432bd592020-12-16 12:42:02 -0800173 soc_c: {},
Liz Kammerdbd48092020-09-21 22:24:17 +0000174 },
175 size: {
176 cflags: ["-DSIZE=%s"],
177 },
178 feature1: {
179 cflags: ["-DFEATURE1"],
180 },
181 feature2: {
182 cflags: ["-DFEATURE2"],
183 },
184 FEATURE3: {
185 cflags: ["-DFEATURE3"],
186 },
Liz Kammerbdce0df2021-10-15 13:34:27 -0400187 always_true: {
188 defaults: ["foo_defaults_always_true"],
189 conditions_default: {
190 // verify that conditions_default is skipped if the
191 // soong config variable is true by specifying a
192 // non-existent module in conditions_default
193 defaults: ["//nonexistent:defaults"],
194 }
195 },
Liz Kammerdbd48092020-09-21 22:24:17 +0000196 },
197 }
Colin Cross9d34f352019-11-22 16:03:51 -0800198 `
199
Paul Duffin791302b2021-03-16 22:45:14 +0000200 fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer {
201 return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
202 variables.VendorVars = vars
203 })
204 }
205
206 run := func(t *testing.T, bp string, fs MockFS) {
Liz Kammer432bd592020-12-16 12:42:02 -0800207 testCases := []struct {
208 name string
Paul Duffin791302b2021-03-16 22:45:14 +0000209 preparer FixturePreparer
Liz Kammer432bd592020-12-16 12:42:02 -0800210 fooExpectedFlags []string
211 fooDefaultsExpectedFlags []string
212 }{
213 {
214 name: "withValues",
Paul Duffin791302b2021-03-16 22:45:14 +0000215 preparer: fixtureForVendorVars(map[string]map[string]string{
216 "acme": {
Liz Kammer432bd592020-12-16 12:42:02 -0800217 "board": "soc_a",
218 "size": "42",
219 "feature1": "true",
220 "feature2": "false",
221 // FEATURE3 unset
222 "unused_feature": "true", // unused
223 "unused_size": "1", // unused
224 "unused_string_var": "a", // unused
Liz Kammerbdce0df2021-10-15 13:34:27 -0400225 "always_true": "true",
Liz Kammer432bd592020-12-16 12:42:02 -0800226 },
227 }),
228 fooExpectedFlags: []string{
229 "DEFAULT",
230 "-DGENERIC",
231 "-DF2_CONDITIONS_DEFAULT",
232 "-DSIZE=42",
233 "-DSOC_A",
234 "-DFEATURE1",
235 },
236 fooDefaultsExpectedFlags: []string{
237 "DEFAULT_A",
Liz Kammerbdce0df2021-10-15 13:34:27 -0400238 "DEFAULT_ALWAYS_TRUE",
Liz Kammer432bd592020-12-16 12:42:02 -0800239 "DEFAULT",
240 "-DGENERIC",
241 "-DSIZE=42",
242 "-DSOC_A",
243 "-DFEATURE1",
244 },
245 },
246 {
247 name: "empty_prop_for_string_var",
Paul Duffin791302b2021-03-16 22:45:14 +0000248 preparer: fixtureForVendorVars(map[string]map[string]string{
Liz Kammerbdce0df2021-10-15 13:34:27 -0400249 "acme": {
250 "board": "soc_c",
251 "always_true": "true",
252 }}),
Liz Kammer432bd592020-12-16 12:42:02 -0800253 fooExpectedFlags: []string{
254 "DEFAULT",
255 "-DGENERIC",
256 "-DF2_CONDITIONS_DEFAULT",
257 "-DSIZE=CONDITIONS_DEFAULT",
258 "-DF1_CONDITIONS_DEFAULT",
259 },
260 fooDefaultsExpectedFlags: []string{
Liz Kammerbdce0df2021-10-15 13:34:27 -0400261 "DEFAULT_ALWAYS_TRUE",
Liz Kammer432bd592020-12-16 12:42:02 -0800262 "DEFAULT",
263 "-DGENERIC",
264 },
265 },
266 {
267 name: "unused_string_var",
Paul Duffin791302b2021-03-16 22:45:14 +0000268 preparer: fixtureForVendorVars(map[string]map[string]string{
Liz Kammerbdce0df2021-10-15 13:34:27 -0400269 "acme": {
270 "board": "soc_d",
271 "always_true": "true",
272 }}),
Liz Kammer432bd592020-12-16 12:42:02 -0800273 fooExpectedFlags: []string{
274 "DEFAULT",
275 "-DGENERIC",
276 "-DF2_CONDITIONS_DEFAULT",
277 "-DSIZE=CONDITIONS_DEFAULT",
278 "-DSOC_CONDITIONS_DEFAULT", // foo does not contain a prop "soc_d", so we use the default
279 "-DF1_CONDITIONS_DEFAULT",
280 },
281 fooDefaultsExpectedFlags: []string{
Liz Kammerbdce0df2021-10-15 13:34:27 -0400282 "DEFAULT_ALWAYS_TRUE",
Liz Kammer432bd592020-12-16 12:42:02 -0800283 "DEFAULT",
284 "-DGENERIC",
285 },
286 },
Colin Cross9d34f352019-11-22 16:03:51 -0800287
Liz Kammer432bd592020-12-16 12:42:02 -0800288 {
Liz Kammerbdce0df2021-10-15 13:34:27 -0400289 name: "conditions_default",
290 preparer: fixtureForVendorVars(map[string]map[string]string{
291 "acme": {
292 "always_true": "true",
293 }}),
Liz Kammer432bd592020-12-16 12:42:02 -0800294 fooExpectedFlags: []string{
295 "DEFAULT",
296 "-DGENERIC",
297 "-DF2_CONDITIONS_DEFAULT",
298 "-DSIZE=CONDITIONS_DEFAULT",
299 "-DSOC_CONDITIONS_DEFAULT",
300 "-DF1_CONDITIONS_DEFAULT",
301 },
302 fooDefaultsExpectedFlags: []string{
Liz Kammerbdce0df2021-10-15 13:34:27 -0400303 "DEFAULT_ALWAYS_TRUE",
Liz Kammer432bd592020-12-16 12:42:02 -0800304 "DEFAULT",
305 "-DGENERIC",
306 },
Colin Cross9d34f352019-11-22 16:03:51 -0800307 },
308 }
309
Liz Kammer432bd592020-12-16 12:42:02 -0800310 for _, tc := range testCases {
Paul Duffin791302b2021-03-16 22:45:14 +0000311 t.Run(tc.name, func(t *testing.T) {
Paul Duffin30ac3e72021-03-20 00:36:14 +0000312 result := GroupFixturePreparers(
Paul Duffin791302b2021-03-16 22:45:14 +0000313 tc.preparer,
314 PrepareForTestWithDefaults,
Paul Duffin32299982023-01-09 14:02:06 +0000315 PrepareForTestWithSoongConfigModuleBuildComponents,
316 prepareForSoongConfigTestModule,
Paul Duffin791302b2021-03-16 22:45:14 +0000317 fs.AddToFixture(),
318 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000319 ).RunTest(t)
Colin Cross9d34f352019-11-22 16:03:51 -0800320
Paul Duffin791302b2021-03-16 22:45:14 +0000321 foo := result.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
322 AssertDeepEquals(t, "foo cflags", tc.fooExpectedFlags, foo.props.Cflags)
Colin Cross9d34f352019-11-22 16:03:51 -0800323
Paul Duffin791302b2021-03-16 22:45:14 +0000324 fooDefaults := result.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
325 AssertDeepEquals(t, "foo_with_defaults cflags", tc.fooDefaultsExpectedFlags, fooDefaults.props.Cflags)
326 })
Liz Kammerdbd48092020-09-21 22:24:17 +0000327 }
Colin Cross9d34f352019-11-22 16:03:51 -0800328 }
329
330 t.Run("single file", func(t *testing.T) {
331 run(t, configBp+bp, nil)
332 })
333
334 t.Run("import", func(t *testing.T) {
335 run(t, importBp+bp, map[string][]byte{
336 "SoongConfig.bp": []byte(configBp),
337 })
338 })
339}
Liz Kammer432bd592020-12-16 12:42:02 -0800340
Liz Kammer0fc1e132021-07-15 12:34:59 -0400341func TestNonExistentPropertyInSoongConfigModule(t *testing.T) {
342 bp := `
343 soong_config_module_type {
344 name: "acme_test",
345 module_type: "test",
346 config_namespace: "acme",
347 bool_variables: ["feature1"],
348 properties: ["made_up_property"],
349 }
350
351 acme_test {
352 name: "foo",
353 cflags: ["-DGENERIC"],
354 soong_config_variables: {
355 feature1: {
356 made_up_property: true,
357 },
358 },
359 }
360 `
361
362 fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer {
363 return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
364 variables.VendorVars = vars
365 })
366 }
367
368 GroupFixturePreparers(
369 fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}),
370 PrepareForTestWithDefaults,
Paul Duffin32299982023-01-09 14:02:06 +0000371 PrepareForTestWithSoongConfigModuleBuildComponents,
372 prepareForSoongConfigTestModule,
Liz Kammer0fc1e132021-07-15 12:34:59 -0400373 FixtureWithRootAndroidBp(bp),
374 ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
375 // TODO(b/171232169): improve the error message for non-existent properties
376 `unrecognized property "soong_config_variables`,
377 })).RunTest(t)
378}
379
Liz Kammer72beb342022-02-03 08:42:10 -0500380func TestDuplicateStringValueInSoongConfigStringVariable(t *testing.T) {
381 bp := `
382 soong_config_string_variable {
383 name: "board",
384 values: ["soc_a", "soc_b", "soc_c", "soc_a"],
385 }
386
387 soong_config_module_type {
388 name: "acme_test",
389 module_type: "test",
390 config_namespace: "acme",
391 variables: ["board"],
392 properties: ["cflags", "srcs", "defaults"],
393 }
394 `
395
396 fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer {
397 return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
398 variables.VendorVars = vars
399 })
400 }
401
402 GroupFixturePreparers(
403 fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}),
404 PrepareForTestWithDefaults,
Paul Duffin32299982023-01-09 14:02:06 +0000405 PrepareForTestWithSoongConfigModuleBuildComponents,
406 prepareForSoongConfigTestModule,
Liz Kammer72beb342022-02-03 08:42:10 -0500407 FixtureWithRootAndroidBp(bp),
408 ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
409 // TODO(b/171232169): improve the error message for non-existent properties
410 `Android.bp: soong_config_string_variable: values property error: duplicate value: "soc_a"`,
411 })).RunTest(t)
412}
413
Paul Duffinf1e6a042023-01-09 15:43:29 +0000414type soongConfigTestSingletonModule struct {
415 SingletonModuleBase
416 props soongConfigTestSingletonModuleProperties
417}
Liz Kammer432bd592020-12-16 12:42:02 -0800418
Paul Duffinf1e6a042023-01-09 15:43:29 +0000419type soongConfigTestSingletonModuleProperties struct {
420 Fragments []struct {
421 Apex string
422 Module string
423 }
424}
Liz Kammer432bd592020-12-16 12:42:02 -0800425
Paul Duffinf1e6a042023-01-09 15:43:29 +0000426func soongConfigTestSingletonModuleFactory() SingletonModule {
427 m := &soongConfigTestSingletonModule{}
428 m.AddProperties(&m.props)
429 InitAndroidModule(m)
430 return m
431}
432
433func (t *soongConfigTestSingletonModule) GenerateAndroidBuildActions(ModuleContext) {}
434
435func (t *soongConfigTestSingletonModule) GenerateSingletonBuildActions(SingletonContext) {}
436
437var prepareForSoongConfigTestSingletonModule = FixtureRegisterWithContext(func(ctx RegistrationContext) {
438 ctx.RegisterSingletonModuleType("test_singleton", soongConfigTestSingletonModuleFactory)
439})
440
441func TestSoongConfigModuleSingletonModule(t *testing.T) {
442 bp := `
443 soong_config_module_type {
444 name: "acme_test_singleton",
445 module_type: "test_singleton",
446 config_namespace: "acme",
447 bool_variables: ["coyote"],
448 properties: ["fragments"],
449 }
450
451 acme_test_singleton {
452 name: "wiley",
453 fragments: [
454 {
455 apex: "com.android.acme",
456 module: "road-runner",
457 },
458 ],
459 soong_config_variables: {
460 coyote: {
461 fragments: [
462 {
463 apex: "com.android.acme",
464 module: "wiley",
465 },
466 ],
467 },
468 },
469 }
470 `
471
472 for _, test := range []struct {
473 coyote bool
474 expectedFragments string
475 }{
476 {
477 coyote: false,
478 expectedFragments: "[{Apex:com.android.acme Module:road-runner}]",
479 },
480 {
481 coyote: true,
482 expectedFragments: "[{Apex:com.android.acme Module:road-runner} {Apex:com.android.acme Module:wiley}]",
483 },
484 } {
485 t.Run(fmt.Sprintf("coyote:%t", test.coyote), func(t *testing.T) {
486 GroupFixturePreparers(
487 PrepareForTestWithSoongConfigModuleBuildComponents,
488 prepareForSoongConfigTestSingletonModule,
489 FixtureWithRootAndroidBp(bp),
490 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
491 variables.VendorVars = map[string]map[string]string{
492 "acme": {
493 "coyote": fmt.Sprintf("%t", test.coyote),
494 },
495 }
496 }),
497 ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
498 `\QDuplicate SingletonModule "test_singleton", previously used in\E`,
499 })).RunTest(t)
500 })
501 }
Liz Kammer432bd592020-12-16 12:42:02 -0800502}