123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // 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 (
- "reflect"
- "testing"
- "android/soong/android"
- "android/soong/java"
- "github.com/google/blueprint"
- )
- // Contains tests for java.CreateClasspathElements logic from java/classpath_element.go that
- // requires apexes.
- // testClasspathElementContext is a ClasspathElementContext suitable for use in tests.
- type testClasspathElementContext struct {
- testContext *android.TestContext
- module android.Module
- errs []error
- }
- func (t *testClasspathElementContext) OtherModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool {
- return t.testContext.ModuleHasProvider(module, provider)
- }
- func (t *testClasspathElementContext) OtherModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} {
- return t.testContext.ModuleProvider(module, provider)
- }
- func (t *testClasspathElementContext) ModuleErrorf(fmt string, args ...interface{}) {
- t.errs = append(t.errs, t.testContext.ModuleErrorf(t.module, fmt, args...))
- }
- var _ java.ClasspathElementContext = (*testClasspathElementContext)(nil)
- func TestCreateClasspathElements(t *testing.T) {
- preparer := android.GroupFixturePreparers(
- prepareForTestWithPlatformBootclasspath,
- prepareForTestWithArtApex,
- prepareForTestWithMyapex,
- // For otherapex.
- android.FixtureMergeMockFs(android.MockFS{
- "system/sepolicy/apex/otherapex-file_contexts": nil,
- }),
- java.PrepareForTestWithJavaSdkLibraryFiles,
- java.FixtureWithLastReleaseApis("foo", "othersdklibrary"),
- java.FixtureConfigureApexBootJars("myapex:bar"),
- android.FixtureWithRootAndroidBp(`
- apex {
- name: "com.android.art",
- key: "com.android.art.key",
- bootclasspath_fragments: [
- "art-bootclasspath-fragment",
- ],
- java_libs: [
- "othersdklibrary",
- ],
- updatable: false,
- }
- apex_key {
- name: "com.android.art.key",
- public_key: "com.android.art.avbpubkey",
- private_key: "com.android.art.pem",
- }
- bootclasspath_fragment {
- name: "art-bootclasspath-fragment",
- image_name: "art",
- apex_available: [
- "com.android.art",
- ],
- contents: [
- "baz",
- "quuz",
- ],
- hidden_api: {
- split_packages: ["*"],
- },
- }
- java_library {
- name: "baz",
- apex_available: [
- "com.android.art",
- ],
- srcs: ["b.java"],
- installable: true,
- }
- java_library {
- name: "quuz",
- apex_available: [
- "com.android.art",
- ],
- srcs: ["b.java"],
- installable: true,
- }
- apex {
- name: "myapex",
- key: "myapex.key",
- bootclasspath_fragments: [
- "mybootclasspath-fragment",
- ],
- java_libs: [
- "othersdklibrary",
- ],
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- bootclasspath_fragment {
- name: "mybootclasspath-fragment",
- apex_available: [
- "myapex",
- ],
- contents: [
- "bar",
- ],
- hidden_api: {
- split_packages: ["*"],
- },
- }
- java_library {
- name: "bar",
- srcs: ["b.java"],
- installable: true,
- apex_available: ["myapex"],
- permitted_packages: ["bar"],
- }
- java_sdk_library {
- name: "foo",
- srcs: ["b.java"],
- }
- java_sdk_library {
- name: "othersdklibrary",
- srcs: ["b.java"],
- shared_library: false,
- apex_available: [
- "com.android.art",
- "myapex",
- ],
- }
- apex {
- name: "otherapex",
- key: "otherapex.key",
- java_libs: [
- "otherapexlibrary",
- ],
- updatable: false,
- }
- apex_key {
- name: "otherapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- java_library {
- name: "otherapexlibrary",
- srcs: ["b.java"],
- installable: true,
- apex_available: ["otherapex"],
- permitted_packages: ["otherapexlibrary"],
- }
- platform_bootclasspath {
- name: "myplatform-bootclasspath",
- fragments: [
- {
- apex: "com.android.art",
- module: "art-bootclasspath-fragment",
- },
- {
- apex: "myapex",
- module: "mybootclasspath-fragment",
- },
- ],
- }
- `),
- )
- result := preparer.RunTest(t)
- artFragment := result.Module("art-bootclasspath-fragment", "android_common_apex10000")
- artBaz := result.Module("baz", "android_common_apex10000")
- artQuuz := result.Module("quuz", "android_common_apex10000")
- myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
- myBar := result.Module("bar", "android_common_apex10000")
- other := result.Module("othersdklibrary", "android_common_apex10000")
- otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
- platformFoo := result.Module("quuz", "android_common")
- bootclasspath := result.Module("myplatform-bootclasspath", "android_common")
- // Use a custom assertion method instead of AssertDeepEquals as the latter formats the output
- // using %#v which results in meaningless output as ClasspathElements are pointers.
- assertElementsEquals := func(t *testing.T, message string, expected, actual java.ClasspathElements) {
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("%s: expected:\n %s\n got:\n %s", message, expected, actual)
- }
- }
- expectFragmentElement := func(module android.Module, contents ...android.Module) java.ClasspathElement {
- return &java.ClasspathFragmentElement{module, contents}
- }
- expectLibraryElement := func(module android.Module) java.ClasspathElement {
- return &java.ClasspathLibraryElement{module}
- }
- newCtx := func() *testClasspathElementContext {
- return &testClasspathElementContext{testContext: result.TestContext, module: bootclasspath}
- }
- // Verify that CreateClasspathElements works when given valid input.
- t.Run("art:baz, art:quuz, my:bar, foo", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, artQuuz, myBar, platformFoo}, []android.Module{artFragment, myFragment})
- expectedElements := java.ClasspathElements{
- expectFragmentElement(artFragment, artBaz, artQuuz),
- expectFragmentElement(myFragment, myBar),
- expectLibraryElement(platformFoo),
- }
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
- // Verify that CreateClasspathElements detects when an apex has multiple fragments.
- t.Run("multiple fragments for same apex", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{artFragment, artFragment})
- android.FailIfNoMatchingErrors(t, "apex com.android.art has multiple fragments, art-bootclasspath-fragment{.*} and art-bootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
- // Verify that CreateClasspathElements detects when a library is in multiple fragments.
- t.Run("library from multiple fragments", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{other}, []android.Module{artFragment, myFragment})
- android.FailIfNoMatchingErrors(t, "library othersdklibrary{.*} is in two separate fragments, art-bootclasspath-fragment{.*} and mybootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
- // Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
- // are separated by a library from another fragment.
- t.Run("discontiguous separated by fragment", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, myBar, artQuuz, platformFoo}, []android.Module{artFragment, myFragment})
- expectedElements := java.ClasspathElements{
- expectFragmentElement(artFragment, artBaz, artQuuz),
- expectFragmentElement(myFragment, myBar),
- expectLibraryElement(platformFoo),
- }
- assertElementsEquals(t, "elements", expectedElements, elements)
- android.FailIfNoMatchingErrors(t, "libraries from the same fragment must be contiguous, however baz{.*} and quuz{os:android,arch:common,apex:apex10000} from fragment art-bootclasspath-fragment{.*} are separated by libraries from fragment mybootclasspath-fragment{.*} like bar{.*}", ctx.errs)
- })
- // Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
- // are separated by a standalone library.
- t.Run("discontiguous separated by library", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, platformFoo, artQuuz, myBar}, []android.Module{artFragment, myFragment})
- expectedElements := java.ClasspathElements{
- expectFragmentElement(artFragment, artBaz, artQuuz),
- expectLibraryElement(platformFoo),
- expectFragmentElement(myFragment, myBar),
- }
- assertElementsEquals(t, "elements", expectedElements, elements)
- android.FailIfNoMatchingErrors(t, "libraries from the same fragment must be contiguous, however baz{.*} and quuz{os:android,arch:common,apex:apex10000} from fragment art-bootclasspath-fragment{.*} are separated by library quuz{.*}", ctx.errs)
- })
- // Verify that CreateClasspathElements detects when there a library on the classpath that
- // indicates it is from an apex the supplied fragments list does not contain a fragment for that
- // apex.
- t.Run("no fragment for apex", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, otherApexLibrary}, []android.Module{artFragment})
- expectedElements := java.ClasspathElements{
- expectFragmentElement(artFragment, artBaz),
- }
- assertElementsEquals(t, "elements", expectedElements, elements)
- android.FailIfNoMatchingErrors(t, `library otherapexlibrary{.*} is from apexes \[otherapex\] which have no corresponding fragment in \[art-bootclasspath-fragment{.*}\]`, ctx.errs)
- })
- }
|