blob: 7ec050f2a81e9f614e5c2866a47041c076ada0d2 [file] [log] [blame]
Colin Crosscb988072019-01-24 14:58:11 -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 (
18 "reflect"
Colin Cross158eeb72019-10-16 13:06:07 -070019 "runtime"
Colin Crosscb988072019-01-24 14:58:11 -080020 "testing"
Colin Cross74449102019-09-25 11:26:40 -070021
22 "github.com/google/blueprint/proptools"
Colin Crosscb988072019-01-24 14:58:11 -080023)
24
25type Named struct {
26 A *string `android:"arch_variant"`
27 B *string
28}
29
30type NamedAllFiltered struct {
31 A *string
32}
33
34type NamedNoneFiltered struct {
35 A *string `android:"arch_variant"`
36}
37
38func TestFilterArchStruct(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -070039 t.Parallel()
Colin Crosscb988072019-01-24 14:58:11 -080040 tests := []struct {
41 name string
42 in interface{}
43 out interface{}
44 filtered bool
45 }{
46 // Property tests
47 {
48 name: "basic",
49 in: &struct {
50 A *string `android:"arch_variant"`
51 B *string
52 }{},
53 out: &struct {
54 A *string
55 }{},
56 filtered: true,
57 },
58 {
Colin Crossb4fecbf2020-01-21 11:38:47 -080059 name: "tags",
60 in: &struct {
61 A *string `android:"arch_variant"`
62 B *string `android:"arch_variant,path"`
63 C *string `android:"arch_variant,path,variant_prepend"`
64 D *string `android:"path,variant_prepend,arch_variant"`
65 E *string `android:"path"`
66 F *string
67 }{},
68 out: &struct {
69 A *string
70 B *string
71 C *string
72 D *string
73 }{},
74 filtered: true,
75 },
76 {
Colin Crosscb988072019-01-24 14:58:11 -080077 name: "all filtered",
78 in: &struct {
79 A *string
80 }{},
81 out: nil,
82 filtered: true,
83 },
84 {
85 name: "none filtered",
86 in: &struct {
87 A *string `android:"arch_variant"`
88 }{},
89 out: &struct {
90 A *string `android:"arch_variant"`
91 }{},
92 filtered: false,
93 },
94
95 // Sub-struct tests
96 {
97 name: "substruct",
98 in: &struct {
99 A struct {
100 A *string `android:"arch_variant"`
101 B *string
102 } `android:"arch_variant"`
103 }{},
104 out: &struct {
105 A struct {
106 A *string
107 }
108 }{},
109 filtered: true,
110 },
111 {
112 name: "substruct all filtered",
113 in: &struct {
114 A struct {
115 A *string
116 } `android:"arch_variant"`
117 }{},
118 out: nil,
119 filtered: true,
120 },
121 {
122 name: "substruct none filtered",
123 in: &struct {
124 A struct {
125 A *string `android:"arch_variant"`
126 } `android:"arch_variant"`
127 }{},
128 out: &struct {
129 A struct {
130 A *string `android:"arch_variant"`
131 } `android:"arch_variant"`
132 }{},
133 filtered: false,
134 },
135
136 // Named sub-struct tests
137 {
138 name: "named substruct",
139 in: &struct {
140 A Named `android:"arch_variant"`
141 }{},
142 out: &struct {
143 A struct {
144 A *string
145 }
146 }{},
147 filtered: true,
148 },
149 {
150 name: "substruct all filtered",
151 in: &struct {
152 A NamedAllFiltered `android:"arch_variant"`
153 }{},
154 out: nil,
155 filtered: true,
156 },
157 {
158 name: "substruct none filtered",
159 in: &struct {
160 A NamedNoneFiltered `android:"arch_variant"`
161 }{},
162 out: &struct {
163 A NamedNoneFiltered `android:"arch_variant"`
164 }{},
165 filtered: false,
166 },
167
168 // Pointer to sub-struct tests
169 {
170 name: "pointer substruct",
171 in: &struct {
172 A *struct {
173 A *string `android:"arch_variant"`
174 B *string
175 } `android:"arch_variant"`
176 }{},
177 out: &struct {
178 A *struct {
179 A *string
180 }
181 }{},
182 filtered: true,
183 },
184 {
185 name: "pointer substruct all filtered",
186 in: &struct {
187 A *struct {
188 A *string
189 } `android:"arch_variant"`
190 }{},
191 out: nil,
192 filtered: true,
193 },
194 {
195 name: "pointer substruct none filtered",
196 in: &struct {
197 A *struct {
198 A *string `android:"arch_variant"`
199 } `android:"arch_variant"`
200 }{},
201 out: &struct {
202 A *struct {
203 A *string `android:"arch_variant"`
204 } `android:"arch_variant"`
205 }{},
206 filtered: false,
207 },
208
209 // Pointer to named sub-struct tests
210 {
211 name: "pointer named substruct",
212 in: &struct {
213 A *Named `android:"arch_variant"`
214 }{},
215 out: &struct {
216 A *struct {
217 A *string
218 }
219 }{},
220 filtered: true,
221 },
222 {
223 name: "pointer substruct all filtered",
224 in: &struct {
225 A *NamedAllFiltered `android:"arch_variant"`
226 }{},
227 out: nil,
228 filtered: true,
229 },
230 {
231 name: "pointer substruct none filtered",
232 in: &struct {
233 A *NamedNoneFiltered `android:"arch_variant"`
234 }{},
235 out: &struct {
236 A *NamedNoneFiltered `android:"arch_variant"`
237 }{},
238 filtered: false,
239 },
240 }
241
242 for _, test := range tests {
243 t.Run(test.name, func(t *testing.T) {
Colin Cross74449102019-09-25 11:26:40 -0700244 out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
Colin Crosscb988072019-01-24 14:58:11 -0800245 if filtered != test.filtered {
246 t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
247 }
248 expected := reflect.TypeOf(test.out)
249 if out != expected {
250 t.Errorf("expected type %v, got %v", expected, out)
251 }
252 })
253 }
254}
Colin Cross158eeb72019-10-16 13:06:07 -0700255
256type archTestModule struct {
257 ModuleBase
258 props struct {
259 Deps []string
260 }
261}
262
263func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
264}
265
266func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
267 ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
268}
269
270func archTestModuleFactory() Module {
271 m := &archTestModule{}
272 m.AddProperties(&m.props)
273 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
274 return m
275}
276
277func TestArchMutator(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700278 t.Parallel()
Colin Cross158eeb72019-10-16 13:06:07 -0700279 var buildOSVariants []string
280 var buildOS32Variants []string
281 switch runtime.GOOS {
282 case "linux":
283 buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
284 buildOS32Variants = []string{"linux_glibc_x86"}
285 case "darwin":
286 buildOSVariants = []string{"darwin_x86_64"}
287 buildOS32Variants = nil
288 }
289
290 bp := `
291 module {
292 name: "foo",
293 }
294
295 module {
296 name: "bar",
297 host_supported: true,
298 }
299
300 module {
301 name: "baz",
302 device_supported: false,
303 }
304
305 module {
306 name: "qux",
307 host_supported: true,
308 compile_multilib: "32",
309 }
310 `
311
Colin Cross158eeb72019-10-16 13:06:07 -0700312 testCases := []struct {
313 name string
314 config func(Config)
315 fooVariants []string
316 barVariants []string
317 bazVariants []string
318 quxVariants []string
319 }{
320 {
321 name: "normal",
322 config: nil,
323 fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
324 barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
325 bazVariants: nil,
326 quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
327 },
328 {
329 name: "host-only",
330 config: func(config Config) {
331 config.BuildOSTarget = Target{}
332 config.BuildOSCommonTarget = Target{}
333 config.Targets[Android] = nil
334 },
335 fooVariants: nil,
336 barVariants: buildOSVariants,
337 bazVariants: nil,
338 quxVariants: buildOS32Variants,
339 },
340 }
341
342 enabledVariants := func(ctx *TestContext, name string) []string {
343 var ret []string
344 variants := ctx.ModuleVariantsForTests(name)
345 for _, variant := range variants {
346 m := ctx.ModuleForTests(name, variant)
347 if m.Module().Enabled() {
348 ret = append(ret, variant)
349 }
350 }
351 return ret
352 }
353
354 for _, tt := range testCases {
355 t.Run(tt.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800356 config := TestArchConfig(buildDir, nil, bp, nil)
357
Colin Cross158eeb72019-10-16 13:06:07 -0700358 ctx := NewTestArchContext()
Colin Cross4b49b762019-11-22 15:25:03 -0800359 ctx.RegisterModuleType("module", archTestModuleFactory)
Colin Cross98be1bb2019-12-13 20:41:13 -0800360 ctx.Register(config)
Colin Cross158eeb72019-10-16 13:06:07 -0700361 if tt.config != nil {
362 tt.config(config)
363 }
364
365 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
366 FailIfErrored(t, errs)
367 _, errs = ctx.PrepareBuildActions(config)
368 FailIfErrored(t, errs)
369
370 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
371 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
372 }
373
374 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
375 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
376 }
377
378 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
379 t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
380 }
381
382 if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
383 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
384 }
385 })
386 }
387}
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200388
389func TestArchMutatorNativeBridge(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700390 t.Parallel()
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200391 bp := `
392 // This module is only enabled for x86.
393 module {
394 name: "foo",
395 }
396
397 // This module is enabled for x86 and arm (via native bridge).
398 module {
399 name: "bar",
400 native_bridge_supported: true,
401 }
402
403 // This module is enabled for arm (native_bridge) only.
404 module {
405 name: "baz",
406 native_bridge_supported: true,
407 enabled: false,
408 target: {
409 native_bridge: {
410 enabled: true,
411 }
412 }
413 }
414 `
415
416 testCases := []struct {
417 name string
418 config func(Config)
419 fooVariants []string
420 barVariants []string
421 bazVariants []string
422 }{
423 {
424 name: "normal",
425 config: nil,
426 fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
427 barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
428 bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
429 },
430 }
431
432 enabledVariants := func(ctx *TestContext, name string) []string {
433 var ret []string
434 variants := ctx.ModuleVariantsForTests(name)
435 for _, variant := range variants {
436 m := ctx.ModuleForTests(name, variant)
437 if m.Module().Enabled() {
438 ret = append(ret, variant)
439 }
440 }
441 return ret
442 }
443
444 for _, tt := range testCases {
445 t.Run(tt.name, func(t *testing.T) {
446 config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
447
448 ctx := NewTestArchContext()
449 ctx.RegisterModuleType("module", archTestModuleFactory)
450 ctx.Register(config)
451 if tt.config != nil {
452 tt.config(config)
453 }
454
455 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
456 FailIfErrored(t, errs)
457 _, errs = ctx.PrepareBuildActions(config)
458 FailIfErrored(t, errs)
459
460 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
461 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
462 }
463
464 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
465 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
466 }
467
468 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
469 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
470 }
471 })
472 }
473}