ec0fe1775b
Previously, when a prebuilt was preferred but did not provide a suitable boot dex jar both the source and the prebuilt were silently ignored which meant that the "hiddenapi list" command was not given a complete set of boot dex jars. That could either lead to incorrect hiddenapi flags being set or the "hiddenapi list" command failing if it could not find a class. Debugging the cause of either of those cases can be very time consuming so this change fails early and makes the cause very explicit. Bug: 181267622 Test: m nothing Change-Id: I6763ddb9ba90ed2e501d0cf7984f6655237e905d
339 lines
11 KiB
Go
339 lines
11 KiB
Go
// Copyright 2020 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"
|
|
"strings"
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir *string) android.Config {
|
|
config := testConfig(nil, bp, nil)
|
|
config.TestProductVariables.BootJars = android.CreateTestConfiguredJarList(bootJars)
|
|
config.TestProductVariables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
|
|
return config
|
|
}
|
|
|
|
func testContextWithHiddenAPI(config android.Config) *android.TestContext {
|
|
ctx := testContext(config)
|
|
RegisterHiddenApiSingletonComponents(ctx)
|
|
return ctx
|
|
}
|
|
|
|
func testHiddenAPIWithConfig(t *testing.T, config android.Config) *android.TestContext {
|
|
t.Helper()
|
|
|
|
ctx := testContextWithHiddenAPI(config)
|
|
|
|
run(t, ctx, config)
|
|
return ctx
|
|
}
|
|
|
|
func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string, prebuiltHiddenApiDir *string) (*android.TestContext, android.Config) {
|
|
config := testConfigWithBootJars(bp, bootJars, prebuiltHiddenApiDir)
|
|
|
|
return testHiddenAPIWithConfig(t, config), config
|
|
}
|
|
|
|
func testHiddenAPIUnbundled(t *testing.T, unbundled bool) (*android.TestContext, android.Config) {
|
|
config := testConfig(nil, ``, nil)
|
|
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(unbundled)
|
|
|
|
return testHiddenAPIWithConfig(t, config), config
|
|
}
|
|
|
|
func TestHiddenAPISingleton(t *testing.T) {
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
`, []string{"platform:foo"}, nil)
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
|
|
want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
}
|
|
|
|
func TestHiddenAPIIndexSingleton(t *testing.T) {
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
|
|
hiddenapi_additional_annotations: [
|
|
"foo-hiddenapi-annotations",
|
|
],
|
|
}
|
|
|
|
java_library {
|
|
name: "foo-hiddenapi-annotations",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
compile_dex: true,
|
|
prefer: false,
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "bar",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
`, []string{"platform:foo", "platform:bar"}, nil)
|
|
|
|
hiddenAPIIndex := ctx.SingletonForTests("hiddenapi_index")
|
|
indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
|
|
CheckHiddenAPIRuleInputs(t, `
|
|
.intermediates/bar/android_common/hiddenapi/index.csv
|
|
.intermediates/foo/android_common/hiddenapi/index.csv
|
|
`,
|
|
indexRule)
|
|
|
|
// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
|
|
// creates the index.csv file.
|
|
foo := ctx.ModuleForTests("foo", "android_common")
|
|
indexParams := foo.Output("hiddenapi/index.csv")
|
|
CheckHiddenAPIRuleInputs(t, `
|
|
.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
|
|
.intermediates/foo/android_common/javac/foo.jar
|
|
`, indexParams)
|
|
}
|
|
|
|
func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
|
|
config := testConfigWithBootJars(`
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
prefer: true,
|
|
}
|
|
`, []string{"platform:foo"}, nil)
|
|
|
|
ctx := testContextWithHiddenAPI(config)
|
|
|
|
runWithErrors(t, ctx, config,
|
|
"hiddenapi has determined that the source module \"foo\" should be ignored as it has been"+
|
|
" replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a"+
|
|
" suitable boot dex jar")
|
|
}
|
|
|
|
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
compile_dex: true,
|
|
}
|
|
`, []string{"platform:foo"}, nil)
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
|
|
want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
}
|
|
|
|
func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
compile_dex: true,
|
|
prefer: false,
|
|
}
|
|
`, []string{"platform:foo"}, nil)
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
|
|
fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
|
|
prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar"
|
|
if strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
|
|
t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
}
|
|
|
|
func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
compile_dex: true,
|
|
prefer: true,
|
|
}
|
|
`, []string{"platform:foo"}, nil)
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
|
|
prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
|
|
fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
|
|
if strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
|
|
t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
}
|
|
|
|
func TestHiddenAPISingletonSdks(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
unbundledBuild bool
|
|
publicStub string
|
|
systemStub string
|
|
testStub string
|
|
corePlatformStub string
|
|
}{
|
|
{
|
|
name: "testBundled",
|
|
unbundledBuild: false,
|
|
publicStub: "android_stubs_current",
|
|
systemStub: "android_system_stubs_current",
|
|
testStub: "android_test_stubs_current",
|
|
corePlatformStub: "legacy.core.platform.api.stubs",
|
|
}, {
|
|
name: "testUnbundled",
|
|
unbundledBuild: true,
|
|
publicStub: "sdk_public_current_android",
|
|
systemStub: "sdk_system_current_android",
|
|
testStub: "sdk_test_current_android",
|
|
corePlatformStub: "legacy.core.platform.api.stubs",
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ctx, _ := testHiddenAPIUnbundled(t, tc.unbundledBuild)
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
|
|
wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, wantPublicStubs) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantPublicStubs, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
|
|
wantSystemStubs := "--system-stub-classpath=" + generateSdkDexPath(tc.systemStub, tc.unbundledBuild)
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, wantSystemStubs) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantSystemStubs, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
|
|
wantTestStubs := "--test-stub-classpath=" + generateSdkDexPath(tc.testStub, tc.unbundledBuild)
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, wantTestStubs) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantTestStubs, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
|
|
wantCorePlatformStubs := "--core-platform-stub-classpath=" + generateDexPath(tc.corePlatformStub)
|
|
if !strings.Contains(hiddenapiRule.RuleParams.Command, wantCorePlatformStubs) {
|
|
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantCorePlatformStubs, hiddenapiRule.RuleParams.Command)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func generateDexedPath(subDir, dex, module string) string {
|
|
return fmt.Sprintf("%s/.intermediates/%s/android_common/%s/%s.jar", buildDir, subDir, dex, module)
|
|
}
|
|
|
|
func generateDexPath(module string) string {
|
|
return generateDexedPath(module, "dex", module)
|
|
}
|
|
|
|
func generateSdkDexPath(module string, unbundled bool) string {
|
|
if unbundled {
|
|
return generateDexedPath("prebuilts/sdk/"+module, "dex", module)
|
|
}
|
|
return generateDexPath(module)
|
|
}
|
|
|
|
func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
|
|
|
|
// The idea behind this test is to ensure that when the build is
|
|
// confugured with a PrebuiltHiddenApiDir that the rules for the
|
|
// hiddenapi singleton copy the prebuilts to the typical output
|
|
// location, and then use that output location for the hiddenapi encode
|
|
// dex step.
|
|
|
|
// Where to find the prebuilt hiddenapi files:
|
|
prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi"
|
|
|
|
ctx, _ := testHiddenAPIBootJars(t, `
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["a.jar"],
|
|
compile_dex: true,
|
|
}
|
|
`, []string{"platform:foo"}, &prebuiltHiddenApiDir)
|
|
|
|
expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
|
|
expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv"
|
|
expectedFlagsCsv := buildDir + "/hiddenapi/hiddenapi-flags.csv"
|
|
|
|
foo := ctx.ModuleForTests("foo", "android_common")
|
|
|
|
hiddenAPI := ctx.SingletonForTests("hiddenapi")
|
|
cpRule := hiddenAPI.Rule("Cp")
|
|
actualCpInput := cpRule.BuildParams.Input
|
|
actualCpOutput := cpRule.BuildParams.Output
|
|
encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
|
|
actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
|
|
|
|
if actualCpInput.String() != expectedCpInput {
|
|
t.Errorf("Prebuilt hiddenapi cp rule input mismatch, actual: %s, expected: %s", actualCpInput, expectedCpInput)
|
|
}
|
|
|
|
if actualCpOutput.String() != expectedCpOutput {
|
|
t.Errorf("Prebuilt hiddenapi cp rule output mismatch, actual: %s, expected: %s", actualCpOutput, expectedCpOutput)
|
|
}
|
|
|
|
if actualFlagsCsv != expectedFlagsCsv {
|
|
t.Errorf("Prebuilt hiddenapi encode dex rule flags csv mismatch, actual: %s, expected: %s", actualFlagsCsv, expectedFlagsCsv)
|
|
}
|
|
}
|