Files
build_soong/apex/systemserver_classpath_fragment_test.go
Spandan Das e21a8d4dc6 Fix the args used to dexpreopt system server jars in prebuilt apexes
For prebuilts, java.dexpreopt gets called twice
1. in the context of the top-level prebuilt apex
2. in the context of the java_library shim

Only the artifacts of (1) get installed. The artifacts generated by 2)
are unused. However the args used to generate the artifacts of (1) are
incorrect. It uses moduleName(ctx) to do special-handling of apex system
server jars. This special-handling does not happen in (1), so although
dexpreopt artficats get generated, they get generated with the wrong
args.

To fix this, add an additional parameter in java.dexpreopt to pass the
libraryName explicitly.

Details
- Delete moduleName function. This was used to determine the java
  library name, which is no longer safe
- Add a libraryName parameter to java.dexpreopt
- Most module types will use j.Name() as libraryName
- prebuilt_apex and apex_set will iterate over its `contents` and use
  each element as libraryName when invoking java.dexpreopt

With the correct args passed from (1), we can drop j.dexpreopt from (2)
completely. Dropping (2) also breaks profile guided dexpreopt tests.
These currently operate on (2). They will be moved to (1) in the next CL
of this stack.

Test: presubmits
Test: lunch cf_x86_64_auto-trunk_staging-userdebug && m nothing (this
was a postsubmit failure with aosp/2923733)
Test: art_standalone_dexpreopt_tests on next https://android-build.corp.google.com/builds/abtd/run/L86000030001579256
Test: art-gtest on git_master-art-host https://android-build.corp.google.com/builds/abtd/run/L07800030001550262

Bug: 308790457
Bug: 322255144

Change-Id: I8eb604c82f1fa5289d3cd1a20084d56e4d7485e3
2024-01-26 18:06:41 +00:00

461 lines
10 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 apex
import (
"strings"
"testing"
"android/soong/android"
"android/soong/dexpreopt"
"android/soong/java"
)
var prepareForTestWithSystemserverclasspathFragment = android.GroupFixturePreparers(
java.PrepareForTestWithDexpreopt,
PrepareForTestWithApexBuildComponents,
)
func TestSystemserverclasspathFragmentContents(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"),
).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: [
"mysystemserverclasspathfragment",
],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: [
"myapex",
],
}
java_library {
name: "bar",
srcs: ["c.java"],
installable: true,
dex_preopt: {
profile: "bar-art-profile",
},
apex_available: [
"myapex",
],
}
java_library {
name: "baz",
srcs: ["d.java"],
installable: true,
dex_preopt: {
profile_guided: true, // ignored
},
apex_available: [
"myapex",
],
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: [
"foo",
"bar",
"baz",
],
apex_available: [
"myapex",
],
}
`)
ctx := result.TestContext
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"etc/classpaths/systemserverclasspath.pb",
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
"javalib/baz.jar",
})
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
`dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
})
assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false)
assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true)
assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false)
}
func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: [
"mysystemserverclasspathfragment",
],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: [
"myapex",
],
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
generate_classpaths_proto: false,
contents: [
"foo",
],
apex_available: [
"myapex",
],
}
`)
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex", []string{
"javalib/foo.jar",
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
`dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
})
}
func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) {
android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
`in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS`)).
RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: [
"mysystemserverclasspathfragment",
],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: ["myapex"],
}
java_library {
name: "bar",
srcs: ["b.java"],
installable: true,
apex_available: ["myapex"],
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: [
"foo",
"bar",
],
apex_available: [
"myapex",
],
}
`)
}
func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
// TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
t.Skip()
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, `
prebuilt_apex {
name: "myapex",
arch: {
arm64: {
src: "myapex-arm64.apex",
},
arm: {
src: "myapex-arm.apex",
},
},
exported_systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
}
java_import {
name: "foo",
jars: ["foo.jar"],
apex_available: [
"myapex",
],
}
java_import {
name: "bar",
jars: ["bar.jar"],
dex_preopt: {
profile_guided: true,
},
apex_available: [
"myapex",
],
}
prebuilt_systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
prefer: true,
contents: [
"foo",
"bar",
],
apex_available: [
"myapex",
],
}
`)
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
`dex2oatd`,
`prebuilt_myapex.apex.selector`,
`prebuilt_myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`,
})
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
`prebuilt_bar`,
`prebuilt_foo`,
`prebuilt_myapex.deapexer`,
})
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
})
assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
}
func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"),
).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: [
"mysystemserverclasspathfragment",
],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: [
"myapex",
],
}
java_library {
name: "bar",
srcs: ["c.java"],
dex_preopt: {
profile: "bar-art-profile",
},
installable: true,
apex_available: [
"myapex",
],
}
java_library {
name: "baz",
srcs: ["d.java"],
dex_preopt: {
profile_guided: true, // ignored
},
installable: true,
apex_available: [
"myapex",
],
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
standalone_contents: [
"foo",
"bar",
"baz",
],
apex_available: [
"myapex",
],
}
`)
ctx := result.TestContext
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"etc/classpaths/systemserverclasspath.pb",
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
"javalib/baz.jar",
})
assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false)
assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true)
assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false)
}
func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
// TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
t.Skip()
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, `
prebuilt_apex {
name: "myapex",
arch: {
arm64: {
src: "myapex-arm64.apex",
},
arm: {
src: "myapex-arm.apex",
},
},
exported_systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
}
java_import {
name: "foo",
jars: ["foo.jar"],
apex_available: [
"myapex",
],
}
java_import {
name: "bar",
jars: ["bar.jar"],
dex_preopt: {
profile_guided: true,
},
apex_available: [
"myapex",
],
}
prebuilt_systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
prefer: true,
standalone_contents: [
"foo",
"bar",
],
apex_available: [
"myapex",
],
}
`)
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
`prebuilt_bar`,
`prebuilt_foo`,
`prebuilt_myapex.deapexer`,
})
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
})
assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
}
func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
dexpreopt := ctx.ModuleForTests(moduleName, variant).Rule("dexpreopt")
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
if expected != actual {
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
}
}