blob: 73dc052d548e42caecbc0145d4192977ebc8e46f [file] [log] [blame]
Colin Cross7e0eaf12017-05-05 16:16:24 -07001// Copyright 2015 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 "reflect"
Colin Cross18c46802019-09-24 22:19:02 -070019 "strconv"
Colin Cross7e0eaf12017-05-05 16:16:24 -070020 "testing"
Colin Cross18c46802019-09-24 22:19:02 -070021
22 "github.com/google/blueprint/proptools"
Colin Cross7e0eaf12017-05-05 16:16:24 -070023)
24
25type printfIntoPropertyTestCase struct {
26 in string
27 val interface{}
28 out string
29 err bool
30}
31
32var printfIntoPropertyTestCases = []printfIntoPropertyTestCase{
33 {
34 in: "%d",
35 val: 0,
36 out: "0",
37 },
38 {
39 in: "%d",
40 val: 1,
41 out: "1",
42 },
43 {
44 in: "%d",
45 val: 2,
46 out: "2",
47 },
48 {
49 in: "%d",
50 val: false,
51 out: "0",
52 },
53 {
54 in: "%d",
55 val: true,
56 out: "1",
57 },
58 {
59 in: "%d",
60 val: -1,
61 out: "-1",
62 },
63
64 {
65 in: "-DA=%d",
66 val: 1,
67 out: "-DA=1",
68 },
69 {
70 in: "-DA=%du",
71 val: 1,
72 out: "-DA=1u",
73 },
74 {
75 in: "-DA=%s",
76 val: "abc",
77 out: "-DA=abc",
78 },
79 {
80 in: `-DA="%s"`,
81 val: "abc",
82 out: `-DA="abc"`,
83 },
84
85 {
86 in: "%%",
87 err: true,
88 },
89 {
90 in: "%d%s",
91 err: true,
92 },
93 {
94 in: "%d,%s",
95 err: true,
96 },
97 {
98 in: "%d",
99 val: "",
100 err: true,
101 },
102 {
103 in: "%d",
104 val: 1.5,
105 err: true,
106 },
107 {
108 in: "%f",
109 val: 1.5,
110 err: true,
111 },
112}
113
114func TestPrintfIntoProperty(t *testing.T) {
115 for _, testCase := range printfIntoPropertyTestCases {
116 s := testCase.in
117 v := reflect.ValueOf(&s).Elem()
118 err := printfIntoProperty(v, testCase.val)
119 if err != nil && !testCase.err {
120 t.Errorf("unexpected error %s", err)
121 } else if err == nil && testCase.err {
122 t.Errorf("expected error")
123 } else if err == nil && v.String() != testCase.out {
124 t.Errorf("expected %q got %q", testCase.out, v.String())
125 }
126 }
127}
Colin Cross18c46802019-09-24 22:19:02 -0700128
129type testProductVariableModule struct {
130 ModuleBase
131}
132
133func (m *testProductVariableModule) GenerateAndroidBuildActions(ctx ModuleContext) {
134}
135
136var testProductVariableProperties = struct {
137 Product_variables struct {
138 Eng struct {
139 Srcs []string
140 Cflags []string
141 }
142 }
143}{}
144
145func testProductVariableModuleFactoryFactory(props interface{}) func() Module {
146 return func() Module {
147 m := &testProductVariableModule{}
148 clonedProps := proptools.CloneProperties(reflect.ValueOf(props)).Interface()
149 m.AddProperties(clonedProps)
150
Colin Cross9d34f352019-11-22 16:03:51 -0800151 // Set a default soongConfigVariableProperties, this will be used as the input to the property struct filter
Colin Cross18c46802019-09-24 22:19:02 -0700152 // for this test module.
153 m.variableProperties = testProductVariableProperties
154 InitAndroidModule(m)
155 return m
156 }
157}
158
159func TestProductVariables(t *testing.T) {
Colin Cross18c46802019-09-24 22:19:02 -0700160 // Test that a module can use one product variable even if it doesn't have all the properties
161 // supported by that product variable.
162 bp := `
163 module1 {
164 name: "foo",
165 product_variables: {
166 eng: {
167 srcs: ["foo.c"],
168 },
169 },
170 }
171 module2 {
172 name: "bar",
173 product_variables: {
174 eng: {
175 cflags: ["-DBAR"],
176 },
177 },
178 }
179
180 module3 {
181 name: "baz",
182 }
183 `
Colin Cross18c46802019-09-24 22:19:02 -0700184
Paul Duffin30ac3e72021-03-20 00:36:14 +0000185 GroupFixturePreparers(
Paul Duffin4bb2b212021-03-16 23:36:24 +0000186 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
187 variables.Eng = proptools.BoolPtr(true)
188 }),
189 FixtureRegisterWithContext(func(ctx RegistrationContext) {
190 // A module type that has a srcs property but not a cflags property.
191 ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
192 Srcs []string
193 }{}))
194 // A module type that has a cflags property but not a srcs property.
195 ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
196 Cflags []string
197 }{}))
198 // A module type that does not have any properties that match product_variables.
199 ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
200 Foo []string
201 }{}))
Colin Cross7da471f2024-08-16 09:21:18 -0700202 registerVariableBuildComponents(ctx)
Paul Duffin4bb2b212021-03-16 23:36:24 +0000203 }),
204 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000205 ).RunTest(t)
Colin Cross18c46802019-09-24 22:19:02 -0700206}
207
Colin Crosseabaedd2020-02-06 17:01:55 -0800208var testProductVariableDefaultsProperties = struct {
209 Product_variables struct {
210 Eng struct {
Colin Cross7da471f2024-08-16 09:21:18 -0700211 Foo []string `android:"arch_variant"`
Colin Crosseabaedd2020-02-06 17:01:55 -0800212 Bar []string
Colin Cross7da471f2024-08-16 09:21:18 -0700213 } `android:"arch_variant"`
214 } `android:"arch_variant"`
Colin Crosseabaedd2020-02-06 17:01:55 -0800215}{}
216
217type productVariablesDefaultsTestProperties struct {
Colin Cross7da471f2024-08-16 09:21:18 -0700218 Foo []string `android:"arch_variant"`
Colin Crosseabaedd2020-02-06 17:01:55 -0800219}
220
221type productVariablesDefaultsTestProperties2 struct {
222 Foo []string
223 Bar []string
224}
225
226type productVariablesDefaultsTestModule struct {
227 ModuleBase
228 DefaultableModuleBase
229 properties productVariablesDefaultsTestProperties
230}
231
232func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
233 ctx.Build(pctx, BuildParams{
234 Rule: Touch,
235 Output: PathForModuleOut(ctx, "out"),
236 })
237}
238
239func productVariablesDefaultsTestModuleFactory() Module {
240 module := &productVariablesDefaultsTestModule{}
241 module.AddProperties(&module.properties)
242 module.variableProperties = testProductVariableDefaultsProperties
Colin Cross7da471f2024-08-16 09:21:18 -0700243 InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
Colin Crosseabaedd2020-02-06 17:01:55 -0800244 InitDefaultableModule(module)
245 return module
246}
247
248type productVariablesDefaultsTestDefaults struct {
249 ModuleBase
250 DefaultsModuleBase
251}
252
253func productVariablesDefaultsTestDefaultsFactory() Module {
254 defaults := &productVariablesDefaultsTestDefaults{}
255 defaults.AddProperties(&productVariablesDefaultsTestProperties{})
256 defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
257 defaults.variableProperties = testProductVariableDefaultsProperties
258 InitDefaultsModule(defaults)
259 return defaults
260}
261
262// Test a defaults module that supports more product variable properties than the target module.
263func TestProductVariablesDefaults(t *testing.T) {
264 bp := `
265 defaults {
266 name: "defaults",
267 product_variables: {
268 eng: {
269 foo: ["product_variable_defaults"],
270 bar: ["product_variable_defaults"],
271 },
272 },
273 foo: ["defaults"],
274 bar: ["defaults"],
275 }
276
277 test {
278 name: "foo",
279 defaults: ["defaults"],
280 foo: ["module"],
281 product_variables: {
282 eng: {
283 foo: ["product_variable_module"],
284 },
285 },
286 }
287 `
288
Paul Duffin30ac3e72021-03-20 00:36:14 +0000289 result := GroupFixturePreparers(
Paul Duffin4bb2b212021-03-16 23:36:24 +0000290 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
291 variables.Eng = boolPtr(true)
292 }),
293 PrepareForTestWithDefaults,
294 PrepareForTestWithVariables,
295 FixtureRegisterWithContext(func(ctx RegistrationContext) {
296 ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
297 ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
298 }),
299 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000300 ).RunTest(t)
Colin Crosseabaedd2020-02-06 17:01:55 -0800301
Paul Duffin4bb2b212021-03-16 23:36:24 +0000302 foo := result.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
Colin Crosseabaedd2020-02-06 17:01:55 -0800303
304 want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
Paul Duffin4bb2b212021-03-16 23:36:24 +0000305 AssertDeepEquals(t, "foo", want, foo.properties.Foo)
Colin Crosseabaedd2020-02-06 17:01:55 -0800306}
307
Colin Cross18c46802019-09-24 22:19:02 -0700308func BenchmarkSliceToTypeArray(b *testing.B) {
309 for _, n := range []int{1, 2, 4, 8, 100} {
310 var propStructs []interface{}
311 for i := 0; i < n; i++ {
312 propStructs = append(propStructs, &struct {
313 A *string
314 B string
315 }{})
316
317 }
318 b.Run(strconv.Itoa(n), func(b *testing.B) {
319 for i := 0; i < b.N; i++ {
320 _ = sliceToTypeArray(propStructs)
321 }
322 })
323 }
324}
Colin Cross7da471f2024-08-16 09:21:18 -0700325
326// Test a defaults module that supports more product variable properties than the target module.
327func TestProductVariablesArch(t *testing.T) {
328 bp := `
329 test {
330 name: "foo",
331 arch: {
332 arm: {
333 product_variables: {
334 eng: {
335 foo: ["arm"],
336 },
337 },
338 },
339 arm64: {
340 product_variables: {
341 eng: {
342 foo: ["arm64"],
343 },
344 },
345 },
346 },
347 foo: ["module"],
348 }
349 `
350
351 result := GroupFixturePreparers(
352 FixtureModifyProductVariables(func(variables FixtureProductVariables) {
353 variables.Eng = boolPtr(true)
354 }),
355 PrepareForTestWithArchMutator,
356 PrepareForTestWithVariables,
357 FixtureRegisterWithContext(func(ctx RegistrationContext) {
358 ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
359 }),
360 FixtureWithRootAndroidBp(bp),
361 ).RunTest(t)
362
363 foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*productVariablesDefaultsTestModule)
364
365 want := []string{"module", "arm64"}
366 AssertDeepEquals(t, "foo", want, foo.properties.Foo)
367}