| // Copyright 2018 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package apex |
| |
| import ( |
| "io/ioutil" |
| "os" |
| "strings" |
| "testing" |
| |
| "github.com/google/blueprint/proptools" |
| |
| "android/soong/android" |
| "android/soong/cc" |
| "android/soong/java" |
| ) |
| |
| func testApex(t *testing.T, bp string) *android.TestContext { |
| config, buildDir := setup(t) |
| defer teardown(buildDir) |
| |
| ctx := android.NewTestArchContext() |
| ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory)) |
| ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory)) |
| ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory)) |
| ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory)) |
| ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory)) |
| ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) |
| |
| ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { |
| ctx.TopDown("apex_deps", apexDepsMutator) |
| ctx.BottomUp("apex", apexMutator) |
| ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel() |
| ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel() |
| }) |
| |
| ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory)) |
| ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory)) |
| ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory)) |
| ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory)) |
| ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory)) |
| ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory)) |
| ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory)) |
| ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory)) |
| ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory)) |
| ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory)) |
| ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory)) |
| ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) { |
| ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel() |
| }) |
| ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { |
| ctx.BottomUp("image", cc.ImageMutator).Parallel() |
| ctx.BottomUp("link", cc.LinkageMutator).Parallel() |
| ctx.BottomUp("vndk", cc.VndkMutator).Parallel() |
| ctx.BottomUp("version", cc.VersionMutator).Parallel() |
| ctx.BottomUp("begin", cc.BeginMutator).Parallel() |
| }) |
| |
| ctx.Register() |
| |
| bp = bp + ` |
| toolchain_library { |
| name: "libcompiler_rt-extras", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| toolchain_library { |
| name: "libatomic", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| toolchain_library { |
| name: "libgcc", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| toolchain_library { |
| name: "libgcc_stripped", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| toolchain_library { |
| name: "libclang_rt.builtins-aarch64-android", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| toolchain_library { |
| name: "libclang_rt.builtins-arm-android", |
| src: "", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| cc_object { |
| name: "crtbegin_so", |
| stl: "none", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| cc_object { |
| name: "crtend_so", |
| stl: "none", |
| vendor_available: true, |
| recovery_available: true, |
| } |
| |
| cc_object { |
| name: "crtbegin_static", |
| stl: "none", |
| } |
| |
| cc_object { |
| name: "crtend_android", |
| stl: "none", |
| } |
| |
| llndk_library { |
| name: "libc", |
| symbol_file: "", |
| } |
| |
| llndk_library { |
| name: "libm", |
| symbol_file: "", |
| } |
| |
| llndk_library { |
| name: "libdl", |
| symbol_file: "", |
| } |
| ` |
| |
| ctx.MockFileSystem(map[string][]byte{ |
| "Android.bp": []byte(bp), |
| "build/make/target/product/security": nil, |
| "apex_manifest.json": nil, |
| "AndroidManifest.xml": nil, |
| "system/sepolicy/apex/myapex-file_contexts": nil, |
| "system/sepolicy/apex/myapex_keytest-file_contexts": nil, |
| "system/sepolicy/apex/otherapex-file_contexts": nil, |
| "mylib.cpp": nil, |
| "myprebuilt": nil, |
| "my_include": nil, |
| "vendor/foo/devkeys/test.x509.pem": nil, |
| "vendor/foo/devkeys/test.pk8": nil, |
| "testkey.x509.pem": nil, |
| "testkey.pk8": nil, |
| "testkey.override.x509.pem": nil, |
| "testkey.override.pk8": nil, |
| "vendor/foo/devkeys/testkey.avbpubkey": nil, |
| "vendor/foo/devkeys/testkey.pem": nil, |
| "NOTICE": nil, |
| "custom_notice": nil, |
| "testkey2.avbpubkey": nil, |
| "testkey2.pem": nil, |
| "myapex-arm64.apex": nil, |
| "myapex-arm.apex": nil, |
| "frameworks/base/api/current.txt": nil, |
| }) |
| _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) |
| android.FailIfErrored(t, errs) |
| _, errs = ctx.PrepareBuildActions(config) |
| android.FailIfErrored(t, errs) |
| |
| return ctx |
| } |
| |
| func setup(t *testing.T) (config android.Config, buildDir string) { |
| buildDir, err := ioutil.TempDir("", "soong_apex_test") |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| config = android.TestArchConfig(buildDir, nil) |
| config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current") |
| config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test") |
| config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"} |
| config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q") |
| config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false) |
| return |
| } |
| |
| func teardown(buildDir string) { |
| os.RemoveAll(buildDir) |
| } |
| |
| // ensure that 'result' contains 'expected' |
| func ensureContains(t *testing.T, result string, expected string) { |
| if !strings.Contains(result, expected) { |
| t.Errorf("%q is not found in %q", expected, result) |
| } |
| } |
| |
| // ensures that 'result' does not contain 'notExpected' |
| func ensureNotContains(t *testing.T, result string, notExpected string) { |
| if strings.Contains(result, notExpected) { |
| t.Errorf("%q is found in %q", notExpected, result) |
| } |
| } |
| |
| func ensureListContains(t *testing.T, result []string, expected string) { |
| if !android.InList(expected, result) { |
| t.Errorf("%q is not found in %v", expected, result) |
| } |
| } |
| |
| func ensureListNotContains(t *testing.T, result []string, notExpected string) { |
| if android.InList(notExpected, result) { |
| t.Errorf("%q is found in %v", notExpected, result) |
| } |
| } |
| |
| // Minimal test |
| func TestBasicApex(t *testing.T) { |
| ctx := testApex(t, ` |
| apex_defaults { |
| name: "myapex-defaults", |
| manifest: ":myapex.manifest", |
| androidManifest: ":myapex.androidmanifest", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| multilib: { |
| both: { |
| binaries: ["foo",], |
| } |
| } |
| } |
| |
| apex { |
| name: "myapex", |
| defaults: ["myapex-defaults"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| filegroup { |
| name: "myapex.manifest", |
| srcs: ["apex_manifest.json"], |
| } |
| |
| filegroup { |
| name: "myapex.androidmanifest", |
| srcs: ["AndroidManifest.xml"], |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["mylib2"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_binary { |
| name: "foo", |
| srcs: ["mylib.cpp"], |
| compile_multilib: "both", |
| multilib: { |
| lib32: { |
| suffix: "32", |
| }, |
| lib64: { |
| suffix: "64", |
| }, |
| }, |
| symlinks: ["foo_link_"], |
| symlink_preferred_arch: true, |
| system_shared_libs: [], |
| static_executable: true, |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib2", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| notice: "custom_notice", |
| } |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| |
| optFlags := apexRule.Args["opt_flags"] |
| ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey") |
| |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| // Ensure that main rule creates an output |
| ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned") |
| |
| // Ensure that apex variant is created for the direct dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that apex variant is created for the indirect dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that both direct and indirect deps are copied into apex |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") |
| |
| // Ensure that the platform variant ends with _core_shared |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared") |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared") |
| |
| // Ensure that all symlinks are present. |
| found_foo_link_64 := false |
| found_foo := false |
| for _, cmd := range strings.Split(copyCmds, " && ") { |
| if strings.HasPrefix(cmd, "ln -s foo64") { |
| if strings.HasSuffix(cmd, "bin/foo") { |
| found_foo = true |
| } else if strings.HasSuffix(cmd, "bin/foo_link_64") { |
| found_foo_link_64 = true |
| } |
| } |
| } |
| good := found_foo && found_foo_link_64 |
| if !good { |
| t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds) |
| } |
| |
| apexMergeNoticeRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexMergeNoticeRule") |
| noticeInputs := strings.Split(apexMergeNoticeRule.Args["inputs"], " ") |
| if len(noticeInputs) != 3 { |
| t.Errorf("number of input notice files: expected = 3, actual = %d", len(noticeInputs)) |
| } |
| ensureListContains(t, noticeInputs, "NOTICE") |
| ensureListContains(t, noticeInputs, "custom_notice") |
| } |
| |
| func TestBasicZipApex(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| payload_type: "zip", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["mylib2"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib2", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule") |
| copyCmds := zipApexRule.Args["copy_commands"] |
| |
| // Ensure that main rule creates an output |
| ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned") |
| |
| // Ensure that APEX variant is created for the direct dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that APEX variant is created for the indirect dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that both direct and indirect deps are copied into apex |
| ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so") |
| ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so") |
| } |
| |
| func TestApexWithStubs(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib", "mylib3"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["mylib2", "mylib3"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib2", |
| srcs: ["mylib.cpp"], |
| cflags: ["-include mylib.h"], |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["1", "2", "3"], |
| }, |
| } |
| |
| cc_library { |
| name: "mylib3", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["mylib4"], |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["10", "11", "12"], |
| }, |
| } |
| |
| cc_library { |
| name: "mylib4", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| // Ensure that direct non-stubs dep is always included |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") |
| |
| // Ensure that indirect stubs dep is not included |
| ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") |
| |
| // Ensure that direct stubs dep is included |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so") |
| |
| mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"] |
| |
| // Ensure that mylib is linking with the latest version of stubs for mylib2 |
| ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_core_shared_3_myapex/mylib2.so") |
| // ... and not linking to the non-stub (impl) variant of mylib2 |
| ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_core_shared_myapex/mylib2.so") |
| |
| // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex) |
| ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_core_shared_myapex/mylib3.so") |
| // .. and not linking to the stubs variant of mylib3 |
| ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_core_shared_12_myapex/mylib3.so") |
| |
| // Ensure that stubs libs are built without -include flags |
| mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"] |
| ensureNotContains(t, mylib2Cflags, "-include ") |
| |
| // Ensure that genstub is invoked with --apex |
| ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_core_static_3_myapex").Rule("genStubSrc").Args["flags"]) |
| } |
| |
| func TestApexWithExplicitStubsDependency(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["libfoo#10"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "libfoo", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["libbar"], |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["10", "20", "30"], |
| }, |
| } |
| |
| cc_library { |
| name: "libbar", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| // Ensure that direct non-stubs dep is always included |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") |
| |
| // Ensure that indirect stubs dep is not included |
| ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so") |
| |
| // Ensure that dependency of stubs is not included |
| ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so") |
| |
| mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"] |
| |
| // Ensure that mylib is linking with version 10 of libfoo |
| ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_core_shared_10_myapex/libfoo.so") |
| // ... and not linking to the non-stub (impl) variant of libfoo |
| ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_core_shared_myapex/libfoo.so") |
| |
| libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_core_shared_10_myapex").Rule("ld").Args["libFlags"] |
| |
| // Ensure that libfoo stubs is not linking to libbar (since it is a stubs) |
| ensureNotContains(t, libFooStubsLdFlags, "libbar.so") |
| } |
| |
| func TestApexWithSystemLibsStubs(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["libdl#27"], |
| stl: "none", |
| } |
| |
| cc_library_shared { |
| name: "mylib_shared", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["libdl#27"], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "libc", |
| no_libgcc: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| } |
| |
| cc_library { |
| name: "libm", |
| no_libgcc: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| } |
| |
| cc_library { |
| name: "libdl", |
| no_libgcc: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| } |
| |
| cc_library { |
| name: "libBootstrap", |
| srcs: ["mylib.cpp"], |
| stl: "none", |
| bootstrap: true, |
| } |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| // Ensure that mylib, libm, libdl are included. |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") |
| ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so") |
| ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so") |
| |
| // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs) |
| ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so") |
| |
| mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"] |
| mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"] |
| mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_core_shared_myapex").Rule("cc").Args["cFlags"] |
| |
| // For dependency to libc |
| // Ensure that mylib is linking with the latest version of stubs |
| ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_core_shared_29_myapex/libc.so") |
| // ... and not linking to the non-stub (impl) variant |
| ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_core_shared_myapex/libc.so") |
| // ... Cflags from stub is correctly exported to mylib |
| ensureContains(t, mylibCFlags, "__LIBC_API__=29") |
| ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29") |
| |
| // For dependency to libm |
| // Ensure that mylib is linking with the non-stub (impl) variant |
| ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_core_shared_myapex/libm.so") |
| // ... and not linking to the stub variant |
| ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_core_shared_29_myapex/libm.so") |
| // ... and is not compiling with the stub |
| ensureNotContains(t, mylibCFlags, "__LIBM_API__=29") |
| ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29") |
| |
| // For dependency to libdl |
| // Ensure that mylib is linking with the specified version of stubs |
| ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_27_myapex/libdl.so") |
| // ... and not linking to the other versions of stubs |
| ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_28_myapex/libdl.so") |
| ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_29_myapex/libdl.so") |
| // ... and not linking to the non-stub (impl) variant |
| ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_myapex/libdl.so") |
| // ... Cflags from stub is correctly exported to mylib |
| ensureContains(t, mylibCFlags, "__LIBDL_API__=27") |
| ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27") |
| |
| // Ensure that libBootstrap is depending on the platform variant of bionic libs |
| libFlags := ctx.ModuleForTests("libBootstrap", "android_arm64_armv8-a_core_shared").Rule("ld").Args["libFlags"] |
| ensureContains(t, libFlags, "libc/android_arm64_armv8-a_core_shared/libc.so") |
| ensureContains(t, libFlags, "libm/android_arm64_armv8-a_core_shared/libm.so") |
| ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_core_shared/libdl.so") |
| } |
| |
| func TestFilesInSubDir(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| binaries: ["mybin"], |
| prebuilts: ["myetc"], |
| compile_multilib: "both", |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| prebuilt_etc { |
| name: "myetc", |
| src: "myprebuilt", |
| sub_dir: "foo/bar", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| relative_install_path: "foo/bar", |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_binary { |
| name: "mybin", |
| srcs: ["mylib.cpp"], |
| relative_install_path: "foo/bar", |
| system_shared_libs: [], |
| static_executable: true, |
| stl: "none", |
| } |
| `) |
| |
| generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig") |
| dirs := strings.Split(generateFsRule.Args["exec_paths"], " ") |
| |
| // Ensure that the subdirectories are all listed |
| ensureListContains(t, dirs, "etc") |
| ensureListContains(t, dirs, "etc/foo") |
| ensureListContains(t, dirs, "etc/foo/bar") |
| ensureListContains(t, dirs, "lib64") |
| ensureListContains(t, dirs, "lib64/foo") |
| ensureListContains(t, dirs, "lib64/foo/bar") |
| ensureListContains(t, dirs, "lib") |
| ensureListContains(t, dirs, "lib/foo") |
| ensureListContains(t, dirs, "lib/foo/bar") |
| |
| ensureListContains(t, dirs, "bin") |
| ensureListContains(t, dirs, "bin/foo") |
| ensureListContains(t, dirs, "bin/foo/bar") |
| } |
| |
| func TestUseVendor(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| use_vendor: true, |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| shared_libs: ["mylib2"], |
| system_shared_libs: [], |
| vendor_available: true, |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib2", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| vendor_available: true, |
| stl: "none", |
| } |
| `) |
| |
| inputsList := []string{} |
| for _, i := range ctx.ModuleForTests("myapex", "android_common_myapex").Module().BuildParamsForTests() { |
| for _, implicit := range i.Implicits { |
| inputsList = append(inputsList, implicit.String()) |
| } |
| } |
| inputsString := strings.Join(inputsList, " ") |
| |
| // ensure that the apex includes vendor variants of the direct and indirect deps |
| ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib.so") |
| ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib2.so") |
| |
| // ensure that the apex does not include core variants |
| ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib.so") |
| ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib2.so") |
| } |
| |
| func TestStaticLinking(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| stubs: { |
| versions: ["1", "2", "3"], |
| }, |
| } |
| |
| cc_binary { |
| name: "not_in_apex", |
| srcs: ["mylib.cpp"], |
| static_libs: ["mylib"], |
| static_executable: true, |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| ldFlags := ctx.ModuleForTests("not_in_apex", "android_arm64_armv8-a_core").Rule("ld").Args["libFlags"] |
| |
| // Ensure that not_in_apex is linking with the static variant of mylib |
| ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_core_static/mylib.a") |
| } |
| |
| func TestKeys(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex_keytest", |
| key: "myapex.key", |
| certificate: ":myapex.certificate", |
| native_shared_libs: ["mylib"], |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| android_app_certificate { |
| name: "myapex.certificate", |
| certificate: "testkey", |
| } |
| |
| android_app_certificate { |
| name: "myapex.certificate.override", |
| certificate: "testkey.override", |
| } |
| |
| `) |
| |
| // check the APEX keys |
| keys := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey) |
| |
| if keys.public_key_file.String() != "vendor/foo/devkeys/testkey.avbpubkey" { |
| t.Errorf("public key %q is not %q", keys.public_key_file.String(), |
| "vendor/foo/devkeys/testkey.avbpubkey") |
| } |
| if keys.private_key_file.String() != "vendor/foo/devkeys/testkey.pem" { |
| t.Errorf("private key %q is not %q", keys.private_key_file.String(), |
| "vendor/foo/devkeys/testkey.pem") |
| } |
| |
| // check the APK certs. It should be overridden to myapex.certificate.override |
| certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"] |
| if certs != "testkey.override.x509.pem testkey.override.pk8" { |
| t.Errorf("cert and private key %q are not %q", certs, |
| "testkey.override.509.pem testkey.override.pk8") |
| } |
| } |
| |
| func TestMacro(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex { |
| name: "otherapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| // non-APEX variant does not have __ANDROID__APEX__ defined |
| mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"] |
| ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex") |
| ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex") |
| |
| // APEX variant has __ANDROID_APEX__=<apexname> defined |
| mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"] |
| ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex") |
| ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex") |
| |
| // APEX variant has __ANDROID_APEX__=<apexname> defined |
| mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"] |
| ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex") |
| ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex") |
| } |
| |
| func TestHeaderLibsDependency(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library_headers { |
| name: "mylib_headers", |
| export_include_dirs: ["my_include"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| header_libs: ["mylib_headers"], |
| export_header_lib_headers: ["mylib_headers"], |
| stubs: { |
| versions: ["1", "2", "3"], |
| }, |
| } |
| |
| cc_library { |
| name: "otherlib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| shared_libs: ["mylib"], |
| } |
| `) |
| |
| cFlags := ctx.ModuleForTests("otherlib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"] |
| |
| // Ensure that the include path of the header lib is exported to 'otherlib' |
| ensureContains(t, cFlags, "-Imy_include") |
| } |
| |
| func TestNonTestApex(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib_common"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib_common", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| module := ctx.ModuleForTests("myapex", "android_common_myapex") |
| apexRule := module.Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| if apex, ok := module.Module().(*apexBundle); !ok || apex.testApex { |
| t.Log("Apex was a test apex!") |
| t.Fail() |
| } |
| // Ensure that main rule creates an output |
| ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned") |
| |
| // Ensure that apex variant is created for the direct dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that both direct and indirect deps are copied into apex |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so") |
| |
| // Ensure that the platform variant ends with _core_shared |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared") |
| |
| if !android.InAnyApex("mylib_common") { |
| t.Log("Found mylib_common not in any apex!") |
| t.Fail() |
| } |
| } |
| |
| func TestTestApex(t *testing.T) { |
| if android.InAnyApex("mylib_common_test") { |
| t.Fatal("mylib_common_test must not be used in any other tests since this checks that global state is not updated in an illegal way!") |
| } |
| ctx := testApex(t, ` |
| apex_test { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib_common_test"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib_common_test", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| module := ctx.ModuleForTests("myapex", "android_common_myapex") |
| apexRule := module.Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| if apex, ok := module.Module().(*apexBundle); !ok || !apex.testApex { |
| t.Log("Apex was not a test apex!") |
| t.Fail() |
| } |
| // Ensure that main rule creates an output |
| ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned") |
| |
| // Ensure that apex variant is created for the direct dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that both direct and indirect deps are copied into apex |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so") |
| |
| // Ensure that the platform variant ends with _core_shared |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared") |
| |
| if android.InAnyApex("mylib_common_test") { |
| t.Log("Found mylib_common_test in some apex!") |
| t.Fail() |
| } |
| } |
| |
| func TestApexWithTarget(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| multilib: { |
| first: { |
| native_shared_libs: ["mylib_common"], |
| } |
| }, |
| target: { |
| android: { |
| multilib: { |
| first: { |
| native_shared_libs: ["mylib"], |
| } |
| } |
| }, |
| host: { |
| multilib: { |
| first: { |
| native_shared_libs: ["mylib2"], |
| } |
| } |
| } |
| } |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| |
| cc_library { |
| name: "mylib_common", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| compile_multilib: "first", |
| } |
| |
| cc_library { |
| name: "mylib2", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| compile_multilib: "first", |
| } |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| // Ensure that main rule creates an output |
| ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned") |
| |
| // Ensure that apex variant is created for the direct dep |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex") |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex") |
| ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex") |
| |
| // Ensure that both direct and indirect deps are copied into apex |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") |
| ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so") |
| ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") |
| |
| // Ensure that the platform variant ends with _core_shared |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared") |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared") |
| ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared") |
| } |
| |
| func TestApexWithShBinary(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| binaries: ["myscript"], |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| } |
| |
| sh_binary { |
| name: "myscript", |
| src: "mylib.cpp", |
| filename: "myscript.sh", |
| sub_dir: "script", |
| } |
| `) |
| |
| apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule") |
| copyCmds := apexRule.Args["copy_commands"] |
| |
| ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh") |
| } |
| |
| func TestApexInProductPartition(t *testing.T) { |
| ctx := testApex(t, ` |
| apex { |
| name: "myapex", |
| key: "myapex.key", |
| native_shared_libs: ["mylib"], |
| product_specific: true, |
| } |
| |
| apex_key { |
| name: "myapex.key", |
| public_key: "testkey.avbpubkey", |
| private_key: "testkey.pem", |
| product_specific: true, |
| } |
| |
| cc_library { |
| name: "mylib", |
| srcs: ["mylib.cpp"], |
| system_shared_libs: [], |
| stl: "none", |
| } |
| `) |
| |
| apex := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle) |
| expected := "target/product/test_device/product/apex" |
| actual := apex.installDir.RelPathString() |
| if actual != expected { |
| t.Errorf("wrong install path. expected %q. actual %q", expected, actual) |
| } |
| } |
| |
| func TestApexKeyFromOtherModule(t *testing.T) { |
| ctx := testApex(t, ` |
| apex_key { |
| name: "myapex.key", |
| public_key: ":my.avbpubkey", |
| private_key: ":my.pem", |
| product_specific: true, |
| } |
| |
| filegroup { |
| name: "my.avbpubkey", |
| srcs: ["testkey2.avbpubkey"], |
| } |
| |
| filegroup { |
| name: "my.pem", |
| srcs: ["testkey2.pem"], |
| } |
| `) |
| |
| apex_key := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey) |
| expected_pubkey := "testkey2.avbpubkey" |
| actual_pubkey := apex_key.public_key_file.String() |
| if actual_pubkey != expected_pubkey { |
| t.Errorf("wrong public key path. expected %q. actual %q", expected_pubkey, actual_pubkey) |
| } |
| expected_privkey := "testkey2.pem" |
| actual_privkey := apex_key.private_key_file.String() |
| if actual_privkey != expected_privkey { |
| t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey) |
| } |
| } |
| |
| func TestPrebuilt(t *testing.T) { |
| ctx := testApex(t, ` |
| prebuilt_apex { |
| name: "myapex", |
| arch: { |
| arm64: { |
| src: "myapex-arm64.apex", |
| }, |
| arm: { |
| src: "myapex-arm.apex", |
| }, |
| }, |
| } |
| `) |
| |
| prebuilt := ctx.ModuleForTests("myapex", "android_common").Module().(*Prebuilt) |
| |
| expectedInput := "myapex-arm64.apex" |
| if prebuilt.inputApex.String() != expectedInput { |
| t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String()) |
| } |
| } |
| |
| func TestPrebuiltFilenameOverride(t *testing.T) { |
| ctx := testApex(t, ` |
| prebuilt_apex { |
| name: "myapex", |
| src: "myapex-arm.apex", |
| filename: "notmyapex.apex", |
| } |
| `) |
| |
| p := ctx.ModuleForTests("myapex", "android_common").Module().(*Prebuilt) |
| |
| expected := "notmyapex.apex" |
| if p.installFilename != expected { |
| t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename) |
| } |
| } |