blob: 9cafedd50b239b1af6153b15d0bde7a496fb6fc5 [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) {
160 ctx := NewTestContext()
161 // A module type that has a srcs property but not a cflags property.
Colin Cross43e789d2020-01-28 09:46:50 -0800162 ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700163 Srcs []string
Colin Cross4b49b762019-11-22 15:25:03 -0800164 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700165 // A module type that has a cflags property but not a srcs property.
Colin Cross43e789d2020-01-28 09:46:50 -0800166 ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700167 Cflags []string
Colin Cross4b49b762019-11-22 15:25:03 -0800168 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700169 // A module type that does not have any properties that match product_variables.
Colin Cross43e789d2020-01-28 09:46:50 -0800170 ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
Colin Cross18c46802019-09-24 22:19:02 -0700171 Foo []string
Colin Cross4b49b762019-11-22 15:25:03 -0800172 }{}))
Colin Cross18c46802019-09-24 22:19:02 -0700173 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
Colin Crosseabaedd2020-02-06 17:01:55 -0800174 ctx.BottomUp("variable", VariableMutator).Parallel()
Colin Cross18c46802019-09-24 22:19:02 -0700175 })
176
177 // Test that a module can use one product variable even if it doesn't have all the properties
178 // supported by that product variable.
179 bp := `
180 module1 {
181 name: "foo",
182 product_variables: {
183 eng: {
184 srcs: ["foo.c"],
185 },
186 },
187 }
188 module2 {
189 name: "bar",
190 product_variables: {
191 eng: {
192 cflags: ["-DBAR"],
193 },
194 },
195 }
196
197 module3 {
198 name: "baz",
199 }
200 `
Colin Cross98be1bb2019-12-13 20:41:13 -0800201 config := TestConfig(buildDir, nil, bp, nil)
Colin Cross18c46802019-09-24 22:19:02 -0700202 config.TestProductVariables.Eng = proptools.BoolPtr(true)
203
Colin Cross98be1bb2019-12-13 20:41:13 -0800204 ctx.Register(config)
205
Colin Cross18c46802019-09-24 22:19:02 -0700206 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
207 FailIfErrored(t, errs)
208 _, errs = ctx.PrepareBuildActions(config)
209 FailIfErrored(t, errs)
210}
211
Colin Crosseabaedd2020-02-06 17:01:55 -0800212var testProductVariableDefaultsProperties = struct {
213 Product_variables struct {
214 Eng struct {
215 Foo []string
216 Bar []string
217 }
218 }
219}{}
220
221type productVariablesDefaultsTestProperties struct {
222 Foo []string
223}
224
225type productVariablesDefaultsTestProperties2 struct {
226 Foo []string
227 Bar []string
228}
229
230type productVariablesDefaultsTestModule struct {
231 ModuleBase
232 DefaultableModuleBase
233 properties productVariablesDefaultsTestProperties
234}
235
236func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
237 ctx.Build(pctx, BuildParams{
238 Rule: Touch,
239 Output: PathForModuleOut(ctx, "out"),
240 })
241}
242
243func productVariablesDefaultsTestModuleFactory() Module {
244 module := &productVariablesDefaultsTestModule{}
245 module.AddProperties(&module.properties)
246 module.variableProperties = testProductVariableDefaultsProperties
247 InitAndroidModule(module)
248 InitDefaultableModule(module)
249 return module
250}
251
252type productVariablesDefaultsTestDefaults struct {
253 ModuleBase
254 DefaultsModuleBase
255}
256
257func productVariablesDefaultsTestDefaultsFactory() Module {
258 defaults := &productVariablesDefaultsTestDefaults{}
259 defaults.AddProperties(&productVariablesDefaultsTestProperties{})
260 defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
261 defaults.variableProperties = testProductVariableDefaultsProperties
262 InitDefaultsModule(defaults)
263 return defaults
264}
265
266// Test a defaults module that supports more product variable properties than the target module.
267func TestProductVariablesDefaults(t *testing.T) {
268 bp := `
269 defaults {
270 name: "defaults",
271 product_variables: {
272 eng: {
273 foo: ["product_variable_defaults"],
274 bar: ["product_variable_defaults"],
275 },
276 },
277 foo: ["defaults"],
278 bar: ["defaults"],
279 }
280
281 test {
282 name: "foo",
283 defaults: ["defaults"],
284 foo: ["module"],
285 product_variables: {
286 eng: {
287 foo: ["product_variable_module"],
288 },
289 },
290 }
291 `
292
293 config := TestConfig(buildDir, nil, bp, nil)
294 config.TestProductVariables.Eng = boolPtr(true)
295
296 ctx := NewTestContext()
297
298 ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
299 ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
300
301 ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
302 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
303 ctx.BottomUp("variable", VariableMutator).Parallel()
304 })
305
306 ctx.Register(config)
307
308 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
309 FailIfErrored(t, errs)
310 _, errs = ctx.PrepareBuildActions(config)
311 FailIfErrored(t, errs)
312
313 foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
314
315 want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
316 if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
317 t.Errorf("expected foo %q, got %q", w, g)
318 }
319}
320
Colin Cross18c46802019-09-24 22:19:02 -0700321func BenchmarkSliceToTypeArray(b *testing.B) {
322 for _, n := range []int{1, 2, 4, 8, 100} {
323 var propStructs []interface{}
324 for i := 0; i < n; i++ {
325 propStructs = append(propStructs, &struct {
326 A *string
327 B string
328 }{})
329
330 }
331 b.Run(strconv.Itoa(n), func(b *testing.B) {
332 for i := 0; i < b.N; i++ {
333 _ = sliceToTypeArray(propStructs)
334 }
335 })
336 }
337}