Files
build_soong/apex/apex_test.go
Alex Light 0851b88eaf Add support for test_apex
Some test and other miscallaneous use-cases need apexs that are
installable but will not affect the installation of other artifacts
onto the device. For this purpose we added a test_apex type. These
test_apex targets create apex files and have all the normal attributes
but are not considered the source of any of their contents for the
device by the rest of the build-system.

Test: build and boot
Test: ALLOW_MISSING_DEPENDENCIES=true \
      DIST_DIR=$ANDROID_BUILD_TOP/out/dist \
      ./art/tools/dist_linux_bionic.sh -j72 showcommands com.android.runtime.host
Bug: 123591866
Bug: 123892969

Change-Id: I7f50be0ac0425cd87868145e18bcee6962d472ef
2019-02-07 16:52:20 -08:00

1114 lines
31 KiB
Go

// 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"
)
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.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_deps", apexDepsMutator)
ctx.BottomUp("apex", apexMutator)
})
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.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: "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/target/product/security": nil,
"apex_manifest.json": nil,
"system/sepolicy/apex/myapex-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,
"vendor/foo/devkeys/testkey.avbpubkey": nil,
"vendor/foo/devkeys/testkey.pem": 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")
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",
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",
}
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",
}
`)
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")
// 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)
}
}
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")
// TODO(b/123721777) respect relative path for binaries
// 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",
key: "myapex.key",
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",
}
`)
// check the APEX keys
keys := ctx.ModuleForTests("myapex.key", "").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
certs := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Args["certificates"]
if certs != "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8" {
t.Errorf("cert and private key %q are not %q", certs,
"vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.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")
}