blob: 7caf8378fbdfa3515efe4437497ac866e42220d4 [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) {
39 tests := []struct {
40 name string
41 in interface{}
42 out interface{}
43 filtered bool
44 }{
45 // Property tests
46 {
47 name: "basic",
48 in: &struct {
49 A *string `android:"arch_variant"`
50 B *string
51 }{},
52 out: &struct {
53 A *string
54 }{},
55 filtered: true,
56 },
57 {
Colin Crossb4fecbf2020-01-21 11:38:47 -080058 name: "tags",
59 in: &struct {
60 A *string `android:"arch_variant"`
61 B *string `android:"arch_variant,path"`
62 C *string `android:"arch_variant,path,variant_prepend"`
63 D *string `android:"path,variant_prepend,arch_variant"`
64 E *string `android:"path"`
65 F *string
66 }{},
67 out: &struct {
68 A *string
Liz Kammer4562a3b2021-04-21 18:15:34 -040069 B *string `android:"path"`
70 C *string `android:"path"`
71 D *string `android:"path"`
Colin Crossb4fecbf2020-01-21 11:38:47 -080072 }{},
73 filtered: true,
74 },
75 {
Colin Crosscb988072019-01-24 14:58:11 -080076 name: "all filtered",
77 in: &struct {
78 A *string
79 }{},
80 out: nil,
81 filtered: true,
82 },
83 {
84 name: "none filtered",
85 in: &struct {
86 A *string `android:"arch_variant"`
87 }{},
88 out: &struct {
89 A *string `android:"arch_variant"`
90 }{},
91 filtered: false,
92 },
93
94 // Sub-struct tests
95 {
96 name: "substruct",
97 in: &struct {
98 A struct {
99 A *string `android:"arch_variant"`
100 B *string
101 } `android:"arch_variant"`
102 }{},
103 out: &struct {
104 A struct {
105 A *string
106 }
107 }{},
108 filtered: true,
109 },
110 {
111 name: "substruct all filtered",
112 in: &struct {
113 A struct {
114 A *string
115 } `android:"arch_variant"`
116 }{},
117 out: nil,
118 filtered: true,
119 },
120 {
121 name: "substruct none filtered",
122 in: &struct {
123 A struct {
124 A *string `android:"arch_variant"`
125 } `android:"arch_variant"`
126 }{},
127 out: &struct {
128 A struct {
129 A *string `android:"arch_variant"`
130 } `android:"arch_variant"`
131 }{},
132 filtered: false,
133 },
134
135 // Named sub-struct tests
136 {
137 name: "named substruct",
138 in: &struct {
139 A Named `android:"arch_variant"`
140 }{},
141 out: &struct {
142 A struct {
143 A *string
144 }
145 }{},
146 filtered: true,
147 },
148 {
149 name: "substruct all filtered",
150 in: &struct {
151 A NamedAllFiltered `android:"arch_variant"`
152 }{},
153 out: nil,
154 filtered: true,
155 },
156 {
157 name: "substruct none filtered",
158 in: &struct {
159 A NamedNoneFiltered `android:"arch_variant"`
160 }{},
161 out: &struct {
162 A NamedNoneFiltered `android:"arch_variant"`
163 }{},
164 filtered: false,
165 },
166
167 // Pointer to sub-struct tests
168 {
169 name: "pointer substruct",
170 in: &struct {
171 A *struct {
172 A *string `android:"arch_variant"`
173 B *string
174 } `android:"arch_variant"`
175 }{},
176 out: &struct {
177 A *struct {
178 A *string
179 }
180 }{},
181 filtered: true,
182 },
183 {
184 name: "pointer substruct all filtered",
185 in: &struct {
186 A *struct {
187 A *string
188 } `android:"arch_variant"`
189 }{},
190 out: nil,
191 filtered: true,
192 },
193 {
194 name: "pointer substruct none filtered",
195 in: &struct {
196 A *struct {
197 A *string `android:"arch_variant"`
198 } `android:"arch_variant"`
199 }{},
200 out: &struct {
201 A *struct {
202 A *string `android:"arch_variant"`
203 } `android:"arch_variant"`
204 }{},
205 filtered: false,
206 },
207
208 // Pointer to named sub-struct tests
209 {
210 name: "pointer named substruct",
211 in: &struct {
212 A *Named `android:"arch_variant"`
213 }{},
214 out: &struct {
215 A *struct {
216 A *string
217 }
218 }{},
219 filtered: true,
220 },
221 {
222 name: "pointer substruct all filtered",
223 in: &struct {
224 A *NamedAllFiltered `android:"arch_variant"`
225 }{},
226 out: nil,
227 filtered: true,
228 },
229 {
230 name: "pointer substruct none filtered",
231 in: &struct {
232 A *NamedNoneFiltered `android:"arch_variant"`
233 }{},
234 out: &struct {
235 A *NamedNoneFiltered `android:"arch_variant"`
236 }{},
237 filtered: false,
238 },
239 }
240
241 for _, test := range tests {
242 t.Run(test.name, func(t *testing.T) {
Colin Cross74449102019-09-25 11:26:40 -0700243 out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
Colin Crosscb988072019-01-24 14:58:11 -0800244 if filtered != test.filtered {
245 t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
246 }
247 expected := reflect.TypeOf(test.out)
248 if out != expected {
249 t.Errorf("expected type %v, got %v", expected, out)
250 }
251 })
252 }
253}
Colin Cross158eeb72019-10-16 13:06:07 -0700254
255type archTestModule struct {
256 ModuleBase
257 props struct {
258 Deps []string
259 }
260}
261
262func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
263}
264
265func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
266 ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
267}
268
269func archTestModuleFactory() Module {
270 m := &archTestModule{}
271 m.AddProperties(&m.props)
272 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
273 return m
274}
275
Paul Duffin738a6d52021-03-16 19:10:48 +0000276var prepareForArchTest = GroupFixturePreparers(
277 PrepareForTestWithArchMutator,
278 FixtureRegisterWithContext(func(ctx RegistrationContext) {
279 ctx.RegisterModuleType("module", archTestModuleFactory)
280 }),
281)
282
Colin Cross158eeb72019-10-16 13:06:07 -0700283func TestArchMutator(t *testing.T) {
284 var buildOSVariants []string
285 var buildOS32Variants []string
286 switch runtime.GOOS {
287 case "linux":
288 buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
289 buildOS32Variants = []string{"linux_glibc_x86"}
290 case "darwin":
291 buildOSVariants = []string{"darwin_x86_64"}
292 buildOS32Variants = nil
293 }
294
295 bp := `
296 module {
297 name: "foo",
298 }
299
300 module {
301 name: "bar",
302 host_supported: true,
303 }
304
305 module {
306 name: "baz",
307 device_supported: false,
308 }
309
310 module {
311 name: "qux",
312 host_supported: true,
313 compile_multilib: "32",
314 }
315 `
316
Colin Cross158eeb72019-10-16 13:06:07 -0700317 testCases := []struct {
318 name string
Paul Duffin738a6d52021-03-16 19:10:48 +0000319 preparer FixturePreparer
Colin Cross158eeb72019-10-16 13:06:07 -0700320 fooVariants []string
321 barVariants []string
322 bazVariants []string
323 quxVariants []string
324 }{
325 {
326 name: "normal",
Paul Duffin738a6d52021-03-16 19:10:48 +0000327 preparer: nil,
Colin Cross158eeb72019-10-16 13:06:07 -0700328 fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
329 barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
330 bazVariants: nil,
331 quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
332 },
333 {
334 name: "host-only",
Paul Duffin738a6d52021-03-16 19:10:48 +0000335 preparer: FixtureModifyConfig(func(config Config) {
Colin Cross158eeb72019-10-16 13:06:07 -0700336 config.BuildOSTarget = Target{}
337 config.BuildOSCommonTarget = Target{}
338 config.Targets[Android] = nil
Paul Duffin738a6d52021-03-16 19:10:48 +0000339 }),
Colin Cross158eeb72019-10-16 13:06:07 -0700340 fooVariants: nil,
341 barVariants: buildOSVariants,
342 bazVariants: nil,
343 quxVariants: buildOS32Variants,
344 },
345 }
346
347 enabledVariants := func(ctx *TestContext, name string) []string {
348 var ret []string
349 variants := ctx.ModuleVariantsForTests(name)
350 for _, variant := range variants {
351 m := ctx.ModuleForTests(name, variant)
352 if m.Module().Enabled() {
353 ret = append(ret, variant)
354 }
355 }
356 return ret
357 }
358
359 for _, tt := range testCases {
360 t.Run(tt.name, func(t *testing.T) {
Paul Duffin30ac3e72021-03-20 00:36:14 +0000361 result := GroupFixturePreparers(
Paul Duffin738a6d52021-03-16 19:10:48 +0000362 prepareForArchTest,
363 // Test specific preparer
364 OptionalFixturePreparer(tt.preparer),
365 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000366 ).RunTest(t)
Paul Duffin738a6d52021-03-16 19:10:48 +0000367 ctx := result.TestContext
Colin Cross158eeb72019-10-16 13:06:07 -0700368
369 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
370 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
371 }
372
373 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
374 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
375 }
376
377 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
378 t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
379 }
380
381 if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
382 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
383 }
384 })
385 }
386}
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200387
388func TestArchMutatorNativeBridge(t *testing.T) {
389 bp := `
390 // This module is only enabled for x86.
391 module {
392 name: "foo",
393 }
394
395 // This module is enabled for x86 and arm (via native bridge).
396 module {
397 name: "bar",
398 native_bridge_supported: true,
399 }
400
401 // This module is enabled for arm (native_bridge) only.
402 module {
403 name: "baz",
404 native_bridge_supported: true,
405 enabled: false,
406 target: {
407 native_bridge: {
408 enabled: true,
409 }
410 }
411 }
412 `
413
414 testCases := []struct {
415 name string
Paul Duffin738a6d52021-03-16 19:10:48 +0000416 preparer FixturePreparer
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200417 fooVariants []string
418 barVariants []string
419 bazVariants []string
420 }{
421 {
422 name: "normal",
Paul Duffin738a6d52021-03-16 19:10:48 +0000423 preparer: nil,
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200424 fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
425 barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
426 bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
427 },
428 }
429
430 enabledVariants := func(ctx *TestContext, name string) []string {
431 var ret []string
432 variants := ctx.ModuleVariantsForTests(name)
433 for _, variant := range variants {
434 m := ctx.ModuleForTests(name, variant)
435 if m.Module().Enabled() {
436 ret = append(ret, variant)
437 }
438 }
439 return ret
440 }
441
442 for _, tt := range testCases {
443 t.Run(tt.name, func(t *testing.T) {
Paul Duffin30ac3e72021-03-20 00:36:14 +0000444 result := GroupFixturePreparers(
Paul Duffin738a6d52021-03-16 19:10:48 +0000445 prepareForArchTest,
446 // Test specific preparer
447 OptionalFixturePreparer(tt.preparer),
448 // Prepare for native bridge test
449 FixtureModifyConfig(func(config Config) {
450 config.Targets[Android] = []Target{
451 {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
452 {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
453 {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false},
454 {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false},
455 }
456 }),
457 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000458 ).RunTest(t)
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200459
Paul Duffin738a6d52021-03-16 19:10:48 +0000460 ctx := result.TestContext
Victor Khimenkoc26fcf42020-05-07 22:16:33 +0200461
462 if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
463 t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
464 }
465
466 if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
467 t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
468 }
469
470 if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
471 t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
472 }
473 })
474 }
475}
Colin Cross4e879902021-07-23 00:18:41 +0000476
477type testArchPropertiesModule struct {
478 ModuleBase
479 properties struct {
480 A []string `android:"arch_variant"`
481 }
482}
483
484func (testArchPropertiesModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
485
486func TestArchProperties(t *testing.T) {
487 bp := `
488 module {
489 name: "foo",
490 a: ["root"],
491 arch: {
492 arm: {
493 a: ["arm"],
Colin Cross4e879902021-07-23 00:18:41 +0000494 },
495 arm64: {
496 a: ["arm64"],
Colin Cross4e879902021-07-23 00:18:41 +0000497 },
498 x86: { a: ["x86"] },
499 x86_64: { a: ["x86_64"] },
500 },
501 multilib: {
502 lib32: { a: ["lib32"] },
503 lib64: { a: ["lib64"] },
504 },
505 target: {
506 bionic: { a: ["bionic"] },
507 host: { a: ["host"] },
508 android: { a: ["android"] },
Colin Cross528d67e2021-07-23 22:23:07 +0000509 glibc: { a: ["glibc"] },
510 musl: { a: ["musl"] },
Colin Cross4e879902021-07-23 00:18:41 +0000511 linux_bionic: { a: ["linux_bionic"] },
512 linux: { a: ["linux"] },
513 linux_glibc: { a: ["linux_glibc"] },
Colin Cross528d67e2021-07-23 22:23:07 +0000514 linux_musl: { a: ["linux_musl"] },
Colin Cross4e879902021-07-23 00:18:41 +0000515 windows: { a: ["windows"], enabled: true },
516 darwin: { a: ["darwin"] },
517 not_windows: { a: ["not_windows"] },
518 android32: { a: ["android32"] },
519 android64: { a: ["android64"] },
520 android_arm: { a: ["android_arm"] },
521 android_arm64: { a: ["android_arm64"] },
522 linux_x86: { a: ["linux_x86"] },
523 linux_x86_64: { a: ["linux_x86_64"] },
524 linux_glibc_x86: { a: ["linux_glibc_x86"] },
525 linux_glibc_x86_64: { a: ["linux_glibc_x86_64"] },
Colin Cross528d67e2021-07-23 22:23:07 +0000526 linux_musl_x86: { a: ["linux_musl_x86"] },
527 linux_musl_x86_64: { a: ["linux_musl_x86_64"] },
Colin Cross4e879902021-07-23 00:18:41 +0000528 darwin_x86_64: { a: ["darwin_x86_64"] },
529 windows_x86: { a: ["windows_x86"] },
530 windows_x86_64: { a: ["windows_x86_64"] },
531 },
532 }
533 `
534
535 type result struct {
536 module string
537 variant string
538 property []string
539 }
540
541 testCases := []struct {
542 name string
543 goOS string
544 preparer FixturePreparer
545 results []result
546 }{
547 {
548 name: "default",
549 results: []result{
550 {
551 module: "foo",
552 variant: "android_arm64_armv8-a",
Liz Kammere8303bd2022-02-16 09:02:48 -0500553 property: []string{"root", "linux", "bionic", "android", "android64", "arm64", "lib64", "android_arm64"},
Colin Cross4e879902021-07-23 00:18:41 +0000554 },
555 {
556 module: "foo",
557 variant: "android_arm_armv7-a-neon",
Liz Kammere8303bd2022-02-16 09:02:48 -0500558 property: []string{"root", "linux", "bionic", "android", "android64", "arm", "lib32", "android_arm"},
Colin Cross4e879902021-07-23 00:18:41 +0000559 },
560 },
561 },
562 {
563 name: "linux",
564 goOS: "linux",
565 results: []result{
566 {
567 module: "foo",
568 variant: "linux_glibc_x86_64",
Colin Cross528d67e2021-07-23 22:23:07 +0000569 property: []string{"root", "host", "linux", "glibc", "linux_glibc", "not_windows", "x86_64", "lib64", "linux_x86_64", "linux_glibc_x86_64"},
Colin Cross4e879902021-07-23 00:18:41 +0000570 },
571 {
572 module: "foo",
573 variant: "linux_glibc_x86",
Colin Cross528d67e2021-07-23 22:23:07 +0000574 property: []string{"root", "host", "linux", "glibc", "linux_glibc", "not_windows", "x86", "lib32", "linux_x86", "linux_glibc_x86"},
Colin Cross4e879902021-07-23 00:18:41 +0000575 },
576 },
577 },
578 {
579 name: "windows",
580 goOS: "linux",
581 preparer: FixtureModifyConfig(func(config Config) {
582 config.Targets[Windows] = []Target{
583 {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
584 {Windows, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", true},
585 }
586 }),
587 results: []result{
588 {
589 module: "foo",
590 variant: "windows_x86_64",
591 property: []string{"root", "host", "windows", "x86_64", "lib64", "windows_x86_64"},
592 },
593 {
594 module: "foo",
595 variant: "windows_x86",
596 property: []string{"root", "host", "windows", "x86", "lib32", "windows_x86"},
597 },
598 },
599 },
600 {
Colin Cross528d67e2021-07-23 22:23:07 +0000601 name: "linux_musl",
602 goOS: "linux",
603 preparer: FixtureModifyConfig(modifyTestConfigForMusl),
604 results: []result{
605 {
606 module: "foo",
607 variant: "linux_musl_x86_64",
608 property: []string{"root", "host", "linux", "musl", "linux_glibc", "linux_musl", "not_windows", "x86_64", "lib64", "linux_x86_64", "linux_musl_x86_64", "linux_glibc_x86_64"},
609 },
610 {
611 module: "foo",
612 variant: "linux_musl_x86",
613 property: []string{"root", "host", "linux", "musl", "linux_glibc", "linux_musl", "not_windows", "x86", "lib32", "linux_x86", "linux_musl_x86", "linux_glibc_x86"},
614 },
615 },
616 },
617 {
Colin Cross4e879902021-07-23 00:18:41 +0000618 name: "darwin",
619 goOS: "darwin",
620 results: []result{
621 {
622 module: "foo",
623 variant: "darwin_x86_64",
624 property: []string{"root", "host", "darwin", "not_windows", "x86_64", "lib64", "darwin_x86_64"},
625 },
626 },
627 },
628 }
629
630 for _, tt := range testCases {
631 t.Run(tt.name, func(t *testing.T) {
632 if tt.goOS != "" && tt.goOS != runtime.GOOS {
633 t.Skipf("test requires runtime.GOOS==%s, got %s", tt.goOS, runtime.GOOS)
634 }
635 result := GroupFixturePreparers(
636 PrepareForTestWithArchMutator,
637 OptionalFixturePreparer(tt.preparer),
638 FixtureRegisterWithContext(func(ctx RegistrationContext) {
639 ctx.RegisterModuleType("module", func() Module {
640 module := &testArchPropertiesModule{}
641 module.AddProperties(&module.properties)
642 InitAndroidArchModule(module, HostAndDeviceDefault, MultilibBoth)
643 return module
644 })
645 }),
646 ).RunTestWithBp(t, bp)
647
648 for _, want := range tt.results {
649 t.Run(want.module+"_"+want.variant, func(t *testing.T) {
650 got := result.ModuleForTests(want.module, want.variant).Module().(*testArchPropertiesModule).properties.A
651 AssertArrayString(t, "arch mutator property", want.property, got)
652 })
653 }
654 })
655 }
656}