280a31aac3
Previously, the stub dex jars for each HiddenAPIScope was created by merging the stub dex jars provided by each module for that scope. Then the widest stub dex jars were chosen. So, if module A provided public, system and test stub dex jars and module B provided only public then the stub dex jars for each scope would be: * public -> A,B * system -> A * test -> A So, the widest API scope for which there are stub dex jars is "test" and so the widest stub dex jars would just come from module A and not module B. So, when "hiddenapi list" is run for module C which depends on modules A and B it only gets given stub dex jars for module A which means that it cannot resolve all the types that C may use which can lead to incorrect flags being generated. This change does not merge the stub dex jars from each module together and instead keeps them separate by module. The widest stub dex jars list is constructed by asking each module in turn for their widest stub dex jars. e.g. Given the above example we would have: Module A: * public * system * test <- widest Module B: * public <- widest So, the widest stub dex jars will be A's test and B's public stub dex jars. Bug: 179354495 Test: m out/soong/hiddenapi-flags.csv - make sure that this does not change the file. Change-Id: Ib137825ebffe94b2bf220732bae6077f7b7ac6db
278 lines
8.6 KiB
Go
278 lines
8.6 KiB
Go
// Copyright (C) 2021 The Android Open Source Project
|
|
//
|
|
// 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 (
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
"android/soong/dexpreopt"
|
|
)
|
|
|
|
// Contains some simple tests for bootclasspath_fragment logic, additional tests can be found in
|
|
// apex/bootclasspath_fragment_test.go as the ART boot image requires modules from the ART apex.
|
|
|
|
var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers(
|
|
PrepareForTestWithJavaDefaultModules,
|
|
dexpreopt.PrepareForTestByEnablingDexpreopt,
|
|
)
|
|
|
|
func TestBootclasspathFragment_UnknownImageName(t *testing.T) {
|
|
prepareForTestWithBootclasspathFragment.
|
|
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
|
|
RunTestWithBp(t, `
|
|
bootclasspath_fragment {
|
|
name: "unknown-bootclasspath-fragment",
|
|
image_name: "unknown",
|
|
contents: ["foo"],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) {
|
|
prepareForTestWithBootclasspathFragment.
|
|
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
|
|
RunTestWithBp(t, `
|
|
prebuilt_bootclasspath_fragment {
|
|
name: "unknown-bootclasspath-fragment",
|
|
image_name: "unknown",
|
|
contents: ["foo"],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T) {
|
|
android.GroupFixturePreparers(
|
|
prepareForTestWithBootclasspathFragment,
|
|
dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"),
|
|
).
|
|
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
`\QArtApexJars is invalid as it requests a platform variant of "foo"\E`)).
|
|
RunTestWithBp(t, `
|
|
bootclasspath_fragment {
|
|
name: "bootclasspath-fragment",
|
|
image_name: "art",
|
|
contents: ["foo", "bar"],
|
|
apex_available: [
|
|
"apex",
|
|
],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testing.T) {
|
|
android.GroupFixturePreparers(
|
|
prepareForTestWithBootclasspathFragment,
|
|
dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"),
|
|
).
|
|
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
`\QArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex "apex1" and "apex2"\E`)).
|
|
RunTestWithBp(t, `
|
|
bootclasspath_fragment {
|
|
name: "bootclasspath-fragment",
|
|
image_name: "art",
|
|
contents: ["foo", "bar"],
|
|
apex_available: [
|
|
"apex1",
|
|
"apex2",
|
|
],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestBootclasspathFragment_Coverage(t *testing.T) {
|
|
prepareForTestWithFrameworkCoverage := android.FixtureMergeEnv(map[string]string{
|
|
"EMMA_INSTRUMENT": "true",
|
|
"EMMA_INSTRUMENT_FRAMEWORK": "true",
|
|
})
|
|
|
|
prepareWithBp := android.FixtureWithRootAndroidBp(`
|
|
bootclasspath_fragment {
|
|
name: "myfragment",
|
|
contents: [
|
|
"mybootlib",
|
|
],
|
|
api: {
|
|
stub_libs: [
|
|
"mysdklibrary",
|
|
],
|
|
},
|
|
coverage: {
|
|
contents: [
|
|
"coveragelib",
|
|
],
|
|
api: {
|
|
stub_libs: [
|
|
"mycoveragestubs",
|
|
],
|
|
},
|
|
},
|
|
}
|
|
|
|
java_library {
|
|
name: "mybootlib",
|
|
srcs: ["Test.java"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_library {
|
|
name: "coveragelib",
|
|
srcs: ["Test.java"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "mysdklibrary",
|
|
srcs: ["Test.java"],
|
|
compile_dex: true,
|
|
public: {enabled: true},
|
|
system: {enabled: true},
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "mycoveragestubs",
|
|
srcs: ["Test.java"],
|
|
compile_dex: true,
|
|
public: {enabled: true},
|
|
}
|
|
`)
|
|
|
|
checkContents := func(t *testing.T, result *android.TestResult, expected ...string) {
|
|
module := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule)
|
|
android.AssertArrayString(t, "contents property", expected, module.properties.Contents)
|
|
}
|
|
|
|
preparer := android.GroupFixturePreparers(
|
|
prepareForTestWithBootclasspathFragment,
|
|
PrepareForTestWithJavaSdkLibraryFiles,
|
|
FixtureWithLastReleaseApis("mysdklibrary", "mycoveragestubs"),
|
|
prepareWithBp,
|
|
)
|
|
|
|
t.Run("without coverage", func(t *testing.T) {
|
|
result := preparer.RunTest(t)
|
|
checkContents(t, result, "mybootlib")
|
|
})
|
|
|
|
t.Run("with coverage", func(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithFrameworkCoverage,
|
|
preparer,
|
|
).RunTest(t)
|
|
checkContents(t, result, "mybootlib", "coveragelib")
|
|
})
|
|
}
|
|
|
|
func TestBootclasspathFragment_StubLibs(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithBootclasspathFragment,
|
|
PrepareForTestWithJavaSdkLibraryFiles,
|
|
FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
|
|
).RunTestWithBp(t, `
|
|
bootclasspath_fragment {
|
|
name: "myfragment",
|
|
contents: ["mysdklibrary"],
|
|
api: {
|
|
stub_libs: [
|
|
"mystublib",
|
|
"myothersdklibrary",
|
|
],
|
|
},
|
|
core_platform_api: {
|
|
stub_libs: ["mycoreplatform"],
|
|
},
|
|
}
|
|
|
|
java_library {
|
|
name: "mystublib",
|
|
srcs: ["Test.java"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "mysdklibrary",
|
|
srcs: ["a.java"],
|
|
shared_library: false,
|
|
public: {enabled: true},
|
|
system: {enabled: true},
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "myothersdklibrary",
|
|
srcs: ["a.java"],
|
|
shared_library: false,
|
|
public: {enabled: true},
|
|
}
|
|
|
|
java_sdk_library {
|
|
name: "mycoreplatform",
|
|
srcs: ["a.java"],
|
|
shared_library: false,
|
|
public: {enabled: true},
|
|
}
|
|
`)
|
|
|
|
fragment := result.Module("myfragment", "android_common")
|
|
info := result.ModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
|
|
|
|
stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
|
|
|
|
// Stubs jars for mysdklibrary
|
|
publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
|
|
systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
|
|
|
|
// Stubs jars for myothersdklibrary
|
|
otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
|
|
|
|
// Check that SdkPublic uses public stubs for all sdk libraries.
|
|
android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
|
|
|
|
// Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
|
|
// as it does not provide system stubs.
|
|
android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(SystemHiddenAPIScope))
|
|
|
|
// Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
|
|
// and public stubs for myothersdklibrary as it does not provide test stubs either.
|
|
android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(TestHiddenAPIScope))
|
|
|
|
// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
|
|
corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
|
|
android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(CorePlatformHiddenAPIScope))
|
|
|
|
// Check the widest stubs.. The list contains the widest stub dex jar provided by each module.
|
|
expectedWidestPaths := []string{
|
|
// mycoreplatform's widest API is core platform.
|
|
corePlatformStubsJar,
|
|
|
|
// myothersdklibrary's widest API is public.
|
|
otherPublicStubsJar,
|
|
|
|
// sdklibrary's widest API is system.
|
|
systemStubsJar,
|
|
|
|
// mystublib's only provides one API and so it must be the widest.
|
|
stubsJar,
|
|
}
|
|
|
|
android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
|
|
}
|