1// Copyright (C) 2019 The Android Open Source Project 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 aidl 16 17import ( 18 "fmt" 19 "os" 20 "path/filepath" 21 "strings" 22 "testing" 23 24 "github.com/google/blueprint" 25 "github.com/google/blueprint/proptools" 26 27 "android/soong/android" 28 "android/soong/apex" 29 "android/soong/cc" 30 "android/soong/genrule" 31 "android/soong/java" 32 "android/soong/rust" 33) 34 35func TestMain(m *testing.M) { 36 os.Exit(m.Run()) 37} 38 39func withFiles(files map[string][]byte) android.FixturePreparer { 40 return android.FixtureMergeMockFs(files) 41} 42 43func intPtr(v int) *int { 44 return &v 45} 46 47func setReleaseEnv() android.FixturePreparer { 48 return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 49 // Q is finalized as 29. No codename that is actively being developed. 50 variables.Platform_sdk_version = intPtr(29) 51 variables.Platform_sdk_codename = proptools.StringPtr("REL") 52 variables.Platform_sdk_final = proptools.BoolPtr(true) 53 variables.Platform_version_active_codenames = []string{} 54 }) 55} 56 57func _testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) android.FixturePreparer { 58 t.Helper() 59 60 preparers := []android.FixturePreparer{} 61 62 preparers = append(preparers, 63 cc.PrepareForTestWithCcDefaultModules, 64 java.PrepareForTestWithJavaDefaultModules, 65 genrule.PrepareForTestWithGenRuleBuildComponents, 66 ) 67 68 bp = bp + ` 69 package { 70 default_visibility: ["//visibility:public"], 71 } 72 java_defaults { 73 name: "aidl-java-module-defaults", 74 } 75 cc_defaults { 76 name: "aidl-cpp-module-defaults", 77 } 78 rust_defaults { 79 name: "aidl-rust-module-defaults", 80 } 81 cc_library { 82 name: "libbinder", 83 } 84 cc_library { 85 name: "libutils", 86 } 87 cc_library { 88 name: "libcutils", 89 } 90 cc_library { 91 name: "libbinder_ndk", 92 stubs: { 93 versions: ["29"], 94 } 95 } 96 ndk_library { 97 name: "libbinder_ndk", 98 symbol_file: "libbinder_ndk.map.txt", 99 first_version: "29", 100 } 101 cc_library { 102 name: "liblog", 103 no_libcrt: true, 104 nocrt: true, 105 system_shared_libs: [], 106 } 107 rust_library { 108 name: "libstd", 109 crate_name: "std", 110 srcs: [""], 111 no_stdlibs: true, 112 sysroot: true, 113 } 114 rust_library { 115 name: "libtest", 116 crate_name: "test", 117 srcs: [""], 118 no_stdlibs: true, 119 sysroot: true, 120 } 121 rust_library { 122 name: "liblazy_static", 123 crate_name: "lazy_static", 124 srcs: [""], 125 } 126 rust_library { 127 name: "libbinder_rs", 128 crate_name: "binder", 129 srcs: [""], 130 } 131 ` 132 133 preparers = append(preparers, android.FixtureWithRootAndroidBp(bp)) 134 preparers = append(preparers, android.FixtureAddTextFile("system/tools/aidl/build/Android.bp", ` 135 aidl_interfaces_metadata { 136 name: "aidl_metadata_json", 137 visibility: ["//system/tools/aidl:__subpackages__"], 138 } 139 `)) 140 141 preparers = append(preparers, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 142 // To keep tests stable, fix Platform_sdk_codename and Platform_sdk_final 143 // Use setReleaseEnv() to test release version 144 variables.Platform_sdk_version = intPtr(28) 145 variables.Platform_sdk_codename = proptools.StringPtr("Q") 146 variables.Platform_version_active_codenames = []string{"Q"} 147 variables.Platform_sdk_final = proptools.BoolPtr(false) 148 })) 149 150 preparers = append(preparers, customizers...) 151 152 preparers = append(preparers, 153 apex.PrepareForTestWithApexBuildComponents, 154 rust.PrepareForTestWithRustBuildComponents, 155 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { 156 ctx.RegisterModuleType("aidl_interface", aidlInterfaceFactory) 157 ctx.RegisterModuleType("aidl_interfaces_metadata", aidlInterfacesMetadataSingletonFactory) 158 ctx.RegisterModuleType("rust_defaults", func() android.Module { 159 return rust.DefaultsFactory() 160 }) 161 162 ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) { 163 ctx.BottomUp("checkImports", checkImports) 164 ctx.TopDown("createAidlInterface", createAidlInterfaceMutator) 165 }) 166 167 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 168 ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel() 169 ctx.BottomUp("recordVersions", recordVersions).Parallel() 170 ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel() 171 }) 172 }), 173 ) 174 175 return android.GroupFixturePreparers(preparers...) 176} 177 178func testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) (*android.TestContext, android.Config) { 179 t.Helper() 180 preparer := _testAidl(t, bp, customizers...) 181 result := preparer.RunTest(t) 182 return result.TestContext, result.Config 183} 184 185func testAidlError(t *testing.T, pattern, bp string, customizers ...android.FixturePreparer) { 186 t.Helper() 187 preparer := _testAidl(t, bp, customizers...) 188 preparer. 189 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). 190 RunTest(t) 191} 192 193// asserts that there are expected module regardless of variants 194func assertModulesExists(t *testing.T, ctx *android.TestContext, names ...string) { 195 t.Helper() 196 missing := []string{} 197 for _, name := range names { 198 variants := ctx.ModuleVariantsForTests(name) 199 if len(variants) == 0 { 200 missing = append(missing, name) 201 } 202 } 203 if len(missing) > 0 { 204 // find all the modules that do exist 205 allModuleNames := make(map[string]bool) 206 ctx.VisitAllModules(func(m blueprint.Module) { 207 allModuleNames[ctx.ModuleName(m)] = true 208 }) 209 t.Errorf("expected modules(%v) not found. all modules: %v", missing, android.SortedStringKeys(allModuleNames)) 210 } 211} 212 213func assertContains(t *testing.T, actual, expected string) { 214 t.Helper() 215 if !strings.Contains(actual, expected) { 216 t.Errorf("%q is not found in %q.", expected, actual) 217 } 218} 219 220func assertListContains(t *testing.T, actual []string, expected string) { 221 t.Helper() 222 for _, a := range actual { 223 if strings.Contains(a, expected) { 224 return 225 } 226 } 227 t.Errorf("%q is not found in %v.", expected, actual) 228} 229 230// Vintf module must have versions in release version 231func TestVintfWithoutVersionInRelease(t *testing.T) { 232 vintfWithoutVersionBp := ` 233 aidl_interface { 234 name: "foo", 235 stability: "vintf", 236 srcs: [ 237 "IFoo.aidl", 238 ], 239 backend: { 240 rust: { 241 enabled: true, 242 }, 243 }, 244 }` 245 expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.` 246 testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv()) 247 248 ctx, _ := testAidl(t, vintfWithoutVersionBp) 249 assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform") 250} 251 252// Check if using unstable version in release cause an error. 253func TestUnstableVersionUsageInRelease(t *testing.T) { 254 unstableVersionUsageInJavaBp := ` 255 aidl_interface { 256 name: "foo", 257 versions: [ 258 "1", 259 ], 260 srcs: [ 261 "IFoo.aidl", 262 ], 263 } 264 java_library { 265 name: "bar", 266 libs: ["foo-V2-java"], 267 }` 268 269 expectedError := `foo-V2-java is disallowed in release version because it is unstable.` 270 testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{ 271 "aidl_api/foo/1/foo.1.aidl": nil, 272 })) 273 274 testAidl(t, unstableVersionUsageInJavaBp, withFiles(map[string][]byte{ 275 "aidl_api/foo/1/foo.1.aidl": nil, 276 })) 277 278 // A stable version can be used in release version 279 stableVersionUsageInJavaBp := ` 280 aidl_interface { 281 name: "foo", 282 versions: [ 283 "1", 284 ], 285 srcs: [ 286 "IFoo.aidl", 287 ], 288 } 289 java_library { 290 name: "bar", 291 libs: ["foo-V1-java"], 292 }` 293 294 testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{ 295 "aidl_api/foo/1/foo.1.aidl": nil, 296 })) 297 298 testAidl(t, stableVersionUsageInJavaBp, withFiles(map[string][]byte{ 299 "aidl_api/foo/1/foo.1.aidl": nil, 300 })) 301} 302 303// The module which has never been frozen and is not "unstable" is not allowed in release version. 304func TestNonVersionedModuleUsageInRelease(t *testing.T) { 305 nonVersionedModuleUsageInJavaBp := ` 306 aidl_interface { 307 name: "foo", 308 srcs: [ 309 "IFoo.aidl", 310 ], 311 } 312 313 java_library { 314 name: "bar", 315 libs: ["foo-V1-java"], 316 }` 317 318 expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.` 319 testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv()) 320 testAidl(t, nonVersionedModuleUsageInJavaBp) 321 322 nonVersionedUnstableModuleUsageInJavaBp := ` 323 aidl_interface { 324 name: "foo", 325 srcs: [ 326 "IFoo.aidl", 327 ], 328 unstable: true, 329 } 330 331 java_library { 332 name: "bar", 333 libs: ["foo-java"], 334 }` 335 336 testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv()) 337 testAidl(t, nonVersionedUnstableModuleUsageInJavaBp) 338} 339 340func TestImportInRelease(t *testing.T) { 341 importInRelease := ` 342 aidl_interface { 343 name: "foo", 344 srcs: [ 345 "IFoo.aidl", 346 ], 347 imports: ["bar"], 348 versions: ["1"], 349 } 350 351 aidl_interface { 352 name: "bar", 353 srcs: [ 354 "IBar.aidl", 355 ], 356 versions: ["1"], 357 } 358 ` 359 360 testAidl(t, importInRelease, setReleaseEnv(), withFiles(map[string][]byte{ 361 "aidl_api/foo/1/foo.1.aidl": nil, 362 "aidl_api/foo/1/.hash": nil, 363 "aidl_api/bar/1/bar.1.aidl": nil, 364 "aidl_api/bar/1/.hash": nil, 365 })) 366} 367 368func TestUnstableVersionedModuleUsageInRelease(t *testing.T) { 369 nonVersionedModuleUsageInJavaBp := ` 370 aidl_interface { 371 name: "foo", 372 srcs: [ 373 "IFoo.aidl", 374 ], 375 versions: ["1"], 376 } 377 378 java_library { 379 name: "bar", 380 libs: ["foo-V2-java"], 381 }` 382 383 expectedError := `Android.bp:10:2: module \"bar\" variant \"android_common\": foo-V2-java is disallowed in release version because it is unstable, and its \"owner\" property is missing.` 384 testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv()) 385 testAidl(t, nonVersionedModuleUsageInJavaBp, withFiles(map[string][]byte{ 386 "aidl_api/foo/1/foo.1.aidl": nil, 387 })) 388} 389 390func TestUnstableModules(t *testing.T) { 391 testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, ` 392 aidl_interface { 393 name: "foo", 394 stability: "vintf", 395 unstable: true, 396 srcs: [ 397 "IFoo.aidl", 398 ], 399 backend: { 400 rust: { 401 enabled: true, 402 }, 403 }, 404 } 405 `) 406 407 testAidlError(t, `module "foo_interface": versions: cannot have versions for an unstable interface`, ` 408 aidl_interface { 409 name: "foo", 410 versions: [ 411 "1", 412 ], 413 unstable: true, 414 srcs: [ 415 "IFoo.aidl", 416 ], 417 backend: { 418 rust: { 419 enabled: true, 420 }, 421 }, 422 } 423 `) 424 425 ctx, _ := testAidl(t, ` 426 aidl_interface { 427 name: "foo", 428 unstable: true, 429 srcs: [ 430 "IFoo.aidl", 431 ], 432 backend: { 433 rust: { 434 enabled: true, 435 }, 436 }, 437 } 438 `) 439 440 assertModulesExists(t, ctx, "foo-java", "foo-rust", "foo-cpp", "foo-ndk", "foo-ndk_platform") 441} 442 443func TestCreatesModulesWithNoVersions(t *testing.T) { 444 ctx, _ := testAidl(t, ` 445 aidl_interface { 446 name: "foo", 447 srcs: [ 448 "IFoo.aidl", 449 ], 450 backend: { 451 rust: { 452 enabled: true, 453 }, 454 }, 455 } 456 `) 457 458 assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform") 459} 460 461func TestCreatesModulesWithFrozenVersions(t *testing.T) { 462 // Each version should be under aidl_api/<name>/<ver> 463 testAidlError(t, `aidl_api/foo/1`, ` 464 aidl_interface { 465 name: "foo", 466 srcs: [ 467 "IFoo.aidl", 468 ], 469 versions: [ 470 "1", 471 ], 472 backend: { 473 rust: { 474 enabled: true, 475 }, 476 }, 477 } 478 `) 479 480 ctx, _ := testAidl(t, ` 481 aidl_interface { 482 name: "foo", 483 srcs: [ 484 "IFoo.aidl", 485 ], 486 versions: [ 487 "1", 488 ], 489 backend: { 490 rust: { 491 enabled: true, 492 }, 493 }, 494 } 495 `, withFiles(map[string][]byte{ 496 "aidl_api/foo/1/foo.1.aidl": nil, 497 })) 498 499 // For frozen version "1" 500 assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform") 501 502 // For ToT (current) 503 assertModulesExists(t, ctx, "foo-V2-java", "foo-V2-rust", "foo-V2-cpp", "foo-V2-ndk", "foo-V2-ndk_platform") 504} 505 506func TestErrorsWithUnsortedVersions(t *testing.T) { 507 testAidlError(t, `versions: should be sorted`, ` 508 aidl_interface { 509 name: "foo", 510 srcs: [ 511 "IFoo.aidl", 512 ], 513 versions: [ 514 "2", 515 "1", 516 ], 517 backend: { 518 rust: { 519 enabled: true, 520 }, 521 }, 522 } 523 `) 524} 525 526func TestErrorsWithDuplicateVersions(t *testing.T) { 527 testAidlError(t, `versions: duplicate`, ` 528 aidl_interface { 529 name: "foo", 530 srcs: [ 531 "IFoo.aidl", 532 ], 533 versions: [ 534 "1", 535 "1", 536 ], 537 } 538 `) 539} 540 541func TestErrorsWithNonPositiveVersions(t *testing.T) { 542 testAidlError(t, `versions: should be > 0`, ` 543 aidl_interface { 544 name: "foo", 545 srcs: [ 546 "IFoo.aidl", 547 ], 548 versions: [ 549 "-1", 550 "1", 551 ], 552 } 553 `) 554} 555 556func TestErrorsWithNonIntegerVersions(t *testing.T) { 557 testAidlError(t, `versions: "first" is not an integer`, ` 558 aidl_interface { 559 name: "foo", 560 srcs: [ 561 "IFoo.aidl", 562 ], 563 versions: [ 564 "first", 565 ], 566 } 567 `) 568} 569 570const ( 571 androidVariant = "android_common" 572 nativeVariant = "android_arm_armv7-a-neon_shared" 573 nativeRustVariant = "android_arm_armv7-a-neon_dylib" 574) 575 576func TestNativeOutputIsAlwaysVersioned(t *testing.T) { 577 var ctx *android.TestContext 578 assertOutput := func(moduleName, variant, outputFilename string) { 579 t.Helper() 580 producer, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer) 581 if !ok { 582 t.Errorf("%s(%s): should be OutputFileProducer.", moduleName, variant) 583 } 584 paths, err := producer.OutputFiles("") 585 if err != nil { 586 t.Errorf("%s(%s): failed to get OutputFiles: %v", moduleName, variant, err) 587 } 588 if len(paths) != 1 || paths[0].Base() != outputFilename { 589 t.Errorf("%s(%s): expected output %q, but got %v", moduleName, variant, outputFilename, paths) 590 } 591 } 592 593 // No versions 594 ctx, _ = testAidl(t, ` 595 aidl_interface { 596 name: "foo", 597 srcs: [ 598 "IFoo.aidl", 599 ], 600 backend: { 601 rust: { 602 enabled: true, 603 }, 604 }, 605 } 606 `) 607 // Even though there is no version, generated modules have version(V1) unless it isn't an unstable interface. 608 assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar") 609 610 assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so") 611 assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so") 612 613 // With versions: "1", "2" 614 ctx, _ = testAidl(t, ` 615 aidl_interface { 616 name: "foo", 617 srcs: [ 618 "IFoo.aidl", 619 ], 620 versions: [ 621 "1", "2", 622 ], 623 backend: { 624 rust: { 625 enabled: true, 626 }, 627 }, 628 } 629 `, withFiles(map[string][]byte{ 630 "aidl_api/foo/1/foo.1.aidl": nil, 631 "aidl_api/foo/2/foo.2.aidl": nil, 632 })) 633 634 // alias for the latest frozen version (=2) 635 assertOutput("foo-V2-java", androidVariant, "foo-V2-java.jar") 636 assertOutput("foo-V2-cpp", nativeVariant, "foo-V2-cpp.so") 637 assertOutput("foo-V2-rust", nativeRustVariant, "libfoo_V2.dylib.so") 638 639 // frozen "1" 640 assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar") 641 assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so") 642 assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so") 643 644 // tot 645 assertOutput("foo-V3-java", androidVariant, "foo-V3-java.jar") 646 assertOutput("foo-V3-cpp", nativeVariant, "foo-V3-cpp.so") 647 assertOutput("foo-V3-rust", nativeRustVariant, "libfoo_V3.dylib.so") 648 649 // skip ndk/ndk_platform since they follow the same rule with cpp 650} 651 652func TestImports(t *testing.T) { 653 testAidlError(t, `Import does not exist:`, ` 654 aidl_interface { 655 name: "foo", 656 srcs: [ 657 "IFoo.aidl", 658 ], 659 imports: [ 660 "bar", 661 ] 662 } 663 `) 664 665 testAidlError(t, `backend.java.enabled: Java backend not enabled in the imported AIDL interface "bar"`, ` 666 aidl_interface { 667 name: "foo", 668 srcs: [ 669 "IFoo.aidl", 670 ], 671 imports: [ 672 "bar", 673 ] 674 } 675 aidl_interface { 676 name: "bar", 677 srcs: [ 678 "IBar.aidl", 679 ], 680 backend: { 681 java: { 682 enabled: false, 683 }, 684 }, 685 } 686 `) 687 688 testAidlError(t, `backend.cpp.enabled: C\+\+ backend not enabled in the imported AIDL interface "bar"`, ` 689 aidl_interface { 690 name: "foo", 691 srcs: [ 692 "IFoo.aidl", 693 ], 694 imports: [ 695 "bar", 696 ] 697 } 698 aidl_interface { 699 name: "bar", 700 srcs: [ 701 "IBar.aidl", 702 ], 703 backend: { 704 cpp: { 705 enabled: false, 706 }, 707 }, 708 } 709 `) 710 711 ctx, _ := testAidl(t, ` 712 aidl_interface { 713 name: "foo", 714 srcs: [ 715 "IFoo.aidl", 716 ], 717 backend: { 718 rust: { 719 enabled: true, 720 }, 721 }, 722 imports: [ 723 "bar.1", 724 ] 725 } 726 aidl_interface { 727 name: "bar.1", 728 srcs: [ 729 "IBar.aidl", 730 ], 731 backend: { 732 rust: { 733 enabled: true, 734 }, 735 }, 736 } 737 `) 738 739 ldRule := ctx.ModuleForTests("foo-V1-cpp", nativeVariant).Rule("ld") 740 libFlags := ldRule.Args["libFlags"] 741 libBar := filepath.Join("bar.1-V1-cpp", nativeVariant, "bar.1-V1-cpp.so") 742 if !strings.Contains(libFlags, libBar) { 743 t.Errorf("%q is not found in %q", libBar, libFlags) 744 } 745 746 rustcRule := ctx.ModuleForTests("foo-V1-rust", nativeRustVariant).Rule("rustc") 747 libFlags = rustcRule.Args["libFlags"] 748 libBar = filepath.Join("out", "soong", ".intermediates", "bar.1-V1-rust", nativeRustVariant, "libbar_1_V1.dylib.so") 749 libBarFlag := "--extern bar_1=" + libBar 750 if !strings.Contains(libFlags, libBarFlag) { 751 t.Errorf("%q is not found in %q", libBarFlag, libFlags) 752 } 753} 754 755func TestDuplicatedVersions(t *testing.T) { 756 // foo depends on myiface-V2-ndk via direct dep and also on 757 // myiface-V1-ndk via indirect dep. This should be prohibited. 758 testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, ` 759 aidl_interface { 760 name: "myiface", 761 srcs: ["IFoo.aidl"], 762 versions: ["1", "2"], 763 } 764 765 cc_library { 766 name: "foo", 767 shared_libs: ["myiface-V2-ndk", "bar"], 768 } 769 770 cc_library { 771 name: "bar", 772 shared_libs: ["myiface-V1-ndk"], 773 } 774 775 `, withFiles(map[string][]byte{ 776 "aidl_api/myiface/1/myiface.1.aidl": nil, 777 "aidl_api/myiface/1/.hash": nil, 778 "aidl_api/myiface/2/myiface.2.aidl": nil, 779 "aidl_api/myiface/2/.hash": nil, 780 })) 781 testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, ` 782 aidl_interface { 783 name: "myiface", 784 srcs: ["IFoo.aidl"], 785 versions: ["1"], 786 } 787 788 aidl_interface { 789 name: "myiface2", 790 srcs: ["IBar.aidl"], 791 imports: ["myiface"] 792 } 793 794 cc_library { 795 name: "foobar", 796 shared_libs: ["myiface-V1-ndk", "myiface2-V1-ndk"], 797 } 798 799 `, withFiles(map[string][]byte{ 800 "aidl_api/myiface/1/myiface.1.aidl": nil, 801 "aidl_api/myiface/1/.hash": nil, 802 })) 803 testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk-source, myiface-V2-ndk`, ` 804 aidl_interface { 805 name: "myiface", 806 srcs: ["IFoo.aidl"], 807 versions: ["1"], 808 backend: { 809 ndk: { 810 srcs_available: true, 811 }, 812 }, 813 } 814 815 aidl_interface { 816 name: "myiface2", 817 srcs: ["IBar.aidl"], 818 imports: ["myiface"] 819 } 820 821 cc_library { 822 name: "foobar", 823 srcs: [":myiface-V1-ndk-source"], 824 shared_libs: ["myiface2-V1-ndk"], 825 } 826 827 `, withFiles(map[string][]byte{ 828 "aidl_api/myiface/1/myiface.1.aidl": nil, 829 "aidl_api/myiface/1/.hash": nil, 830 })) 831 testAidl(t, ` 832 aidl_interface { 833 name: "myiface", 834 srcs: ["IFoo.aidl"], 835 versions: ["1"], 836 backend: { 837 ndk: { 838 srcs_available: true, 839 }, 840 }, 841 } 842 843 aidl_interface { 844 name: "myiface2", 845 srcs: ["IBar.aidl"], 846 imports: ["myiface"] 847 } 848 849 cc_library { 850 name: "foobar", 851 srcs: [":myiface-V2-ndk-source"], 852 shared_libs: ["myiface2-V1-ndk"], 853 } 854 855 `, withFiles(map[string][]byte{ 856 "aidl_api/myiface/1/myiface.1.aidl": nil, 857 "aidl_api/myiface/1/.hash": nil, 858 })) 859 testAidl(t, ` 860 aidl_interface { 861 name: "myiface", 862 srcs: ["IFoo.aidl"], 863 versions: ["1"], 864 } 865 866 aidl_interface { 867 name: "myiface2", 868 srcs: ["IBar.aidl"], 869 imports: ["myiface"] 870 } 871 872 cc_library { 873 name: "foobar", 874 shared_libs: ["myiface-V2-ndk", "myiface2-V1-ndk"], 875 } 876 877 `, withFiles(map[string][]byte{ 878 "aidl_api/myiface/1/myiface.1.aidl": nil, 879 "aidl_api/myiface/1/.hash": nil, 880 })) 881} 882 883func TestUnstableVndkModule(t *testing.T) { 884 testAidlError(t, `module "myiface_interface": stability: must be "vintf" if the module is for VNDK.`, ` 885 aidl_interface { 886 name: "myiface", 887 srcs: ["IFoo.aidl"], 888 vendor_available: true, 889 product_available: true, 890 unstable: true, 891 vndk: { 892 enabled: true, 893 }, 894 } 895 `) 896 testAidlError(t, `module "myiface_interface": stability: must be "vintf" if the module is for VNDK.`, ` 897 aidl_interface { 898 name: "myiface", 899 vendor_available: true, 900 product_available: true, 901 srcs: ["IFoo.aidl"], 902 vndk: { 903 enabled: true, 904 }, 905 } 906 `) 907 testAidl(t, ` 908 aidl_interface { 909 name: "myiface", 910 vendor_available: true, 911 product_available: true, 912 srcs: ["IFoo.aidl"], 913 stability: "vintf", 914 vndk: { 915 enabled: true, 916 }, 917 } 918 `) 919} 920 921func TestCcModuleWithApexNameMacro(t *testing.T) { 922 ctx, _ := testAidl(t, ` 923 aidl_interface { 924 name: "myiface", 925 srcs: ["IFoo.aidl"], 926 backend: { 927 ndk: { 928 apex_available: ["myapex"], 929 }, 930 }, 931 } 932 apex { 933 name: "myapex", 934 key: "myapex.key", 935 native_shared_libs: ["myiface-V1-ndk_platform"], 936 updatable: false, 937 } 938 apex_key { 939 name: "myapex.key", 940 public_key: "testkey.avbpubkey", 941 private_key: "testkey.pem", 942 } 943 `, withFiles(map[string][]byte{ 944 "system/sepolicy/apex/myapex-file_contexts": nil, 945 })) 946 947 ccRule := ctx.ModuleForTests("myiface-V1-ndk_platform", "android_arm64_armv8-a_static_myapex").Rule("cc") 948 assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX__") 949 assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_NAME__='\"myapex\"'") 950 assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_MYAPEX__") 951} 952 953func TestSrcsAvailable(t *testing.T) { 954 bp := ` 955 aidl_interface { 956 name: "myiface", 957 srcs: ["IFoo.aidl"], 958 backend: { 959 java: { 960 srcs_available: %s, 961 }, 962 cpp: { 963 srcs_available: %s, 964 }, 965 }, 966 } 967 ` 968 customizer := withFiles(map[string][]byte{ 969 "otherpackage/Android.bp": []byte(` 970 java_library { 971 name: "javalib", 972 srcs: [":myiface-V1-java-source"], 973 } 974 cc_library_shared { 975 name: "cclib", 976 srcs: [":myiface-V1-cpp-source"], 977 } 978 `), 979 }) 980 ctx, _ := testAidl(t, fmt.Sprintf(bp, "true", "true"), customizer) 981 javaInputs := ctx.ModuleForTests("javalib", "android_common").Rule("javac").Inputs.Strings() 982 assertListContains(t, javaInputs, "myiface-V1-java-source/gen/IFoo.java") 983 ccInput := ctx.ModuleForTests("cclib", "android_arm64_armv8-a_shared").Rule("cc").Input.String() 984 assertContains(t, ccInput, "myiface-V1-cpp-source/gen/IFoo.cpp") 985 986 testAidlError(t, `depends on //.:myiface-V1-java-source which is not visible to this module`, 987 fmt.Sprintf(bp, "false", "true"), customizer) 988 testAidlError(t, `depends on //.:myiface-V1-cpp-source which is not visible to this module`, 989 fmt.Sprintf(bp, "true", "false"), customizer) 990} 991 992func TestRustDuplicateNames(t *testing.T) { 993 testAidl(t, ` 994 aidl_interface { 995 name: "myiface", 996 srcs: ["dir/a/Foo.aidl", "dir/b/Foo.aidl"], 997 backend: { 998 rust: { 999 enabled: true, 1000 }, 1001 }, 1002 } 1003 `) 1004} 1005 1006func TestAidlImportFlagsForIncludeDirs(t *testing.T) { 1007 customizer := withFiles(map[string][]byte{ 1008 "foo/Android.bp": []byte(` 1009 aidl_interface { 1010 name: "foo-iface", 1011 local_include_dir: "src", 1012 include_dirs: [ 1013 "path1", 1014 "path2/sub", 1015 ], 1016 srcs: [ 1017 "src/foo/Foo.aidl", 1018 ], 1019 imports: [ 1020 "bar-iface", 1021 ], 1022 versions: ["1", "2"], 1023 } 1024 aidl_interface { 1025 name: "bar-iface", 1026 local_include_dir: "src", 1027 srcs: [ 1028 "src/bar/Bar.aidl", 1029 ], 1030 } 1031 `), 1032 "foo/src/foo/Foo.aidl": nil, 1033 "foo/src/bar/Bar.aidl": nil, 1034 "foo/aidl_api/foo-iface/current/foo/Foo.aidl": nil, 1035 "foo/aidl_api/foo-iface/1/foo/Foo.aidl": nil, 1036 "foo/aidl_api/foo-iface/1/.hash": nil, 1037 "foo/aidl_api/foo-iface/2/foo/Foo.aidl": nil, 1038 "foo/aidl_api/foo-iface/2/.hash": nil, 1039 }) 1040 ctx, _ := testAidl(t, ``, customizer) 1041 1042 // compile for older version 1043 { 1044 rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp") 1045 imports := strings.Split(rule.Args["imports"], " ") 1046 android.AssertArrayString(t, "should import foo/1(target) and bar/current(imported)", []string{ 1047 "-Ifoo/aidl_api/foo-iface/1", 1048 "-Ipath1", 1049 "-Ipath2/sub", 1050 "-Ifoo/aidl_api/bar-iface/current", 1051 }, imports) 1052 } 1053 // compile for tot version 1054 { 1055 rule := ctx.ModuleForTests("foo-iface-V3-cpp-source", "").Output("foo/Foo.cpp") 1056 imports := strings.Split(rule.Args["imports"], " ") 1057 android.AssertArrayString(t, "aidlCompile should import ToT", []string{ 1058 "-Ifoo/src", 1059 "-Ipath1", 1060 "-Ipath2/sub", 1061 "-Ifoo/src", 1062 }, imports) 1063 } 1064} 1065 1066func TestSupportsGenruleAndFilegroup(t *testing.T) { 1067 customizer := withFiles(map[string][]byte{ 1068 "foo/Android.bp": []byte(` 1069 aidl_interface { 1070 name: "foo-iface", 1071 local_include_dir: "src", 1072 include_dirs: [ 1073 "path1", 1074 "path2/sub", 1075 ], 1076 srcs: [ 1077 "src/foo/Foo.aidl", 1078 ":filegroup1", 1079 ":gen1", 1080 ], 1081 imports: [ 1082 "bar-iface", 1083 ], 1084 versions: ["1"], 1085 } 1086 filegroup { 1087 name: "filegroup1", 1088 path: "filegroup/sub", 1089 srcs: [ 1090 "filegroup/sub/pkg/Bar.aidl", 1091 ], 1092 } 1093 genrule { 1094 name: "gen1", 1095 cmd: "generate baz/Baz.aidl", 1096 out: [ 1097 "baz/Baz.aidl", 1098 ] 1099 } 1100 aidl_interface { 1101 name: "bar-iface", 1102 local_include_dir: "src", 1103 srcs: [ 1104 "src/bar/Bar.aidl", 1105 ], 1106 } 1107 `), 1108 "foo/aidl_api/foo-iface/1/foo/Foo.aidl": nil, 1109 "foo/aidl_api/foo-iface/1/.hash": nil, 1110 "foo/filegroup/sub/pkg/Bar.aidl": nil, 1111 "foo/src/foo/Foo.aidl": nil, 1112 }) 1113 ctx, _ := testAidl(t, ``, customizer) 1114 1115 // aidlCompile for snapshots (v1) 1116 { 1117 rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp") 1118 imports := strings.Split(rule.Args["imports"], " ") 1119 android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{ 1120 "-Ifoo/aidl_api/foo-iface/1", 1121 "-Ipath1", 1122 "-Ipath2/sub", 1123 "-Ifoo/aidl_api/bar-iface/current", 1124 }, imports) 1125 } 1126 // aidlCompile for ToT (v2) 1127 { 1128 rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("foo/Foo.cpp") 1129 imports := strings.Split(rule.Args["imports"], " ") 1130 android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{ 1131 "-Ifoo/src", 1132 "-Ifoo/filegroup/sub", 1133 "-Iout/soong/.intermediates/foo/gen1/gen", 1134 "-Ipath1", 1135 "-Ipath2/sub", 1136 "-Ifoo/src", 1137 }, imports) 1138 } 1139 1140 // dumpapi 1141 { 1142 rule := ctx.ModuleForTests("foo-iface-api", "").Rule("aidlDumpApiRule") 1143 android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump srcs/filegroups/genrules", []string{ 1144 "foo/src/foo/Foo.aidl", 1145 "foo/filegroup/sub/pkg/Bar.aidl", 1146 "out/soong/.intermediates/foo/gen1/gen/baz/Baz.aidl", 1147 }, rule.Inputs) 1148 1149 dumpDir := "out/soong/.intermediates/foo/foo-iface-api/dump" 1150 android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump with rel paths", []string{ 1151 dumpDir + "/foo/Foo.aidl", 1152 dumpDir + "/pkg/Bar.aidl", 1153 dumpDir + "/baz/Baz.aidl", 1154 dumpDir + "/.hash", 1155 }, rule.Outputs.Paths()) 1156 1157 imports := strings.Split(rule.Args["imports"], " ") 1158 android.AssertArrayString(t, "dumpapi should import filegroup/genrule as well", []string{ 1159 // these are from foo-iface.srcs 1160 "-Ifoo/src", 1161 "-Ifoo/filegroup/sub", 1162 "-Iout/soong/.intermediates/foo/gen1/gen", 1163 1164 // this is from bar-iface.srcs 1165 "-Ifoo/src", 1166 1167 // this is from foo-iface.Local_include_dir 1168 "-Ifoo/src", 1169 1170 // these are from foo-iface.include_dirs 1171 "-Ipath1", 1172 "-Ipath2/sub", 1173 }, imports) 1174 } 1175} 1176 1177func TestAidlFlags(t *testing.T) { 1178 ctx, _ := testAidl(t, ` 1179 aidl_interface { 1180 name: "myiface", 1181 srcs: ["a/Foo.aidl", "b/Bar.aidl"], 1182 flags: ["-Weverything", "-Werror"], 1183 backend: { rust: { enabled: true }} 1184 } 1185 `) 1186 for module, outputs := range map[string][]string{ 1187 "myiface-V1-cpp-source": {"a/Foo.h", "b/Bar.h"}, 1188 "myiface-V1-java-source": {"a/Foo.java", "b/Bar.java"}, 1189 "myiface-V1-ndk-source": {"aidl/a/Foo.h", "aidl/b/Bar.h"}, 1190 "myiface-V1-rust-source": {"a/Foo.rs", "b/Bar.rs"}, 1191 } { 1192 for _, output := range outputs { 1193 t.Run(module+"/"+output, func(t *testing.T) { 1194 params := ctx.ModuleForTests(module, "").Output(output) 1195 assertContains(t, params.Args["optionalFlags"], "-Weverything") 1196 assertContains(t, params.Args["optionalFlags"], "-Werror") 1197 }) 1198 } 1199 } 1200} 1201 1202func TestAidlModuleNameContainsVersion(t *testing.T) { 1203 testAidlError(t, "aidl_interface should not have '-V<number> suffix", ` 1204 aidl_interface { 1205 name: "myiface-V2", 1206 srcs: ["a/Foo.aidl", "b/Bar.aidl"], 1207 } 1208 `) 1209 // Ugly, but okay 1210 testAidl(t, ` 1211 aidl_interface { 1212 name: "myiface-V2aa", 1213 srcs: ["a/Foo.aidl", "b/Bar.aidl"], 1214 } 1215 `) 1216} 1217 1218func TestExplicitAidlModuleImport(t *testing.T) { 1219 for _, importVersion := range []string{"V1", "V2"} { 1220 1221 ctx, _ := testAidl(t, ` 1222 aidl_interface { 1223 name: "foo", 1224 srcs: ["Foo.aidl"], 1225 versions: [ 1226 "1", 1227 ], 1228 imports: ["bar-`+importVersion+`"] 1229 } 1230 1231 aidl_interface { 1232 name: "bar", 1233 srcs: ["Bar.aidl"], 1234 versions: [ 1235 "1", 1236 ], 1237 } 1238 `, withFiles(map[string][]byte{ 1239 "aidl_api/foo/1/Foo.aidl": nil, 1240 "aidl_api/foo/1/.hash": nil, 1241 "aidl_api/bar/1/Bar.aidl": nil, 1242 "aidl_api/bar/1/.hash": nil, 1243 })) 1244 for _, foo := range []string{"foo-V1-cpp", "foo-V2-cpp"} { 1245 ldRule := ctx.ModuleForTests(foo, nativeVariant).Rule("ld") 1246 libFlags := ldRule.Args["libFlags"] 1247 libBar := filepath.Join("bar-"+importVersion+"-cpp", nativeVariant, "bar-"+importVersion+"-cpp.so") 1248 if !strings.Contains(libFlags, libBar) { 1249 t.Errorf("%q is not found in %q", libBar, libFlags) 1250 } 1251 1252 } 1253 } 1254 1255 testAidlError(t, "module \"foo_interface\": imports: \"foo\" depends on \"bar\" version \"3\"", ` 1256 aidl_interface { 1257 name: "foo", 1258 srcs: ["Foo.aidl"], 1259 versions: [ 1260 "1", 1261 ], 1262 imports: ["bar-V3"] 1263 } 1264 1265 aidl_interface { 1266 name: "bar", 1267 srcs: ["Bar.aidl"], 1268 versions: [ 1269 "1", 1270 ], 1271 } 1272 `, withFiles(map[string][]byte{ 1273 "aidl_api/foo/1/Foo.aidl": nil, 1274 "aidl_api/foo/1/.hash": nil, 1275 "aidl_api/bar/1/Bar.aidl": nil, 1276 "aidl_api/bar/1/.hash": nil, 1277 })) 1278} 1279