blob: 9348b0d5f60c388d0a0e5fe33a5531f4b71fa77e [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) {
Colin Cross323dc602020-09-18 14:25:31 -0700115 t.Parallel()
Colin Cross7e0eaf12017-05-05 16:16:24 -0700116 for _, testCase := range printfIntoPropertyTestCases {
117 s := testCase.in
118 v := reflect.ValueOf(&s).Elem()
119 err := printfIntoProperty(v, testCase.val)
120 if err != nil && !testCase.err {
121 t.Errorf("unexpected error %s", err)
122 } else if err == nil && testCase.err {
123 t.Errorf("expected error")
124 } else if err == nil && v.String() != testCase.out {
125 t.Errorf("expected %q got %q", testCase.out, v.String())
126 }
127 }
128}
Colin Cross18c46802019-09-24 22:19:02 -0700129
130type testProductVariableModule struct {
131 ModuleBase
132}
133
134func (m *testProductVariableModule) GenerateAndroidBuildActions(ctx ModuleContext) {
135}
136
137var testProductVariableProperties = struct {
138 Product_variables struct {
139 Eng struct {
140 Srcs []string
141 Cflags []string
142 }
143 }
144}{}
145
146func testProductVariableModuleFactoryFactory(props interface{}) func() Module {
147 return func() Module {
148 m := &testProductVariableModule{}
149 clonedProps := proptools.CloneProperties(reflect.ValueOf(props)).Interface()
150 m.AddProperties(clonedProps)
151
Colin Cross9d34f352019-11-22 16:03:51 -0800152 // Set a default soongConfigVariableProperties, this will be used as the input to the property struct filter
Colin Cross18c46802019-09-24 22:19:02 -0700153 // for this test module.
154 m.variableProperties = testProductVariableProperties
155 InitAndroidModule(m)
156 return m
157 }
158}
159
160func TestProductVariables(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700161 t.Parallel()
Colin Cross18c46802019-09-24 22:19:02 -0700162 ctx := NewTestContext()
163 // A module type that has a srcs property but not a cflags property.
Colin Cross43e789d2020-01-28 09:46:50 -0800164 ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700165 Srcs []string
Colin Cross4b49b762019-11-22 15:25:03 -0800166 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700167 // A module type that has a cflags property but not a srcs property.
Colin Cross43e789d2020-01-28 09:46:50 -0800168 ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700169 Cflags []string
Colin Cross4b49b762019-11-22 15:25:03 -0800170 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700171 // A module type that does not have any properties that match product_variables.
Colin Cross43e789d2020-01-28 09:46:50 -0800172 ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700173 Foo []string
Colin Cross4b49b762019-11-22 15:25:03 -0800174 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700175 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
Colin Crosseabaedd2020-02-06 17:01:55 -0800176 ctx.BottomUp("variable", VariableMutator).Parallel()
Colin Cross18c46802019-09-24 22:19:02 -0700177 })
178
179 // Test that a module can use one product variable even if it doesn't have all the properties
180 // supported by that product variable.
181 bp := `
182 module1 {
183 name: "foo",
184 product_variables: {
185 eng: {
186 srcs: ["foo.c"],
187 },
188 },
189 }
190 module2 {
191 name: "bar",
192 product_variables: {
193 eng: {
194 cflags: ["-DBAR"],
195 },
196 },
197 }
198
199 module3 {
200 name: "baz",
201 }
202 `
Colin Cross98be1bb2019-12-13 20:41:13 -0800203 config := TestConfig(buildDir, nil, bp, nil)
Colin Cross18c46802019-09-24 22:19:02 -0700204 config.TestProductVariables.Eng = proptools.BoolPtr(true)
205
Colin Cross98be1bb2019-12-13 20:41:13 -0800206 ctx.Register(config)
207
Colin Cross18c46802019-09-24 22:19:02 -0700208 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
209 FailIfErrored(t, errs)
210 _, errs = ctx.PrepareBuildActions(config)
211 FailIfErrored(t, errs)
212}
213
Colin Crosseabaedd2020-02-06 17:01:55 -0800214var testProductVariableDefaultsProperties = struct {
215 Product_variables struct {
216 Eng struct {
217 Foo []string
218 Bar []string
219 }
220 }
221}{}
222
223type productVariablesDefaultsTestProperties struct {
224 Foo []string
225}
226
227type productVariablesDefaultsTestProperties2 struct {
228 Foo []string
229 Bar []string
230}
231
232type productVariablesDefaultsTestModule struct {
233 ModuleBase
234 DefaultableModuleBase
235 properties productVariablesDefaultsTestProperties
236}
237
238func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
239 ctx.Build(pctx, BuildParams{
240 Rule: Touch,
241 Output: PathForModuleOut(ctx, "out"),
242 })
243}
244
245func productVariablesDefaultsTestModuleFactory() Module {
246 module := &productVariablesDefaultsTestModule{}
247 module.AddProperties(&module.properties)
248 module.variableProperties = testProductVariableDefaultsProperties
249 InitAndroidModule(module)
250 InitDefaultableModule(module)
251 return module
252}
253
254type productVariablesDefaultsTestDefaults struct {
255 ModuleBase
256 DefaultsModuleBase
257}
258
259func productVariablesDefaultsTestDefaultsFactory() Module {
260 defaults := &productVariablesDefaultsTestDefaults{}
261 defaults.AddProperties(&productVariablesDefaultsTestProperties{})
262 defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
263 defaults.variableProperties = testProductVariableDefaultsProperties
264 InitDefaultsModule(defaults)
265 return defaults
266}
267
268// Test a defaults module that supports more product variable properties than the target module.
269func TestProductVariablesDefaults(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700270 t.Parallel()
Colin Crosseabaedd2020-02-06 17:01:55 -0800271 bp := `
272 defaults {
273 name: "defaults",
274 product_variables: {
275 eng: {
276 foo: ["product_variable_defaults"],
277 bar: ["product_variable_defaults"],
278 },
279 },
280 foo: ["defaults"],
281 bar: ["defaults"],
282 }
283
284 test {
285 name: "foo",
286 defaults: ["defaults"],
287 foo: ["module"],
288 product_variables: {
289 eng: {
290 foo: ["product_variable_module"],
291 },
292 },
293 }
294 `
295
296 config := TestConfig(buildDir, nil, bp, nil)
297 config.TestProductVariables.Eng = boolPtr(true)
298
299 ctx := NewTestContext()
300
301 ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
302 ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
303
304 ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
305 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
306 ctx.BottomUp("variable", VariableMutator).Parallel()
307 })
308
309 ctx.Register(config)
310
311 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
312 FailIfErrored(t, errs)
313 _, errs = ctx.PrepareBuildActions(config)
314 FailIfErrored(t, errs)
315
316 foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
317
318 want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
319 if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
320 t.Errorf("expected foo %q, got %q", w, g)
321 }
322}
323
Colin Cross18c46802019-09-24 22:19:02 -0700324func BenchmarkSliceToTypeArray(b *testing.B) {
325 for _, n := range []int{1, 2, 4, 8, 100} {
326 var propStructs []interface{}
327 for i := 0; i < n; i++ {
328 propStructs = append(propStructs, &struct {
329 A *string
330 B string
331 }{})
332
333 }
334 b.Run(strconv.Itoa(n), func(b *testing.B) {
335 for i := 0; i < b.N; i++ {
336 _ = sliceToTypeArray(propStructs)
337 }
338 })
339 }
340}