c6f4b532f3
Tests that run against mainline modules generally need to be built twice: once for aosp (unsigned) and once for internal (signed). The override_android_test rule is really useful for generating a signed version of the unsigned test. However, mainline tests need to use a MainlineTestModuleController to only run tests on targets with the expected module. Since unsigned and signed mainline modules have different package names, this means the test config needs to be updated when overriding a test. Add a new "mainline_package_name" argument so that android test rules can update the targeted mainline package. Without this, the only way to create a mainline package test is to instead use android_test, which results in a lot of copy-pasta. Test: added tests to soong Test: manual, using a locally-modified RkpdAppUnitTest Test: test_config_fixer_test.py Change-Id: Idaffd63f225719a2bfda41018fda630b17db0080
3507 lines
96 KiB
Go
3507 lines
96 KiB
Go
// Copyright 2017 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 java
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/blueprint/proptools"
|
|
|
|
"android/soong/android"
|
|
"android/soong/cc"
|
|
"android/soong/dexpreopt"
|
|
)
|
|
|
|
// testApp runs tests using the prepareForJavaTest
|
|
//
|
|
// See testJava for an explanation as to how to stop using this deprecated method.
|
|
//
|
|
// deprecated
|
|
func testApp(t *testing.T, bp string) *android.TestContext {
|
|
t.Helper()
|
|
result := prepareForJavaTest.RunTestWithBp(t, bp)
|
|
return result.TestContext
|
|
}
|
|
|
|
func TestApp(t *testing.T) {
|
|
resourceFiles := []string{
|
|
"res/layout/layout.xml",
|
|
"res/values/strings.xml",
|
|
"res/values-en-rUS/strings.xml",
|
|
}
|
|
|
|
compiledResourceFiles := []string{
|
|
"aapt2/res/layout_layout.xml.flat",
|
|
"aapt2/res/values_strings.arsc.flat",
|
|
"aapt2/res/values-en-rUS_strings.arsc.flat",
|
|
}
|
|
|
|
for _, moduleType := range []string{"android_app", "android_library"} {
|
|
t.Run(moduleType, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
android.FixtureModifyMockFS(func(fs android.MockFS) {
|
|
for _, file := range resourceFiles {
|
|
fs[file] = nil
|
|
}
|
|
}),
|
|
).RunTestWithBp(t, moduleType+` {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current"
|
|
}
|
|
`)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
var expectedLinkImplicits []string
|
|
|
|
manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
|
|
expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
|
|
|
|
frameworkRes := result.ModuleForTests("framework-res", "android_common")
|
|
expectedLinkImplicits = append(expectedLinkImplicits,
|
|
frameworkRes.Output("package-res.apk").Output.String())
|
|
|
|
// Test the mapping from input files to compiled output file names
|
|
compile := foo.Output(compiledResourceFiles[0])
|
|
android.AssertDeepEquals(t, "aapt2 compile inputs", resourceFiles, compile.Inputs.Strings())
|
|
|
|
compiledResourceOutputs := compile.Outputs.Strings()
|
|
sort.Strings(compiledResourceOutputs)
|
|
|
|
expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
|
|
|
|
list := foo.Output("aapt2/res.list")
|
|
expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
|
|
|
|
// Check that the link rule uses
|
|
res := result.ModuleForTests("foo", "android_common").Output("package-res.apk")
|
|
android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAppSplits(t *testing.T) {
|
|
ctx := testApp(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
package_splits: ["v4", "v7,hdpi"],
|
|
sdk_version: "current"
|
|
}`)
|
|
|
|
foo := ctx.ModuleForTests("foo", "android_common")
|
|
|
|
expectedOutputs := []string{
|
|
"out/soong/.intermediates/foo/android_common/foo.apk",
|
|
"out/soong/.intermediates/foo/android_common/foo_v4.apk",
|
|
"out/soong/.intermediates/foo/android_common/foo_v7_hdpi.apk",
|
|
}
|
|
for _, expectedOutput := range expectedOutputs {
|
|
foo.Output(expectedOutput)
|
|
}
|
|
|
|
outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
|
|
}
|
|
|
|
func TestPlatformAPIs(t *testing.T) {
|
|
testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
platform_apis: true,
|
|
}
|
|
`)
|
|
|
|
testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`)
|
|
|
|
testJavaError(t, "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true", `
|
|
android_app {
|
|
name: "bar",
|
|
srcs: ["b.java"],
|
|
}
|
|
`)
|
|
|
|
testJavaError(t, "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.", `
|
|
android_app {
|
|
name: "bar",
|
|
srcs: ["b.java"],
|
|
sdk_version: "system_current",
|
|
platform_apis: true,
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestAndroidAppLinkType(t *testing.T) {
|
|
testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
libs: ["bar"],
|
|
static_libs: ["baz"],
|
|
platform_apis: true,
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
srcs: ["b.java"],
|
|
}
|
|
|
|
android_library {
|
|
name: "baz",
|
|
sdk_version: "system_current",
|
|
srcs: ["c.java"],
|
|
}
|
|
`)
|
|
|
|
testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
libs: ["bar"],
|
|
sdk_version: "current",
|
|
static_libs: ["baz"],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
srcs: ["b.java"],
|
|
}
|
|
|
|
android_library {
|
|
name: "baz",
|
|
sdk_version: "system_current",
|
|
srcs: ["c.java"],
|
|
}
|
|
`)
|
|
|
|
testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
libs: ["bar"],
|
|
sdk_version: "system_current",
|
|
static_libs: ["baz"],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
srcs: ["b.java"],
|
|
}
|
|
|
|
android_library {
|
|
name: "baz",
|
|
sdk_version: "system_current",
|
|
srcs: ["c.java"],
|
|
}
|
|
`)
|
|
|
|
testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
libs: ["bar"],
|
|
sdk_version: "system_current",
|
|
static_libs: ["baz"],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
srcs: ["b.java"],
|
|
}
|
|
|
|
android_library {
|
|
name: "baz",
|
|
srcs: ["c.java"],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestUpdatableApps(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
expectedError string
|
|
}{
|
|
{
|
|
name: "Stable public SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "29",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "Stable system SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "system_29",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "Current public SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "Current system SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "system_current",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "Current module SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "module_current",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "Current core SDK",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "core_current",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
},
|
|
{
|
|
name: "No Platform APIs",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
platform_apis: true,
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
expectedError: "Updatable apps must use stable SDKs",
|
|
},
|
|
{
|
|
name: "No Core Platform APIs",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "core_platform",
|
|
min_sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
expectedError: "Updatable apps must use stable SDKs",
|
|
},
|
|
{
|
|
name: "No unspecified APIs",
|
|
bp: `android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
min_sdk_version: "29",
|
|
}`,
|
|
expectedError: "Updatable apps must use stable SDK",
|
|
},
|
|
{
|
|
name: "Must specify min_sdk_version",
|
|
bp: `android_app {
|
|
name: "app_without_min_sdk_version",
|
|
srcs: ["a.java"],
|
|
sdk_version: "29",
|
|
updatable: true,
|
|
}`,
|
|
expectedError: "updatable apps must set min_sdk_version.",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
errorHandler := android.FixtureExpectsNoErrors
|
|
if test.expectedError != "" {
|
|
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
|
|
}
|
|
android.GroupFixturePreparers(
|
|
prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{
|
|
"29": {"foo"},
|
|
})).
|
|
ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, test.bp)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
|
|
testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
static_libs: ["bar"],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
|
|
testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
sdk_version: "current",
|
|
min_sdk_version: "current",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
cc_library {
|
|
name: "libjni",
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
sdk_version: "current",
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
|
|
bp := cc.GatherRequiredDepsForTest(android.Android) + `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
cc_library {
|
|
name: "libjni",
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
}
|
|
`
|
|
fs := map[string][]byte{
|
|
"prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil,
|
|
"prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil,
|
|
"prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil,
|
|
"prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil,
|
|
}
|
|
|
|
ctx, _ := testJavaWithFS(t, bp, fs)
|
|
|
|
inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
|
|
var crtbeginFound, crtendFound bool
|
|
expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
|
|
"android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
|
|
expectedCrtEnd := ctx.ModuleForTests("crtend_so",
|
|
"android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
|
|
implicits := []string{}
|
|
for _, input := range inputs {
|
|
implicits = append(implicits, input.String())
|
|
if strings.HasSuffix(input.String(), expectedCrtBegin.String()) {
|
|
crtbeginFound = true
|
|
} else if strings.HasSuffix(input.String(), expectedCrtEnd.String()) {
|
|
crtendFound = true
|
|
}
|
|
}
|
|
if !crtbeginFound {
|
|
t.Error(fmt.Sprintf(
|
|
"expected implicit with suffix %q, have the following implicits:\n%s",
|
|
expectedCrtBegin, strings.Join(implicits, "\n")))
|
|
}
|
|
if !crtendFound {
|
|
t.Error(fmt.Sprintf(
|
|
"expected implicit with suffix %q, have the following implicits:\n%s",
|
|
expectedCrtEnd, strings.Join(implicits, "\n")))
|
|
}
|
|
}
|
|
|
|
func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) {
|
|
bp := cc.GatherRequiredDepsForTest(android.Android) + `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
sdk_version: "current",
|
|
min_sdk_version: "29", // this APK should support 29
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
cc_library {
|
|
name: "libjni",
|
|
stl: "none",
|
|
sdk_version: "current",
|
|
min_sdk_version: "current",
|
|
}
|
|
`
|
|
testJavaError(t, `"libjni" .*: min_sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp)
|
|
}
|
|
|
|
func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) {
|
|
bp := cc.GatherRequiredDepsForTest(android.Android) + `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
updatable: true,
|
|
sdk_version: "current",
|
|
min_sdk_version: "29", // this APK should support 29
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
cc_library {
|
|
name: "libjni",
|
|
stl: "none",
|
|
shared_libs: ["libbar"],
|
|
system_shared_libs: [],
|
|
sdk_version: "27",
|
|
min_sdk_version: "27",
|
|
}
|
|
|
|
cc_library {
|
|
name: "libbar",
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
sdk_version: "current",
|
|
min_sdk_version: "current",
|
|
}
|
|
`
|
|
testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp)
|
|
}
|
|
|
|
func TestResourceDirs(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
prop string
|
|
resources []string
|
|
}{
|
|
{
|
|
name: "no resource_dirs",
|
|
prop: "",
|
|
resources: []string{"res/res/values/strings.xml"},
|
|
},
|
|
{
|
|
name: "resource_dirs",
|
|
prop: `resource_dirs: ["res"]`,
|
|
resources: []string{"res/res/values/strings.xml"},
|
|
},
|
|
{
|
|
name: "empty resource_dirs",
|
|
prop: `resource_dirs: []`,
|
|
resources: nil,
|
|
},
|
|
}
|
|
|
|
fs := android.MockFS{
|
|
"res/res/values/strings.xml": nil,
|
|
}
|
|
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
%s
|
|
}
|
|
`
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
PrepareForTestWithOverlayBuildComponents,
|
|
fs.AddToFixture(),
|
|
).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
|
|
|
|
module := result.ModuleForTests("foo", "android_common")
|
|
resourceList := module.MaybeOutput("aapt2/res.list")
|
|
|
|
var resources []string
|
|
if resourceList.Rule != nil {
|
|
for _, compiledResource := range resourceList.Inputs.Strings() {
|
|
resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
|
|
}
|
|
}
|
|
|
|
android.AssertDeepEquals(t, "resource files", testCase.resources, resources)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLibraryAssets(t *testing.T) {
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
static_libs: ["lib1", "lib2", "lib3"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib1",
|
|
sdk_version: "current",
|
|
asset_dirs: ["assets_a"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib2",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_library {
|
|
name: "lib3",
|
|
sdk_version: "current",
|
|
static_libs: ["lib4"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib4",
|
|
sdk_version: "current",
|
|
asset_dirs: ["assets_b"],
|
|
}
|
|
`
|
|
|
|
testCases := []struct {
|
|
name string
|
|
assetFlag string
|
|
assetPackages []string
|
|
}{
|
|
{
|
|
name: "foo",
|
|
// lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
|
|
assetPackages: []string{
|
|
"out/soong/.intermediates/foo/android_common/aapt2/package-res.apk",
|
|
"out/soong/.intermediates/lib1/android_common/assets.zip",
|
|
"out/soong/.intermediates/lib3/android_common/assets.zip",
|
|
},
|
|
},
|
|
{
|
|
name: "lib1",
|
|
assetFlag: "-A assets_a",
|
|
},
|
|
{
|
|
name: "lib2",
|
|
},
|
|
{
|
|
name: "lib3",
|
|
assetPackages: []string{
|
|
"out/soong/.intermediates/lib3/android_common/aapt2/package-res.apk",
|
|
"out/soong/.intermediates/lib4/android_common/assets.zip",
|
|
},
|
|
},
|
|
{
|
|
name: "lib4",
|
|
assetFlag: "-A assets_b",
|
|
},
|
|
}
|
|
ctx := testApp(t, bp)
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
m := ctx.ModuleForTests(test.name, "android_common")
|
|
|
|
// Check asset flag in aapt2 link flags
|
|
var aapt2link android.TestingBuildParams
|
|
if len(test.assetPackages) > 0 {
|
|
aapt2link = m.Output("aapt2/package-res.apk")
|
|
} else {
|
|
aapt2link = m.Output("package-res.apk")
|
|
}
|
|
aapt2link = aapt2link
|
|
aapt2Flags := aapt2link.Args["flags"]
|
|
if test.assetFlag != "" {
|
|
android.AssertStringDoesContain(t, "asset flag", aapt2Flags, test.assetFlag)
|
|
} else {
|
|
android.AssertStringDoesNotContain(t, "aapt2 link flags", aapt2Flags, " -A ")
|
|
}
|
|
|
|
// Check asset merge rule.
|
|
if len(test.assetPackages) > 0 {
|
|
mergeAssets := m.Output("package-res.apk")
|
|
android.AssertPathsRelativeToTopEquals(t, "mergeAssets inputs", test.assetPackages, mergeAssets.Inputs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAppJavaResources(t *testing.T) {
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
java_resources: ["resources/a"],
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
android_app {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
java_resources: ["resources/a"],
|
|
}
|
|
`
|
|
|
|
ctx := testApp(t, bp)
|
|
|
|
foo := ctx.ModuleForTests("foo", "android_common")
|
|
fooResources := foo.Output("res/foo.jar")
|
|
fooDexJar := foo.Output("dex-withres/foo.jar")
|
|
fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
|
|
fooApk := foo.Rule("combineApk")
|
|
|
|
if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
|
|
t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
|
|
}
|
|
|
|
if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
|
|
t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
|
|
}
|
|
|
|
if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
|
|
t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
|
|
}
|
|
|
|
bar := ctx.ModuleForTests("bar", "android_common")
|
|
barResources := bar.Output("res/bar.jar")
|
|
barApk := bar.Rule("combineApk")
|
|
|
|
if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
|
|
t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
|
|
}
|
|
}
|
|
|
|
func TestAndroidResources(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
enforceRROTargets []string
|
|
enforceRROExcludedOverlays []string
|
|
resourceFiles map[string][]string
|
|
overlayFiles map[string][]string
|
|
rroDirs map[string][]string
|
|
}{
|
|
{
|
|
name: "no RRO",
|
|
enforceRROTargets: nil,
|
|
enforceRROExcludedOverlays: nil,
|
|
resourceFiles: map[string][]string{
|
|
"foo": nil,
|
|
"bar": {"bar/res/res/values/strings.xml"},
|
|
"lib": nil,
|
|
"lib2": {"lib2/res/res/values/strings.xml"},
|
|
},
|
|
overlayFiles: map[string][]string{
|
|
"foo": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib3/android_common/package-res.apk",
|
|
"foo/res/res/values/strings.xml",
|
|
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
|
"device/vendor/blah/overlay/foo/res/values/strings.xml",
|
|
"product/vendor/blah/overlay/foo/res/values/strings.xml",
|
|
},
|
|
"bar": {
|
|
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
|
|
"device/vendor/blah/overlay/bar/res/values/strings.xml",
|
|
},
|
|
"lib": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"lib/res/res/values/strings.xml",
|
|
"device/vendor/blah/overlay/lib/res/values/strings.xml",
|
|
},
|
|
},
|
|
rroDirs: map[string][]string{
|
|
"foo": nil,
|
|
"bar": nil,
|
|
},
|
|
},
|
|
{
|
|
name: "enforce RRO on foo",
|
|
enforceRROTargets: []string{"foo"},
|
|
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
|
|
resourceFiles: map[string][]string{
|
|
"foo": nil,
|
|
"bar": {"bar/res/res/values/strings.xml"},
|
|
"lib": nil,
|
|
"lib2": {"lib2/res/res/values/strings.xml"},
|
|
},
|
|
overlayFiles: map[string][]string{
|
|
"foo": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib3/android_common/package-res.apk",
|
|
"foo/res/res/values/strings.xml",
|
|
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
|
},
|
|
"bar": {
|
|
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
|
|
"device/vendor/blah/overlay/bar/res/values/strings.xml",
|
|
},
|
|
"lib": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"lib/res/res/values/strings.xml",
|
|
},
|
|
},
|
|
|
|
rroDirs: map[string][]string{
|
|
"foo": {
|
|
"device:device/vendor/blah/overlay/foo/res",
|
|
"product:product/vendor/blah/overlay/foo/res",
|
|
"device:device/vendor/blah/overlay/lib/res",
|
|
},
|
|
"bar": nil,
|
|
"lib": {"device:device/vendor/blah/overlay/lib/res"},
|
|
},
|
|
},
|
|
{
|
|
name: "enforce RRO on all",
|
|
enforceRROTargets: []string{"*"},
|
|
enforceRROExcludedOverlays: []string{
|
|
// Excluding specific apps/res directories also allowed.
|
|
"device/vendor/blah/static_overlay/foo",
|
|
"device/vendor/blah/static_overlay/bar/res",
|
|
},
|
|
resourceFiles: map[string][]string{
|
|
"foo": nil,
|
|
"bar": {"bar/res/res/values/strings.xml"},
|
|
"lib": nil,
|
|
"lib2": {"lib2/res/res/values/strings.xml"},
|
|
},
|
|
overlayFiles: map[string][]string{
|
|
"foo": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib/android_common/package-res.apk",
|
|
"out/soong/.intermediates/lib3/android_common/package-res.apk",
|
|
"foo/res/res/values/strings.xml",
|
|
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
|
|
},
|
|
"bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
|
|
"lib": {
|
|
"out/soong/.intermediates/lib2/android_common/package-res.apk",
|
|
"lib/res/res/values/strings.xml",
|
|
},
|
|
},
|
|
rroDirs: map[string][]string{
|
|
"foo": {
|
|
"device:device/vendor/blah/overlay/foo/res",
|
|
"product:product/vendor/blah/overlay/foo/res",
|
|
// Lib dep comes after the direct deps
|
|
"device:device/vendor/blah/overlay/lib/res",
|
|
},
|
|
"bar": {"device:device/vendor/blah/overlay/bar/res"},
|
|
"lib": {"device:device/vendor/blah/overlay/lib/res"},
|
|
},
|
|
},
|
|
}
|
|
|
|
deviceResourceOverlays := []string{
|
|
"device/vendor/blah/overlay",
|
|
"device/vendor/blah/overlay2",
|
|
"device/vendor/blah/static_overlay",
|
|
}
|
|
|
|
productResourceOverlays := []string{
|
|
"product/vendor/blah/overlay",
|
|
}
|
|
|
|
fs := android.MockFS{
|
|
"foo/res/res/values/strings.xml": nil,
|
|
"bar/res/res/values/strings.xml": nil,
|
|
"lib/res/res/values/strings.xml": nil,
|
|
"lib2/res/res/values/strings.xml": nil,
|
|
"device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
|
|
"device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
|
|
"device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
|
|
"device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
|
|
"device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
|
|
"device/vendor/blah/overlay2/res/values/strings.xml": nil,
|
|
"product/vendor/blah/overlay/foo/res/values/strings.xml": nil,
|
|
}
|
|
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
resource_dirs: ["foo/res"],
|
|
static_libs: ["lib", "lib3"],
|
|
}
|
|
|
|
android_app {
|
|
name: "bar",
|
|
sdk_version: "current",
|
|
resource_dirs: ["bar/res"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib",
|
|
sdk_version: "current",
|
|
resource_dirs: ["lib/res"],
|
|
static_libs: ["lib2"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib2",
|
|
sdk_version: "current",
|
|
resource_dirs: ["lib2/res"],
|
|
}
|
|
|
|
// This library has the same resources as lib (should not lead to dupe RROs)
|
|
android_library {
|
|
name: "lib3",
|
|
sdk_version: "current",
|
|
resource_dirs: ["lib/res"]
|
|
}
|
|
`
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
PrepareForTestWithOverlayBuildComponents,
|
|
fs.AddToFixture(),
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.DeviceResourceOverlays = deviceResourceOverlays
|
|
variables.ProductResourceOverlays = productResourceOverlays
|
|
if testCase.enforceRROTargets != nil {
|
|
variables.EnforceRROTargets = testCase.enforceRROTargets
|
|
}
|
|
if testCase.enforceRROExcludedOverlays != nil {
|
|
variables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
|
|
}
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
|
|
for _, o := range list {
|
|
res := module.MaybeOutput(o)
|
|
if res.Rule != nil {
|
|
// If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
|
|
// verify the inputs to the .arsc.flat rule.
|
|
files = append(files, res.Inputs.Strings()...)
|
|
} else {
|
|
// Otherwise, verify the full path to the output of the other module
|
|
files = append(files, o)
|
|
}
|
|
}
|
|
return files
|
|
}
|
|
|
|
getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
|
|
module := result.ModuleForTests(moduleName, "android_common")
|
|
resourceList := module.MaybeOutput("aapt2/res.list")
|
|
if resourceList.Rule != nil {
|
|
resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
|
|
}
|
|
overlayList := module.MaybeOutput("aapt2/overlay.list")
|
|
if overlayList.Rule != nil {
|
|
overlayFiles = resourceListToFiles(module, android.PathsRelativeToTop(overlayList.Inputs))
|
|
}
|
|
|
|
for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
|
|
var prefix string
|
|
if d.overlayType == device {
|
|
prefix = "device:"
|
|
} else if d.overlayType == product {
|
|
prefix = "product:"
|
|
} else {
|
|
t.Fatalf("Unexpected overlayType %d", d.overlayType)
|
|
}
|
|
rroDirs = append(rroDirs, prefix+android.PathRelativeToTop(d.path))
|
|
}
|
|
|
|
return resourceFiles, overlayFiles, rroDirs
|
|
}
|
|
|
|
modules := []string{"foo", "bar", "lib", "lib2"}
|
|
for _, module := range modules {
|
|
resourceFiles, overlayFiles, rroDirs := getResources(module)
|
|
|
|
if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
|
|
t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
|
|
module, testCase.resourceFiles[module], resourceFiles)
|
|
}
|
|
if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
|
|
t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
|
|
module, testCase.overlayFiles[module], overlayFiles)
|
|
}
|
|
if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
|
|
t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
|
|
module, testCase.rroDirs[module], rroDirs)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) {
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
link := foo.Output("package-res.apk")
|
|
linkFlags := strings.Split(link.Args["flags"], " ")
|
|
min := android.IndexList("--min-sdk-version", linkFlags)
|
|
target := android.IndexList("--target-sdk-version", linkFlags)
|
|
|
|
if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
|
|
t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
|
|
}
|
|
|
|
gotMinSdkVersion := linkFlags[min+1]
|
|
gotTargetSdkVersion := linkFlags[target+1]
|
|
|
|
android.AssertStringEquals(t, "incorrect --min-sdk-version", expectedSdkVersion, gotMinSdkVersion)
|
|
|
|
android.AssertStringEquals(t, "incorrect --target-sdk-version", expectedSdkVersion, gotTargetSdkVersion)
|
|
}
|
|
|
|
func TestAppSdkVersion(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
sdkVersion string
|
|
platformSdkInt int
|
|
platformSdkCodename string
|
|
platformSdkFinal bool
|
|
expectedMinSdkVersion string
|
|
platformApis bool
|
|
activeCodenames []string
|
|
}{
|
|
{
|
|
name: "current final SDK",
|
|
sdkVersion: "current",
|
|
platformSdkInt: 27,
|
|
platformSdkCodename: "REL",
|
|
platformSdkFinal: true,
|
|
expectedMinSdkVersion: "27",
|
|
},
|
|
{
|
|
name: "current non-final SDK",
|
|
sdkVersion: "current",
|
|
platformSdkInt: 27,
|
|
platformSdkCodename: "OMR1",
|
|
platformSdkFinal: false,
|
|
expectedMinSdkVersion: "OMR1",
|
|
activeCodenames: []string{"OMR1"},
|
|
},
|
|
{
|
|
name: "default final SDK",
|
|
sdkVersion: "",
|
|
platformApis: true,
|
|
platformSdkInt: 27,
|
|
platformSdkCodename: "REL",
|
|
platformSdkFinal: true,
|
|
expectedMinSdkVersion: "27",
|
|
},
|
|
{
|
|
name: "default non-final SDK",
|
|
sdkVersion: "",
|
|
platformApis: true,
|
|
platformSdkInt: 27,
|
|
platformSdkCodename: "OMR1",
|
|
platformSdkFinal: false,
|
|
expectedMinSdkVersion: "OMR1",
|
|
activeCodenames: []string{"OMR1"},
|
|
},
|
|
{
|
|
name: "14",
|
|
sdkVersion: "14",
|
|
expectedMinSdkVersion: "14",
|
|
platformSdkCodename: "S",
|
|
activeCodenames: []string{"S"},
|
|
},
|
|
}
|
|
|
|
for _, moduleType := range []string{"android_app", "android_library"} {
|
|
for _, test := range testCases {
|
|
t.Run(moduleType+" "+test.name, func(t *testing.T) {
|
|
platformApiProp := ""
|
|
if test.platformApis {
|
|
platformApiProp = "platform_apis: true,"
|
|
}
|
|
bp := fmt.Sprintf(`%s {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "%s",
|
|
%s
|
|
}`, moduleType, test.sdkVersion, platformApiProp)
|
|
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.Platform_sdk_version = &test.platformSdkInt
|
|
variables.Platform_sdk_codename = &test.platformSdkCodename
|
|
variables.Platform_version_active_codenames = test.activeCodenames
|
|
variables.Platform_sdk_final = &test.platformSdkFinal
|
|
}),
|
|
FixtureWithPrebuiltApis(map[string][]string{
|
|
"14": {"foo"},
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
checkSdkVersion(t, result, test.expectedMinSdkVersion)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVendorAppSdkVersion(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
sdkVersion string
|
|
platformSdkInt int
|
|
platformSdkCodename string
|
|
platformSdkFinal bool
|
|
deviceCurrentApiLevelForVendorModules string
|
|
expectedMinSdkVersion string
|
|
}{
|
|
{
|
|
name: "current final SDK",
|
|
sdkVersion: "current",
|
|
platformSdkInt: 29,
|
|
platformSdkCodename: "REL",
|
|
platformSdkFinal: true,
|
|
deviceCurrentApiLevelForVendorModules: "29",
|
|
expectedMinSdkVersion: "29",
|
|
},
|
|
{
|
|
name: "current final SDK",
|
|
sdkVersion: "current",
|
|
platformSdkInt: 29,
|
|
platformSdkCodename: "REL",
|
|
platformSdkFinal: true,
|
|
deviceCurrentApiLevelForVendorModules: "28",
|
|
expectedMinSdkVersion: "28",
|
|
},
|
|
{
|
|
name: "current final SDK",
|
|
sdkVersion: "current",
|
|
platformSdkInt: 29,
|
|
platformSdkCodename: "Q",
|
|
platformSdkFinal: false,
|
|
deviceCurrentApiLevelForVendorModules: "28",
|
|
expectedMinSdkVersion: "28",
|
|
},
|
|
}
|
|
|
|
for _, moduleType := range []string{"android_app", "android_library"} {
|
|
for _, sdkKind := range []string{"", "system_"} {
|
|
for _, test := range testCases {
|
|
t.Run(moduleType+" "+test.name, func(t *testing.T) {
|
|
bp := fmt.Sprintf(`%s {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "%s%s",
|
|
vendor: true,
|
|
}`, moduleType, sdkKind, test.sdkVersion)
|
|
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.Platform_sdk_version = &test.platformSdkInt
|
|
variables.Platform_sdk_codename = &test.platformSdkCodename
|
|
variables.Platform_sdk_final = &test.platformSdkFinal
|
|
variables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
|
|
variables.DeviceSystemSdkVersions = []string{"28", "29"}
|
|
}),
|
|
FixtureWithPrebuiltApis(map[string][]string{
|
|
"28": {"foo"},
|
|
"29": {"foo"},
|
|
"current": {"foo"},
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
checkSdkVersion(t, result, test.expectedMinSdkVersion)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestJNIABI(t *testing.T) {
|
|
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
cc_library {
|
|
name: "libjni",
|
|
system_shared_libs: [],
|
|
sdk_version: "current",
|
|
stl: "none",
|
|
}
|
|
|
|
android_test {
|
|
name: "test",
|
|
sdk_version: "core_platform",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test {
|
|
name: "test_first",
|
|
sdk_version: "core_platform",
|
|
compile_multilib: "first",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test {
|
|
name: "test_both",
|
|
sdk_version: "core_platform",
|
|
compile_multilib: "both",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test {
|
|
name: "test_32",
|
|
sdk_version: "core_platform",
|
|
compile_multilib: "32",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test {
|
|
name: "test_64",
|
|
sdk_version: "core_platform",
|
|
compile_multilib: "64",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
`)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
abis []string
|
|
}{
|
|
{"test", []string{"arm64-v8a"}},
|
|
{"test_first", []string{"arm64-v8a"}},
|
|
{"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
|
|
{"test_32", []string{"armeabi-v7a"}},
|
|
{"test_64", []string{"arm64-v8a"}},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
app := ctx.ModuleForTests(test.name, "android_common")
|
|
jniLibZip := app.Output(jniJarOutputPathString)
|
|
var abis []string
|
|
args := strings.Fields(jniLibZip.Args["jarArgs"])
|
|
for i := 0; i < len(args); i++ {
|
|
if args[i] == "-P" {
|
|
abis = append(abis, filepath.Base(args[i+1]))
|
|
i++
|
|
}
|
|
}
|
|
if !reflect.DeepEqual(abis, test.abis) {
|
|
t.Errorf("want abis %v, got %v", test.abis, abis)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAppSdkVersionByPartition(t *testing.T) {
|
|
testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
vendor: true,
|
|
platform_apis: true,
|
|
}
|
|
`)
|
|
|
|
testJava(t, `
|
|
android_app {
|
|
name: "bar",
|
|
srcs: ["b.java"],
|
|
platform_apis: true,
|
|
}
|
|
`)
|
|
|
|
for _, enforce := range []bool{true, false} {
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
product_specific: true,
|
|
platform_apis: true,
|
|
}
|
|
`
|
|
|
|
errorHandler := android.FixtureExpectsNoErrors
|
|
if enforce {
|
|
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product")
|
|
}
|
|
|
|
android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
|
|
}),
|
|
).
|
|
ExtendWithErrorHandler(errorHandler).
|
|
RunTestWithBp(t, bp)
|
|
}
|
|
}
|
|
|
|
func TestJNIPackaging(t *testing.T) {
|
|
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
cc_library {
|
|
name: "libjni",
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app {
|
|
name: "app",
|
|
jni_libs: ["libjni"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app {
|
|
name: "app_noembed",
|
|
jni_libs: ["libjni"],
|
|
use_embedded_native_libs: false,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app {
|
|
name: "app_embed",
|
|
jni_libs: ["libjni"],
|
|
use_embedded_native_libs: true,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test {
|
|
name: "test",
|
|
sdk_version: "current",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test {
|
|
name: "test_noembed",
|
|
sdk_version: "current",
|
|
jni_libs: ["libjni"],
|
|
use_embedded_native_libs: false,
|
|
}
|
|
|
|
android_test_helper_app {
|
|
name: "test_helper",
|
|
sdk_version: "current",
|
|
jni_libs: ["libjni"],
|
|
}
|
|
|
|
android_test_helper_app {
|
|
name: "test_helper_noembed",
|
|
sdk_version: "current",
|
|
jni_libs: ["libjni"],
|
|
use_embedded_native_libs: false,
|
|
}
|
|
`)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
packaged bool
|
|
compressed bool
|
|
}{
|
|
{"app", false, false},
|
|
{"app_noembed", false, false},
|
|
{"app_embed", true, false},
|
|
{"test", true, false},
|
|
{"test_noembed", true, true},
|
|
{"test_helper", true, false},
|
|
{"test_helper_noembed", true, true},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
app := ctx.ModuleForTests(test.name, "android_common")
|
|
jniLibZip := app.MaybeOutput(jniJarOutputPathString)
|
|
if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
|
|
t.Errorf("expected jni packaged %v, got %v", w, g)
|
|
}
|
|
|
|
if jniLibZip.Rule != nil {
|
|
if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
|
|
t.Errorf("expected jni compressed %v, got %v", w, g)
|
|
}
|
|
|
|
if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") {
|
|
t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String())
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJNISDK(t *testing.T) {
|
|
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
cc_library {
|
|
name: "libjni",
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test {
|
|
name: "app_platform",
|
|
jni_libs: ["libjni"],
|
|
platform_apis: true,
|
|
}
|
|
|
|
android_test {
|
|
name: "app_sdk",
|
|
jni_libs: ["libjni"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test {
|
|
name: "app_force_platform",
|
|
jni_libs: ["libjni"],
|
|
sdk_version: "current",
|
|
jni_uses_platform_apis: true,
|
|
}
|
|
|
|
android_test {
|
|
name: "app_force_sdk",
|
|
jni_libs: ["libjni"],
|
|
platform_apis: true,
|
|
jni_uses_sdk_apis: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "libvendorjni",
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
vendor: true,
|
|
}
|
|
|
|
android_test {
|
|
name: "app_vendor",
|
|
jni_libs: ["libvendorjni"],
|
|
sdk_version: "current",
|
|
vendor: true,
|
|
}
|
|
`)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
sdkJNI bool
|
|
vendorJNI bool
|
|
}{
|
|
{name: "app_platform"},
|
|
{name: "app_sdk", sdkJNI: true},
|
|
{name: "app_force_platform"},
|
|
{name: "app_force_sdk", sdkJNI: true},
|
|
{name: "app_vendor", vendorJNI: true},
|
|
}
|
|
|
|
platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
|
|
Output("libjni.so").Output.String()
|
|
sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
|
|
Output("libjni.so").Output.String()
|
|
vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
|
|
Output("libvendorjni.so").Output.String()
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
app := ctx.ModuleForTests(test.name, "android_common")
|
|
|
|
jniLibZip := app.MaybeOutput(jniJarOutputPathString)
|
|
if len(jniLibZip.Implicits) != 1 {
|
|
t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
|
|
}
|
|
gotJNI := jniLibZip.Implicits[0].String()
|
|
|
|
if test.sdkJNI {
|
|
if gotJNI != sdkJNI {
|
|
t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI)
|
|
}
|
|
} else if test.vendorJNI {
|
|
if gotJNI != vendorJNI {
|
|
t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI)
|
|
}
|
|
} else {
|
|
if gotJNI != platformJNI {
|
|
t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("jni_uses_platform_apis_error", func(t *testing.T) {
|
|
testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, `
|
|
android_test {
|
|
name: "app_platform",
|
|
platform_apis: true,
|
|
jni_uses_platform_apis: true,
|
|
}
|
|
`)
|
|
})
|
|
|
|
t.Run("jni_uses_sdk_apis_error", func(t *testing.T) {
|
|
testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, `
|
|
android_test {
|
|
name: "app_sdk",
|
|
sdk_version: "current",
|
|
jni_uses_sdk_apis: true,
|
|
}
|
|
`)
|
|
})
|
|
|
|
}
|
|
|
|
func TestCertificates(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
allowMissingDependencies bool
|
|
certificateOverride string
|
|
expectedCertSigningFlags string
|
|
expectedCertificate string
|
|
}{
|
|
{
|
|
name: "default",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
certificateOverride: "",
|
|
expectedCertSigningFlags: "",
|
|
expectedCertificate: "build/make/target/product/security/testkey",
|
|
},
|
|
{
|
|
name: "module certificate property",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: ":new_certificate",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "new_certificate",
|
|
certificate: "cert/new_cert",
|
|
}
|
|
`,
|
|
certificateOverride: "",
|
|
expectedCertSigningFlags: "",
|
|
expectedCertificate: "cert/new_cert",
|
|
},
|
|
{
|
|
name: "path certificate property",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: "expiredkey",
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
certificateOverride: "",
|
|
expectedCertSigningFlags: "",
|
|
expectedCertificate: "build/make/target/product/security/expiredkey",
|
|
},
|
|
{
|
|
name: "certificate overrides",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: "expiredkey",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "new_certificate",
|
|
certificate: "cert/new_cert",
|
|
}
|
|
`,
|
|
certificateOverride: "foo:new_certificate",
|
|
expectedCertSigningFlags: "",
|
|
expectedCertificate: "cert/new_cert",
|
|
},
|
|
{
|
|
name: "certificate signing flags",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: ":new_certificate",
|
|
lineage: "lineage.bin",
|
|
rotationMinSdkVersion: "32",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "new_certificate",
|
|
certificate: "cert/new_cert",
|
|
}
|
|
`,
|
|
certificateOverride: "",
|
|
expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
|
|
expectedCertificate: "cert/new_cert",
|
|
},
|
|
{
|
|
name: "cert signing flags from filegroup",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: ":new_certificate",
|
|
lineage: ":lineage_bin",
|
|
rotationMinSdkVersion: "32",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "new_certificate",
|
|
certificate: "cert/new_cert",
|
|
}
|
|
|
|
filegroup {
|
|
name: "lineage_bin",
|
|
srcs: ["lineage.bin"],
|
|
}
|
|
`,
|
|
certificateOverride: "",
|
|
expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
|
|
expectedCertificate: "cert/new_cert",
|
|
},
|
|
{
|
|
name: "missing with AllowMissingDependencies",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: ":new_certificate",
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
expectedCertificate: "out/soong/.intermediates/foo/android_common/missing",
|
|
allowMissingDependencies: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
if test.certificateOverride != "" {
|
|
variables.CertificateOverrides = []string{test.certificateOverride}
|
|
}
|
|
if test.allowMissingDependencies {
|
|
variables.Allow_missing_dependencies = proptools.BoolPtr(true)
|
|
}
|
|
}),
|
|
android.FixtureModifyContext(func(ctx *android.TestContext) {
|
|
ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
|
|
}),
|
|
).RunTestWithBp(t, test.bp)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
certificate := foo.Module().(*AndroidApp).certificate
|
|
android.AssertPathRelativeToTopEquals(t, "certificates key", test.expectedCertificate+".pk8", certificate.Key)
|
|
// The sign_target_files_apks and check_target_files_signatures
|
|
// tools require that certificates have a .x509.pem extension.
|
|
android.AssertPathRelativeToTopEquals(t, "certificates pem", test.expectedCertificate+".x509.pem", certificate.Pem)
|
|
|
|
signapk := foo.Output("foo.apk")
|
|
if signapk.Rule != android.ErrorRule {
|
|
signCertificateFlags := signapk.Args["certificates"]
|
|
expectedFlags := certificate.Pem.String() + " " + certificate.Key.String()
|
|
android.AssertStringEquals(t, "certificates flags", expectedFlags, signCertificateFlags)
|
|
|
|
certSigningFlags := signapk.Args["flags"]
|
|
android.AssertStringEquals(t, "cert signing flags", test.expectedCertSigningFlags, certSigningFlags)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRequestV4SigningFlag(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "default",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "default",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
v4_signature: false,
|
|
}
|
|
`,
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "module certificate property",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
v4_signature: true,
|
|
}
|
|
`,
|
|
expected: "--enable-v4",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
).RunTestWithBp(t, test.bp)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
signapk := foo.Output("foo.apk")
|
|
signFlags := signapk.Args["flags"]
|
|
android.AssertStringEquals(t, "signing flags", test.expected, signFlags)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPackageNameOverride(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
packageNameOverride string
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "default",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
packageNameOverride: "",
|
|
expected: []string{
|
|
"out/soong/.intermediates/foo/android_common/foo.apk",
|
|
"out/soong/target/product/test_device/system/app/foo/foo.apk",
|
|
},
|
|
},
|
|
{
|
|
name: "overridden via PRODUCT_PACKAGE_NAME_OVERRIDES",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
packageNameOverride: "foo:bar",
|
|
expected: []string{
|
|
// The package apk should be still be the original name for test dependencies.
|
|
"out/soong/.intermediates/foo/android_common/bar.apk",
|
|
"out/soong/target/product/test_device/system/app/bar/bar.apk",
|
|
},
|
|
},
|
|
{
|
|
name: "overridden via stem",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
stem: "bar",
|
|
}
|
|
`,
|
|
packageNameOverride: "",
|
|
expected: []string{
|
|
"out/soong/.intermediates/foo/android_common/bar.apk",
|
|
"out/soong/target/product/test_device/system/app/bar/bar.apk",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
if test.packageNameOverride != "" {
|
|
variables.PackageNameOverrides = []string{test.packageNameOverride}
|
|
}
|
|
}),
|
|
).RunTestWithBp(t, test.bp)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
outSoongDir := result.Config.SoongOutDir()
|
|
|
|
outputs := foo.AllOutputs()
|
|
outputMap := make(map[string]bool)
|
|
for _, o := range outputs {
|
|
outputMap[android.StringPathRelativeToTop(outSoongDir, o)] = true
|
|
}
|
|
for _, e := range test.expected {
|
|
if _, exist := outputMap[e]; !exist {
|
|
t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInstrumentationTargetOverridden(t *testing.T) {
|
|
bp := `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test {
|
|
name: "bar",
|
|
instrumentation_for: "foo",
|
|
sdk_version: "current",
|
|
}
|
|
`
|
|
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
bar := result.ModuleForTests("bar", "android_common")
|
|
res := bar.Output("package-res.apk")
|
|
aapt2Flags := res.Args["flags"]
|
|
e := "--rename-instrumentation-target-package org.dandroid.bp"
|
|
if !strings.Contains(aapt2Flags, e) {
|
|
t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidApp(t *testing.T) {
|
|
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
|
|
t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: "expiredkey",
|
|
overrides: ["qux"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "bar",
|
|
base: "foo",
|
|
certificate: ":new_certificate",
|
|
lineage: "lineage.bin",
|
|
rotationMinSdkVersion: "32",
|
|
logging_parent: "bah",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "new_certificate",
|
|
certificate: "cert/new_cert",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "baz",
|
|
base: "foo",
|
|
package_name: "org.dandroid.bp",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "baz_no_rename_resources",
|
|
base: "foo",
|
|
package_name: "org.dandroid.bp",
|
|
rename_resources_package: false,
|
|
}
|
|
|
|
android_app {
|
|
name: "foo_no_rename_resources",
|
|
srcs: ["a.java"],
|
|
certificate: "expiredkey",
|
|
overrides: ["qux"],
|
|
rename_resources_package: false,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "baz_base_no_rename_resources",
|
|
base: "foo_no_rename_resources",
|
|
package_name: "org.dandroid.bp",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "baz_override_base_rename_resources",
|
|
base: "foo_no_rename_resources",
|
|
package_name: "org.dandroid.bp",
|
|
rename_resources_package: true,
|
|
}
|
|
`)
|
|
|
|
expectedVariants := []struct {
|
|
name string
|
|
moduleName string
|
|
variantName string
|
|
apkName string
|
|
apkPath string
|
|
certFlag string
|
|
certSigningFlags string
|
|
overrides []string
|
|
packageFlag string
|
|
renameResources bool
|
|
logging_parent string
|
|
}{
|
|
{
|
|
name: "foo",
|
|
moduleName: "foo",
|
|
variantName: "android_common",
|
|
apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk",
|
|
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
|
|
certSigningFlags: "",
|
|
overrides: []string{"qux"},
|
|
packageFlag: "",
|
|
renameResources: false,
|
|
logging_parent: "",
|
|
},
|
|
{
|
|
name: "foo",
|
|
moduleName: "bar",
|
|
variantName: "android_common_bar",
|
|
apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk",
|
|
certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
|
|
certSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
|
|
overrides: []string{"qux", "foo"},
|
|
packageFlag: "",
|
|
renameResources: false,
|
|
logging_parent: "bah",
|
|
},
|
|
{
|
|
name: "foo",
|
|
moduleName: "baz",
|
|
variantName: "android_common_baz",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz/baz.apk",
|
|
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
|
|
certSigningFlags: "",
|
|
overrides: []string{"qux", "foo"},
|
|
packageFlag: "org.dandroid.bp",
|
|
renameResources: true,
|
|
logging_parent: "",
|
|
},
|
|
{
|
|
name: "foo",
|
|
moduleName: "baz_no_rename_resources",
|
|
variantName: "android_common_baz_no_rename_resources",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk",
|
|
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
|
|
certSigningFlags: "",
|
|
overrides: []string{"qux", "foo"},
|
|
packageFlag: "org.dandroid.bp",
|
|
renameResources: false,
|
|
logging_parent: "",
|
|
},
|
|
{
|
|
name: "foo_no_rename_resources",
|
|
moduleName: "baz_base_no_rename_resources",
|
|
variantName: "android_common_baz_base_no_rename_resources",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk",
|
|
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
|
|
certSigningFlags: "",
|
|
overrides: []string{"qux", "foo_no_rename_resources"},
|
|
packageFlag: "org.dandroid.bp",
|
|
renameResources: false,
|
|
logging_parent: "",
|
|
},
|
|
{
|
|
name: "foo_no_rename_resources",
|
|
moduleName: "baz_override_base_rename_resources",
|
|
variantName: "android_common_baz_override_base_rename_resources",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk",
|
|
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
|
|
certSigningFlags: "",
|
|
overrides: []string{"qux", "foo_no_rename_resources"},
|
|
packageFlag: "org.dandroid.bp",
|
|
renameResources: true,
|
|
logging_parent: "",
|
|
},
|
|
}
|
|
for _, expected := range expectedVariants {
|
|
variant := result.ModuleForTests(expected.name, expected.variantName)
|
|
|
|
// Check the final apk name
|
|
variant.Output(expected.apkPath)
|
|
|
|
// Check the certificate paths
|
|
signapk := variant.Output(expected.moduleName + ".apk")
|
|
certFlag := signapk.Args["certificates"]
|
|
android.AssertStringEquals(t, "certificates flags", expected.certFlag, certFlag)
|
|
|
|
// Check the cert signing flags
|
|
certSigningFlags := signapk.Args["flags"]
|
|
android.AssertStringEquals(t, "cert signing flags", expected.certSigningFlags, certSigningFlags)
|
|
|
|
// Check if the overrides field values are correctly aggregated.
|
|
mod := variant.Module().(*AndroidApp)
|
|
android.AssertDeepEquals(t, "overrides property", expected.overrides, mod.overridableAppProperties.Overrides)
|
|
|
|
// Test Overridable property: Logging_parent
|
|
logging_parent := mod.aapt.LoggingParent
|
|
android.AssertStringEquals(t, "overrides property value for logging parent", expected.logging_parent, logging_parent)
|
|
|
|
// Check the package renaming flag, if exists.
|
|
res := variant.Output("package-res.apk")
|
|
aapt2Flags := res.Args["flags"]
|
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
|
|
expectedPackage := expected.packageFlag
|
|
if !expected.renameResources {
|
|
expectedPackage = ""
|
|
}
|
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expectedPackage)
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidAppOverrides(t *testing.T) {
|
|
ctx, _ := testJava(
|
|
t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
overrides: ["qux"]
|
|
}
|
|
|
|
android_app {
|
|
name: "bar",
|
|
srcs: ["b.java"],
|
|
sdk_version: "current",
|
|
overrides: ["foo"]
|
|
}
|
|
|
|
override_android_app {
|
|
name: "foo_override",
|
|
base: "foo",
|
|
overrides: ["bar"]
|
|
}
|
|
`)
|
|
|
|
expectedVariants := []struct {
|
|
name string
|
|
moduleName string
|
|
variantName string
|
|
overrides []string
|
|
}{
|
|
{
|
|
name: "foo",
|
|
moduleName: "foo",
|
|
variantName: "android_common",
|
|
overrides: []string{"qux"},
|
|
},
|
|
{
|
|
name: "bar",
|
|
moduleName: "bar",
|
|
variantName: "android_common",
|
|
overrides: []string{"foo"},
|
|
},
|
|
{
|
|
name: "foo",
|
|
moduleName: "foo_override",
|
|
variantName: "android_common_foo_override",
|
|
overrides: []string{"bar", "foo"},
|
|
},
|
|
}
|
|
for _, expected := range expectedVariants {
|
|
variant := ctx.ModuleForTests(expected.name, expected.variantName)
|
|
|
|
// Check if the overrides field values are correctly aggregated.
|
|
mod := variant.Module().(*AndroidApp)
|
|
android.AssertDeepEquals(t, "overrides property", expected.overrides, mod.overridableAppProperties.Overrides)
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidAppWithPrebuilt(t *testing.T) {
|
|
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
|
|
t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "bar",
|
|
base: "foo",
|
|
}
|
|
|
|
android_app_import {
|
|
name: "bar",
|
|
prefer: true,
|
|
apk: "bar.apk",
|
|
presigned: true,
|
|
}
|
|
`)
|
|
|
|
// An app that has an override that also has a prebuilt should not be hidden.
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
if foo.Module().IsHideFromMake() {
|
|
t.Errorf("expected foo to have HideFromMake false")
|
|
}
|
|
|
|
// An override that also has a prebuilt should be hidden.
|
|
barOverride := result.ModuleForTests("foo", "android_common_bar")
|
|
if !barOverride.Module().IsHideFromMake() {
|
|
t.Errorf("expected bar override variant of foo to have HideFromMake true")
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidAppStem(t *testing.T) {
|
|
ctx, _ := testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
override_android_app {
|
|
name: "bar",
|
|
base: "foo",
|
|
}
|
|
override_android_app {
|
|
name: "baz",
|
|
base: "foo",
|
|
stem: "baz_stem",
|
|
}
|
|
android_app {
|
|
name: "foo2",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
stem: "foo2_stem",
|
|
}
|
|
override_android_app {
|
|
name: "bar2",
|
|
base: "foo2",
|
|
}
|
|
override_android_app {
|
|
name: "baz2",
|
|
base: "foo2",
|
|
stem: "baz2_stem",
|
|
}
|
|
`)
|
|
for _, expected := range []struct {
|
|
moduleName string
|
|
variantName string
|
|
apkPath string
|
|
}{
|
|
{
|
|
moduleName: "foo",
|
|
variantName: "android_common",
|
|
apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk",
|
|
},
|
|
{
|
|
moduleName: "foo",
|
|
variantName: "android_common_bar",
|
|
apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk",
|
|
},
|
|
{
|
|
moduleName: "foo",
|
|
variantName: "android_common_baz",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz_stem/baz_stem.apk",
|
|
},
|
|
{
|
|
moduleName: "foo2",
|
|
variantName: "android_common",
|
|
apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
|
|
},
|
|
{
|
|
moduleName: "foo2",
|
|
variantName: "android_common_bar2",
|
|
// Note that this may cause the duplicate output error.
|
|
apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
|
|
},
|
|
{
|
|
moduleName: "foo2",
|
|
variantName: "android_common_baz2",
|
|
apkPath: "out/soong/target/product/test_device/system/app/baz2_stem/baz2_stem.apk",
|
|
},
|
|
} {
|
|
variant := ctx.ModuleForTests(expected.moduleName, expected.variantName)
|
|
variant.Output(expected.apkPath)
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidAppDependency(t *testing.T) {
|
|
ctx, _ := testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "bar",
|
|
base: "foo",
|
|
package_name: "org.dandroid.bp",
|
|
}
|
|
|
|
android_test {
|
|
name: "baz",
|
|
srcs: ["b.java"],
|
|
instrumentation_for: "foo",
|
|
}
|
|
|
|
android_test {
|
|
name: "qux",
|
|
srcs: ["b.java"],
|
|
instrumentation_for: "bar",
|
|
}
|
|
`)
|
|
|
|
// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
|
|
javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
|
|
fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
|
|
if !strings.Contains(javac.Args["classpath"], fooTurbine) {
|
|
t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
|
|
}
|
|
|
|
// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
|
|
javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
|
|
barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
|
|
if !strings.Contains(javac.Args["classpath"], barTurbine) {
|
|
t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
|
|
}
|
|
}
|
|
|
|
func TestOverrideAndroidTest(t *testing.T) {
|
|
ctx, _ := testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
package_name: "com.android.foo",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
override_android_app {
|
|
name: "bar",
|
|
base: "foo",
|
|
package_name: "com.android.bar",
|
|
}
|
|
|
|
android_test {
|
|
name: "foo_test",
|
|
srcs: ["b.java"],
|
|
instrumentation_for: "foo",
|
|
}
|
|
|
|
override_android_test {
|
|
name: "bar_test",
|
|
base: "foo_test",
|
|
package_name: "com.android.bar.test",
|
|
instrumentation_for: "bar",
|
|
instrumentation_target_package: "com.android.bar",
|
|
}
|
|
`)
|
|
|
|
expectedVariants := []struct {
|
|
moduleName string
|
|
variantName string
|
|
apkPath string
|
|
overrides []string
|
|
targetVariant string
|
|
packageFlag string
|
|
targetPackageFlag string
|
|
}{
|
|
{
|
|
variantName: "android_common",
|
|
apkPath: "/target/product/test_device/testcases/foo_test/arm64/foo_test.apk",
|
|
overrides: nil,
|
|
targetVariant: "android_common",
|
|
packageFlag: "",
|
|
targetPackageFlag: "",
|
|
},
|
|
{
|
|
variantName: "android_common_bar_test",
|
|
apkPath: "/target/product/test_device/testcases/bar_test/arm64/bar_test.apk",
|
|
overrides: []string{"foo_test"},
|
|
targetVariant: "android_common_bar",
|
|
packageFlag: "com.android.bar.test",
|
|
targetPackageFlag: "com.android.bar",
|
|
},
|
|
}
|
|
for _, expected := range expectedVariants {
|
|
variant := ctx.ModuleForTests("foo_test", expected.variantName)
|
|
|
|
// Check the final apk name
|
|
variant.Output("out/soong" + expected.apkPath)
|
|
|
|
// Check if the overrides field values are correctly aggregated.
|
|
mod := variant.Module().(*AndroidTest)
|
|
if !reflect.DeepEqual(expected.overrides, mod.overridableAppProperties.Overrides) {
|
|
t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
|
|
expected.overrides, mod.overridableAppProperties.Overrides)
|
|
}
|
|
|
|
// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
|
|
javac := variant.Rule("javac")
|
|
turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
|
|
if !strings.Contains(javac.Args["classpath"], turbine) {
|
|
t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
|
|
}
|
|
|
|
// Check aapt2 flags.
|
|
res := variant.Output("package-res.apk")
|
|
aapt2Flags := res.Args["flags"]
|
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
|
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expected.packageFlag)
|
|
checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag)
|
|
}
|
|
}
|
|
|
|
func TestAndroidTest_FixTestConfig(t *testing.T) {
|
|
ctx, _ := testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
package_name: "com.android.foo",
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test {
|
|
name: "foo_test",
|
|
srcs: ["b.java"],
|
|
instrumentation_for: "foo",
|
|
}
|
|
|
|
android_test {
|
|
name: "bar_test",
|
|
srcs: ["b.java"],
|
|
package_name: "com.android.bar.test",
|
|
instrumentation_for: "foo",
|
|
mainline_package_name: "com.android.bar",
|
|
}
|
|
|
|
override_android_test {
|
|
name: "baz_test",
|
|
base: "foo_test",
|
|
package_name: "com.android.baz.test",
|
|
mainline_package_name: "com.android.baz",
|
|
}
|
|
`)
|
|
|
|
testCases := []struct {
|
|
moduleName string
|
|
variantName string
|
|
expectedFlags []string
|
|
}{
|
|
{
|
|
moduleName: "foo_test",
|
|
variantName: "android_common",
|
|
},
|
|
{
|
|
moduleName: "bar_test",
|
|
variantName: "android_common",
|
|
expectedFlags: []string{
|
|
"--manifest out/soong/.intermediates/bar_test/android_common/manifest_fixer/AndroidManifest.xml",
|
|
"--package-name com.android.bar.test",
|
|
"--mainline-package-name com.android.bar",
|
|
},
|
|
},
|
|
{
|
|
moduleName: "foo_test",
|
|
variantName: "android_common_baz_test",
|
|
expectedFlags: []string{
|
|
"--manifest out/soong/.intermediates/foo_test/android_common_baz_test/manifest_fixer/AndroidManifest.xml",
|
|
"--package-name com.android.baz.test",
|
|
"--test-file-name baz_test.apk",
|
|
"out/soong/.intermediates/foo_test/android_common_baz_test/test_config_fixer/AndroidTest.xml",
|
|
"--mainline-package-name com.android.baz",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
variant := ctx.ModuleForTests(test.moduleName, test.variantName)
|
|
params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
|
|
|
|
if len(test.expectedFlags) > 0 {
|
|
if params.Rule == nil {
|
|
t.Errorf("test_config_fixer was expected to run, but didn't")
|
|
} else {
|
|
for _, flag := range test.expectedFlags {
|
|
if !strings.Contains(params.RuleParams.Command, flag) {
|
|
t.Errorf("Flag %q was not found in command: %q", flag, params.RuleParams.Command)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if params.Rule != nil {
|
|
t.Errorf("test_config_fixer was not expected to run, but did: %q", params.RuleParams.Command)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInstrumentationTargetPrebuilt(t *testing.T) {
|
|
bp := `
|
|
android_app_import {
|
|
name: "foo",
|
|
apk: "foo.apk",
|
|
presigned: true,
|
|
}
|
|
|
|
android_test {
|
|
name: "bar",
|
|
srcs: ["a.java"],
|
|
instrumentation_for: "foo",
|
|
sdk_version: "current",
|
|
}
|
|
`
|
|
|
|
android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
"instrumentation_for: dependency \"foo\" of type \"android_app_import\" does not provide JavaInfo so is unsuitable for use with this property")).
|
|
RunTestWithBp(t, bp)
|
|
}
|
|
|
|
func TestStl(t *testing.T) {
|
|
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
|
|
cc_library {
|
|
name: "libjni",
|
|
sdk_version: "current",
|
|
stl: "c++_shared",
|
|
}
|
|
|
|
android_test {
|
|
name: "stl",
|
|
jni_libs: ["libjni"],
|
|
compile_multilib: "both",
|
|
sdk_version: "current",
|
|
stl: "c++_shared",
|
|
}
|
|
|
|
android_test {
|
|
name: "system",
|
|
jni_libs: ["libjni"],
|
|
compile_multilib: "both",
|
|
sdk_version: "current",
|
|
}
|
|
`)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
jnis []string
|
|
}{
|
|
{"stl",
|
|
[]string{
|
|
"libjni.so",
|
|
"libc++_shared.so",
|
|
},
|
|
},
|
|
{"system",
|
|
[]string{
|
|
"libjni.so",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
app := ctx.ModuleForTests(test.name, "android_common")
|
|
jniLibZip := app.Output(jniJarOutputPathString)
|
|
var jnis []string
|
|
args := strings.Fields(jniLibZip.Args["jarArgs"])
|
|
for i := 0; i < len(args); i++ {
|
|
if args[i] == "-f" {
|
|
jnis = append(jnis, args[i+1])
|
|
i += 1
|
|
}
|
|
}
|
|
jnisJoined := strings.Join(jnis, " ")
|
|
for _, jni := range test.jnis {
|
|
if !strings.Contains(jnisJoined, jni) {
|
|
t.Errorf("missing jni %q in %q", jni, jnis)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUsesLibraries(t *testing.T) {
|
|
bp := `
|
|
java_sdk_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
api_packages: ["foo"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "qux",
|
|
srcs: ["a.java"],
|
|
api_packages: ["qux"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "quuz",
|
|
srcs: ["a.java"],
|
|
api_packages: ["quuz"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "fred",
|
|
srcs: ["a.java"],
|
|
api_packages: ["fred"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "bar",
|
|
srcs: ["a.java"],
|
|
api_packages: ["bar"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "runtime-library",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "static-runtime-helper",
|
|
srcs: ["a.java"],
|
|
libs: ["runtime-library"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "runtime-required-x",
|
|
srcs: ["a.java"],
|
|
installable: true,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "runtime-optional-x",
|
|
srcs: ["a.java"],
|
|
installable: true,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_library {
|
|
name: "static-x",
|
|
uses_libs: ["runtime-required-x"],
|
|
optional_uses_libs: ["runtime-optional-x"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "runtime-required-y",
|
|
srcs: ["a.java"],
|
|
installable: true,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "runtime-optional-y",
|
|
srcs: ["a.java"],
|
|
installable: true,
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "static-y",
|
|
srcs: ["a.java"],
|
|
uses_libs: ["runtime-required-y"],
|
|
optional_uses_libs: ["runtime-optional-y"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
// A library that has to use "provides_uses_lib", because:
|
|
// - it is not an SDK library
|
|
// - its library name is different from its module name
|
|
java_library {
|
|
name: "non-sdk-lib",
|
|
provides_uses_lib: "com.non.sdk.lib",
|
|
installable: true,
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
android_app {
|
|
name: "app",
|
|
srcs: ["a.java"],
|
|
libs: [
|
|
"qux",
|
|
"quuz.stubs"
|
|
],
|
|
static_libs: [
|
|
"static-runtime-helper",
|
|
// statically linked component libraries should not pull their SDK libraries,
|
|
// so "fred" should not be added to class loader context
|
|
"fred.stubs",
|
|
"static-x",
|
|
"static-y",
|
|
],
|
|
uses_libs: [
|
|
"foo",
|
|
"non-sdk-lib"
|
|
],
|
|
sdk_version: "current",
|
|
optional_uses_libs: [
|
|
"bar",
|
|
"baz",
|
|
],
|
|
}
|
|
|
|
android_app_import {
|
|
name: "prebuilt",
|
|
apk: "prebuilts/apk/app.apk",
|
|
certificate: "platform",
|
|
uses_libs: [
|
|
"foo",
|
|
"non-sdk-lib",
|
|
"android.test.runner"
|
|
],
|
|
optional_uses_libs: [
|
|
"bar",
|
|
"baz",
|
|
],
|
|
}
|
|
`
|
|
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
PrepareForTestWithJavaSdkLibraryFiles,
|
|
FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.MissingUsesLibraries = []string{"baz"}
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
app := result.ModuleForTests("app", "android_common")
|
|
prebuilt := result.ModuleForTests("prebuilt", "android_common")
|
|
|
|
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
|
|
// These also include explicit `uses_libs`/`optional_uses_libs` entries, as they may be
|
|
// propagated from dependencies.
|
|
actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
expectManifestFixerArgs := `--extract-native-libs=true ` +
|
|
`--uses-library qux ` +
|
|
`--uses-library quuz ` +
|
|
`--uses-library foo ` +
|
|
`--uses-library com.non.sdk.lib ` +
|
|
`--uses-library runtime-library ` +
|
|
`--uses-library runtime-required-x ` +
|
|
`--uses-library runtime-required-y ` +
|
|
`--optional-uses-library bar ` +
|
|
`--optional-uses-library runtime-optional-x ` +
|
|
`--optional-uses-library runtime-optional-y`
|
|
android.AssertStringDoesContain(t, "manifest_fixer args", actualManifestFixerArgs, expectManifestFixerArgs)
|
|
|
|
// Test that all libraries are verified (library order matters).
|
|
verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
|
|
verifyArgs := `--uses-library foo ` +
|
|
`--uses-library com.non.sdk.lib ` +
|
|
`--uses-library qux ` +
|
|
`--uses-library quuz ` +
|
|
`--uses-library runtime-library ` +
|
|
`--uses-library runtime-required-x ` +
|
|
`--uses-library runtime-required-y ` +
|
|
`--optional-uses-library bar ` +
|
|
`--optional-uses-library baz ` +
|
|
`--optional-uses-library runtime-optional-x ` +
|
|
`--optional-uses-library runtime-optional-y `
|
|
android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
|
|
|
|
// Test that all libraries are verified for an APK (library order matters).
|
|
verifyApkCmd := prebuilt.Rule("verify_uses_libraries").RuleParams.Command
|
|
verifyApkArgs := `--uses-library foo ` +
|
|
`--uses-library com.non.sdk.lib ` +
|
|
`--uses-library android.test.runner ` +
|
|
`--optional-uses-library bar ` +
|
|
`--optional-uses-library baz `
|
|
android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
|
|
|
|
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
|
|
cmd := app.Rule("dexpreopt").RuleParams.Command
|
|
w := `--target-context-for-sdk any ` +
|
|
`PCL[/system/framework/qux.jar]#` +
|
|
`PCL[/system/framework/quuz.jar]#` +
|
|
`PCL[/system/framework/foo.jar]#` +
|
|
`PCL[/system/framework/non-sdk-lib.jar]#` +
|
|
`PCL[/system/framework/bar.jar]#` +
|
|
`PCL[/system/framework/runtime-library.jar]#` +
|
|
`PCL[/system/framework/runtime-required-x.jar]#` +
|
|
`PCL[/system/framework/runtime-optional-x.jar]#` +
|
|
`PCL[/system/framework/runtime-required-y.jar]#` +
|
|
`PCL[/system/framework/runtime-optional-y.jar] `
|
|
android.AssertStringDoesContain(t, "dexpreopt app cmd args", cmd, w)
|
|
|
|
// Test conditional context for target SDK version 28.
|
|
android.AssertStringDoesContain(t, "dexpreopt app cmd 28", cmd,
|
|
`--target-context-for-sdk 28`+
|
|
` PCL[/system/framework/org.apache.http.legacy.jar] `)
|
|
|
|
// Test conditional context for target SDK version 29.
|
|
android.AssertStringDoesContain(t, "dexpreopt app cmd 29", cmd,
|
|
`--target-context-for-sdk 29`+
|
|
` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]`+
|
|
`#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `)
|
|
|
|
// Test conditional context for target SDK version 30.
|
|
// "android.test.mock" is absent because "android.test.runner" is not used.
|
|
android.AssertStringDoesContain(t, "dexpreopt app cmd 30", cmd,
|
|
`--target-context-for-sdk 30`+
|
|
` PCL[/system/framework/android.test.base.jar] `)
|
|
|
|
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
|
|
android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd", cmd,
|
|
`--target-context-for-sdk any`+
|
|
` PCL[/system/framework/foo.jar]`+
|
|
`#PCL[/system/framework/non-sdk-lib.jar]`+
|
|
`#PCL[/system/framework/android.test.runner.jar]`+
|
|
`#PCL[/system/framework/bar.jar] `)
|
|
|
|
// Test conditional context for target SDK version 30.
|
|
// "android.test.mock" is present because "android.test.runner" is used.
|
|
android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd 30", cmd,
|
|
`--target-context-for-sdk 30`+
|
|
` PCL[/system/framework/android.test.base.jar]`+
|
|
`#PCL[/system/framework/android.test.mock.jar] `)
|
|
}
|
|
|
|
func TestDexpreoptBcp(t *testing.T) {
|
|
bp := `
|
|
java_sdk_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
api_packages: ["foo"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "bar",
|
|
srcs: ["a.java"],
|
|
api_packages: ["bar"],
|
|
permitted_packages: ["bar"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_app {
|
|
name: "app",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`
|
|
|
|
testCases := []struct {
|
|
name string
|
|
with bool
|
|
expect string
|
|
}{
|
|
{
|
|
name: "with updatable bcp",
|
|
with: true,
|
|
expect: "/system/framework/foo.jar:/system/framework/bar.jar",
|
|
},
|
|
{
|
|
name: "without updatable bcp",
|
|
with: false,
|
|
expect: "/system/framework/foo.jar",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
PrepareForTestWithJavaSdkLibraryFiles,
|
|
FixtureWithLastReleaseApis("runtime-library", "foo", "bar"),
|
|
dexpreopt.FixtureSetBootJars("platform:foo"),
|
|
dexpreopt.FixtureSetApexBootJars("platform:bar"),
|
|
dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
app := result.ModuleForTests("app", "android_common")
|
|
cmd := app.Rule("dexpreopt").RuleParams.Command
|
|
bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters
|
|
android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCodelessApp(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
noCode bool
|
|
}{
|
|
{
|
|
name: "normal",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
noCode: false,
|
|
},
|
|
{
|
|
name: "app without sources",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
noCode: true,
|
|
},
|
|
{
|
|
name: "app with libraries",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
static_libs: ["lib"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "lib",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
noCode: false,
|
|
},
|
|
{
|
|
name: "app with sourceless libraries",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
static_libs: ["lib"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
java_library {
|
|
name: "lib",
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
// TODO(jungjw): this should probably be true
|
|
noCode: false,
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
ctx := testApp(t, test.bp)
|
|
|
|
foo := ctx.ModuleForTests("foo", "android_common")
|
|
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
|
|
t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUncompressDex(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
bp string
|
|
|
|
uncompressedPlatform bool
|
|
uncompressedUnbundled bool
|
|
}{
|
|
{
|
|
name: "normal",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
uncompressedPlatform: true,
|
|
uncompressedUnbundled: false,
|
|
},
|
|
{
|
|
name: "use_embedded_dex",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
use_embedded_dex: true,
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
uncompressedPlatform: true,
|
|
uncompressedUnbundled: true,
|
|
},
|
|
{
|
|
name: "privileged",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
privileged: true,
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
`,
|
|
uncompressedPlatform: true,
|
|
uncompressedUnbundled: true,
|
|
},
|
|
{
|
|
name: "normal_uncompress_dex_true",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
uncompress_dex: true,
|
|
}
|
|
`,
|
|
uncompressedPlatform: true,
|
|
uncompressedUnbundled: true,
|
|
},
|
|
{
|
|
name: "normal_uncompress_dex_false",
|
|
bp: `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
uncompress_dex: false,
|
|
}
|
|
`,
|
|
uncompressedPlatform: false,
|
|
uncompressedUnbundled: false,
|
|
},
|
|
}
|
|
|
|
test := func(t *testing.T, bp string, want bool, unbundled bool) {
|
|
t.Helper()
|
|
|
|
result := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
PrepareForTestWithPrebuiltsOfCurrentApi,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
if unbundled {
|
|
variables.Unbundled_build = proptools.BoolPtr(true)
|
|
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
|
|
}
|
|
}),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
dex := foo.Rule("r8")
|
|
uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
|
|
aligned := foo.MaybeRule("zipalign").Rule != nil
|
|
|
|
android.AssertBoolEquals(t, "uncompressed in dex", want, uncompressedInDexJar)
|
|
|
|
android.AssertBoolEquals(t, "aligne", want, aligned)
|
|
}
|
|
|
|
for _, tt := range testCases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Run("platform", func(t *testing.T) {
|
|
test(t, tt.bp, tt.uncompressedPlatform, false)
|
|
})
|
|
t.Run("unbundled", func(t *testing.T) {
|
|
test(t, tt.bp, tt.uncompressedUnbundled, true)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string) {
|
|
if expectedValue != "" {
|
|
expectedFlag := "--" + flagName + " " + expectedValue
|
|
if !strings.Contains(aapt2Flags, expectedFlag) {
|
|
t.Errorf("%q is missing in aapt2 link flags, %q", expectedFlag, aapt2Flags)
|
|
}
|
|
} else {
|
|
unexpectedFlag := "--" + flagName
|
|
if strings.Contains(aapt2Flags, unexpectedFlag) {
|
|
t.Errorf("unexpected flag, %q is found in aapt2 link flags, %q", unexpectedFlag, aapt2Flags)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExportedProguardFlagFiles(t *testing.T) {
|
|
ctx, _ := testJava(t, `
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
static_libs: ["lib1"],
|
|
}
|
|
|
|
android_library {
|
|
name: "lib1",
|
|
sdk_version: "current",
|
|
optimize: {
|
|
proguard_flags_files: ["lib1proguard.cfg"],
|
|
}
|
|
}
|
|
`)
|
|
|
|
m := ctx.ModuleForTests("foo", "android_common")
|
|
hasLib1Proguard := false
|
|
for _, s := range m.Rule("java.r8").Implicits.Strings() {
|
|
if s == "lib1proguard.cfg" {
|
|
hasLib1Proguard = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !hasLib1Proguard {
|
|
t.Errorf("App does not use library proguard config")
|
|
}
|
|
}
|
|
|
|
func TestTargetSdkVersionManifestFixer(t *testing.T) {
|
|
platform_sdk_codename := "Tiramisu"
|
|
testCases := []struct {
|
|
name string
|
|
targetSdkVersionInBp string
|
|
targetSdkVersionExpected string
|
|
unbundledBuild bool
|
|
}{
|
|
{
|
|
name: "Non-Unbundled build: Android.bp has targetSdkVersion",
|
|
targetSdkVersionInBp: "30",
|
|
targetSdkVersionExpected: "30",
|
|
unbundledBuild: false,
|
|
},
|
|
{
|
|
name: "Unbundled build: Android.bp has targetSdkVersion",
|
|
targetSdkVersionInBp: "30",
|
|
targetSdkVersionExpected: "30",
|
|
unbundledBuild: true,
|
|
},
|
|
{
|
|
name: "Non-Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
|
|
targetSdkVersionInBp: platform_sdk_codename,
|
|
targetSdkVersionExpected: platform_sdk_codename,
|
|
unbundledBuild: false,
|
|
},
|
|
{
|
|
name: "Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
|
|
targetSdkVersionInBp: platform_sdk_codename,
|
|
targetSdkVersionExpected: "10000",
|
|
unbundledBuild: true,
|
|
},
|
|
|
|
{
|
|
name: "Non-Unbundled build: Android.bp has no targetSdkVersion",
|
|
targetSdkVersionExpected: platform_sdk_codename,
|
|
unbundledBuild: false,
|
|
},
|
|
{
|
|
name: "Unbundled build: Android.bp has no targetSdkVersion",
|
|
targetSdkVersionExpected: "10000",
|
|
unbundledBuild: true,
|
|
},
|
|
}
|
|
for _, testCase := range testCases {
|
|
bp := fmt.Sprintf(`
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
target_sdk_version: "%v",
|
|
}
|
|
`, testCase.targetSdkVersionInBp)
|
|
fixture := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
// explicitly set platform_sdk_codename to make the test deterministic
|
|
variables.Platform_sdk_codename = &platform_sdk_codename
|
|
variables.Platform_version_active_codenames = []string{platform_sdk_codename}
|
|
// create a non-empty list if unbundledBuild==true
|
|
if testCase.unbundledBuild {
|
|
variables.Unbundled_build_apps = []string{"apex_a", "apex_b"}
|
|
}
|
|
}),
|
|
)
|
|
|
|
result := fixture.RunTestWithBp(t, bp)
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
|
|
}
|
|
}
|
|
|
|
func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) {
|
|
platform_sdk_codename := "Tiramisu"
|
|
platform_sdk_version := 33
|
|
testCases := []struct {
|
|
name string
|
|
platform_sdk_final bool
|
|
targetSdkVersionInBp *string
|
|
targetSdkVersionExpected *string
|
|
updatable bool
|
|
}{
|
|
{
|
|
name: "Non-Updatable Module: Android.bp has older targetSdkVersion",
|
|
targetSdkVersionInBp: proptools.StringPtr("29"),
|
|
targetSdkVersionExpected: proptools.StringPtr("29"),
|
|
updatable: false,
|
|
},
|
|
{
|
|
name: "Updatable Module: Android.bp has older targetSdkVersion",
|
|
targetSdkVersionInBp: proptools.StringPtr("30"),
|
|
targetSdkVersionExpected: proptools.StringPtr("30"),
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: "Updatable Module: Android.bp has no targetSdkVersion",
|
|
targetSdkVersionExpected: proptools.StringPtr("10000"),
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: "[SDK finalised] Non-Updatable Module: Android.bp has older targetSdkVersion",
|
|
platform_sdk_final: true,
|
|
targetSdkVersionInBp: proptools.StringPtr("30"),
|
|
targetSdkVersionExpected: proptools.StringPtr("30"),
|
|
updatable: false,
|
|
},
|
|
{
|
|
name: "[SDK finalised] Updatable Module: Android.bp has older targetSdkVersion",
|
|
platform_sdk_final: true,
|
|
targetSdkVersionInBp: proptools.StringPtr("30"),
|
|
targetSdkVersionExpected: proptools.StringPtr("30"),
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: "[SDK finalised] Updatable Module: Android.bp has targetSdkVersion as platform sdk codename",
|
|
platform_sdk_final: true,
|
|
targetSdkVersionInBp: proptools.StringPtr(platform_sdk_codename),
|
|
targetSdkVersionExpected: proptools.StringPtr("33"),
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: "[SDK finalised] Updatable Module: Android.bp has no targetSdkVersion",
|
|
platform_sdk_final: true,
|
|
targetSdkVersionExpected: proptools.StringPtr("33"),
|
|
updatable: true,
|
|
},
|
|
}
|
|
for _, testCase := range testCases {
|
|
bp := fmt.Sprintf(`
|
|
android_app {
|
|
name: "foo",
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
target_sdk_version: "%v",
|
|
updatable: %t,
|
|
enforce_default_target_sdk_version: %t
|
|
}
|
|
`, proptools.String(testCase.targetSdkVersionInBp), testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
|
|
|
|
fixture := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.PrepareForTestWithAllowMissingDependencies,
|
|
android.PrepareForTestWithAndroidMk,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
// explicitly set following platform variables to make the test deterministic
|
|
variables.Platform_sdk_final = &testCase.platform_sdk_final
|
|
variables.Platform_sdk_version = &platform_sdk_version
|
|
variables.Platform_sdk_codename = &platform_sdk_codename
|
|
variables.Platform_version_active_codenames = []string{platform_sdk_codename}
|
|
variables.Unbundled_build = proptools.BoolPtr(true)
|
|
variables.Unbundled_build_apps = []string{"sampleModule"}
|
|
}),
|
|
)
|
|
|
|
result := fixture.RunTestWithBp(t, bp)
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
|
|
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected)
|
|
}
|
|
}
|
|
|
|
func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) {
|
|
platform_sdk_codename := "Tiramisu"
|
|
platform_sdk_version := 33
|
|
testCases := []struct {
|
|
name string
|
|
enforceDefaultTargetSdkVersion bool
|
|
expectedError string
|
|
platform_sdk_final bool
|
|
targetSdkVersionInBp string
|
|
targetSdkVersionExpected string
|
|
updatable bool
|
|
}{
|
|
{
|
|
name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: false,
|
|
targetSdkVersionInBp: "29",
|
|
targetSdkVersionExpected: "29",
|
|
updatable: false,
|
|
},
|
|
{
|
|
name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: true,
|
|
platform_sdk_final: true,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "33",
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: true,
|
|
platform_sdk_final: false,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "10000",
|
|
updatable: false,
|
|
},
|
|
{
|
|
name: "Not enforcing Target SDK Version for Updatable app",
|
|
enforceDefaultTargetSdkVersion: false,
|
|
expectedError: "Updatable apps must enforce default target sdk version",
|
|
targetSdkVersionInBp: "29",
|
|
targetSdkVersionExpected: "29",
|
|
updatable: true,
|
|
},
|
|
}
|
|
for _, testCase := range testCases {
|
|
errExpected := testCase.expectedError != ""
|
|
bp := fmt.Sprintf(`
|
|
android_app {
|
|
name: "foo",
|
|
enforce_default_target_sdk_version: %t,
|
|
sdk_version: "current",
|
|
min_sdk_version: "29",
|
|
target_sdk_version: "%v",
|
|
updatable: %t
|
|
}
|
|
`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable)
|
|
|
|
fixture := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.PrepareForTestWithAllowMissingDependencies,
|
|
android.PrepareForTestWithAndroidMk,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
// explicitly set following platform variables to make the test deterministic
|
|
variables.Platform_sdk_final = &testCase.platform_sdk_final
|
|
variables.Platform_sdk_version = &platform_sdk_version
|
|
variables.Platform_sdk_codename = &platform_sdk_codename
|
|
variables.Unbundled_build = proptools.BoolPtr(true)
|
|
variables.Unbundled_build_apps = []string{"sampleModule"}
|
|
}),
|
|
)
|
|
|
|
errorHandler := android.FixtureExpectsNoErrors
|
|
if errExpected {
|
|
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
|
|
}
|
|
result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
|
|
|
|
if !errExpected {
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) {
|
|
platform_sdk_codename := "Tiramisu"
|
|
platform_sdk_version := 33
|
|
testCases := []struct {
|
|
name string
|
|
enforceDefaultTargetSdkVersion bool
|
|
expectedError string
|
|
platform_sdk_final bool
|
|
targetSdkVersionInBp string
|
|
targetSdkVersionExpected string
|
|
}{
|
|
{
|
|
name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: false,
|
|
targetSdkVersionInBp: "29",
|
|
targetSdkVersionExpected: "29",
|
|
},
|
|
{
|
|
name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: true,
|
|
platform_sdk_final: true,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "33",
|
|
},
|
|
{
|
|
name: "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
|
|
enforceDefaultTargetSdkVersion: true,
|
|
platform_sdk_final: false,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "10000",
|
|
},
|
|
}
|
|
for _, testCase := range testCases {
|
|
errExpected := testCase.expectedError != ""
|
|
bp := fmt.Sprintf(`
|
|
android_test {
|
|
name: "foo",
|
|
enforce_default_target_sdk_version: %t,
|
|
min_sdk_version: "29",
|
|
target_sdk_version: "%v",
|
|
}
|
|
`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp)
|
|
|
|
fixture := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.PrepareForTestWithAllowMissingDependencies,
|
|
android.PrepareForTestWithAndroidMk,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
// explicitly set following platform variables to make the test deterministic
|
|
variables.Platform_sdk_final = &testCase.platform_sdk_final
|
|
variables.Platform_sdk_version = &platform_sdk_version
|
|
variables.Platform_sdk_codename = &platform_sdk_codename
|
|
variables.Unbundled_build = proptools.BoolPtr(true)
|
|
variables.Unbundled_build_apps = []string{"sampleModule"}
|
|
}),
|
|
)
|
|
|
|
errorHandler := android.FixtureExpectsNoErrors
|
|
if errExpected {
|
|
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
|
|
}
|
|
result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
|
|
|
|
if !errExpected {
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
android.PrepareForTestWithAllowMissingDependencies,
|
|
android.PrepareForTestWithAndroidMk,
|
|
).RunTestWithBp(t, `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
certificate: ":missing_certificate",
|
|
sdk_version: "current",
|
|
}`)
|
|
|
|
foo := result.ModuleForTests("foo", "android_common")
|
|
fooApk := foo.Output("foo.apk")
|
|
if fooApk.Rule != android.ErrorRule {
|
|
t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
|
|
}
|
|
android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
|
|
}
|
|
|
|
func TestAppIncludesJniPackages(t *testing.T) {
|
|
ctx := android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
).RunTestWithBp(t, `
|
|
android_library_import {
|
|
name: "aary-nodeps",
|
|
aars: ["aary.aar"],
|
|
extract_jni: true,
|
|
}
|
|
|
|
android_library {
|
|
name: "aary-lib",
|
|
sdk_version: "current",
|
|
min_sdk_version: "21",
|
|
static_libs: ["aary-nodeps"],
|
|
}
|
|
|
|
android_app {
|
|
name: "aary-lib-dep",
|
|
sdk_version: "current",
|
|
min_sdk_version: "21",
|
|
manifest: "AndroidManifest.xml",
|
|
static_libs: ["aary-lib"],
|
|
use_embedded_native_libs: true,
|
|
}
|
|
|
|
android_app {
|
|
name: "aary-import-dep",
|
|
sdk_version: "current",
|
|
min_sdk_version: "21",
|
|
manifest: "AndroidManifest.xml",
|
|
static_libs: ["aary-nodeps"],
|
|
use_embedded_native_libs: true,
|
|
}
|
|
|
|
android_app {
|
|
name: "aary-no-use-embedded",
|
|
sdk_version: "current",
|
|
min_sdk_version: "21",
|
|
manifest: "AndroidManifest.xml",
|
|
static_libs: ["aary-nodeps"],
|
|
}`)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
hasPackage bool
|
|
}{
|
|
{
|
|
name: "aary-import-dep",
|
|
hasPackage: true,
|
|
},
|
|
{
|
|
name: "aary-lib-dep",
|
|
hasPackage: true,
|
|
},
|
|
{
|
|
name: "aary-no-use-embedded",
|
|
hasPackage: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
app := ctx.ModuleForTests(tc.name, "android_common")
|
|
|
|
outputFile := "jnilibs.zip"
|
|
jniOutputLibZip := app.MaybeOutput(outputFile)
|
|
if jniOutputLibZip.Rule == nil && !tc.hasPackage {
|
|
return
|
|
}
|
|
|
|
jniPackage := "arm64-v8a_jni.zip"
|
|
inputs := jniOutputLibZip.Inputs
|
|
foundPackage := false
|
|
for i := 0; i < len(inputs); i++ {
|
|
if strings.Contains(inputs[i].String(), jniPackage) {
|
|
foundPackage = true
|
|
}
|
|
}
|
|
if foundPackage != tc.hasPackage {
|
|
t.Errorf("expected to find %v in %v inputs; inputs = %v", jniPackage, outputFile, inputs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTargetSdkVersionMtsTests(t *testing.T) {
|
|
platformSdkCodename := "Tiramisu"
|
|
android_test := "android_test"
|
|
android_test_helper_app := "android_test_helper_app"
|
|
bpTemplate := `
|
|
%v {
|
|
name: "mytest",
|
|
target_sdk_version: "%v",
|
|
test_suites: ["othersuite", "%v"],
|
|
}
|
|
`
|
|
testCases := []struct {
|
|
desc string
|
|
moduleType string
|
|
targetSdkVersionInBp string
|
|
targetSdkVersionExpected string
|
|
testSuites string
|
|
}{
|
|
{
|
|
desc: "Non-MTS android_test_apps targeting current should not be upgraded to 10000",
|
|
moduleType: android_test,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: platformSdkCodename,
|
|
testSuites: "non-mts-suite",
|
|
},
|
|
{
|
|
desc: "MTS android_test_apps targeting released sdks should not be upgraded to 10000",
|
|
moduleType: android_test,
|
|
targetSdkVersionInBp: "29",
|
|
targetSdkVersionExpected: "29",
|
|
testSuites: "mts-suite",
|
|
},
|
|
{
|
|
desc: "MTS android_test_apps targeting current should be upgraded to 10000",
|
|
moduleType: android_test,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "10000",
|
|
testSuites: "mts-suite",
|
|
},
|
|
{
|
|
desc: "MTS android_test_helper_apps targeting current should be upgraded to 10000",
|
|
moduleType: android_test_helper_app,
|
|
targetSdkVersionInBp: "current",
|
|
targetSdkVersionExpected: "10000",
|
|
testSuites: "mts-suite",
|
|
},
|
|
}
|
|
fixture := android.GroupFixturePreparers(
|
|
prepareForJavaTest,
|
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
|
variables.Platform_sdk_codename = &platformSdkCodename
|
|
variables.Platform_version_active_codenames = []string{platformSdkCodename}
|
|
}),
|
|
)
|
|
for _, testCase := range testCases {
|
|
result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites))
|
|
mytest := result.ModuleForTests("mytest", "android_common")
|
|
manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
|
android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
|
|
}
|
|
}
|