// 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 platform_bootclasspath. var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, dexpreopt.PrepareForTestByEnablingDexpreopt, ) func TestPlatformBootclasspath(t *testing.T) { preparer := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, FixtureConfigureBootJars("platform:foo", "system_ext:bar"), android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } java_library { name: "bar", srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, system_ext_specific: true, } `), ) var addSourceBootclassPathModule = android.FixtureAddTextFile("source/Android.bp", ` java_library { name: "foo", host_supported: true, // verify that b/232106778 is fixed srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, } `) var addPrebuiltBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", ` java_import { name: "foo", jars: ["a.jar"], compile_dex: true, prefer: false, } `) var addPrebuiltPreferredBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", ` java_import { name: "foo", jars: ["a.jar"], compile_dex: true, prefer: true, } `) t.Run("missing", func(t *testing.T) { preparer. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"platform-bootclasspath" depends on undefined module "foo"`)). RunTest(t) }) t.Run("source", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, ).RunTest(t) CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ "platform:foo", "platform:bar", }) }) t.Run("prebuilt", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, addPrebuiltBootclassPathModule, ).RunTest(t) CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ "platform:prebuilt_foo", "platform:bar", }) }) t.Run("source+prebuilt - source preferred", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, addPrebuiltBootclassPathModule, ).RunTest(t) CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ "platform:foo", "platform:bar", }) }) t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, addPrebuiltPreferredBootclassPathModule, ).RunTest(t) CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ "platform:prebuilt_foo", "platform:bar", }) }) t.Run("dex import", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, android.FixtureAddTextFile("deximport/Android.bp", ` dex_import { name: "foo", jars: ["a.jar"], } `), ).RunTest(t) CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ "platform:prebuilt_foo", "platform:bar", }) }) } func TestPlatformBootclasspathVariant(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } `), ).RunTest(t) variants := result.ModuleVariantsForTests("platform-bootclasspath") android.AssertIntEquals(t, "expect 1 variant", 1, len(variants)) } func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } `), ).RunTest(t) p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) android.AssertStringEquals(t, "output filepath", "bootclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base()) android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) } func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { preparer := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } `), ) t.Run("AndroidMkEntries", func(t *testing.T) { result := preparer.RunTest(t) p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) android.AssertIntEquals(t, "AndroidMkEntries count", 2, len(entries)) }) t.Run("hiddenapi-flags-entry", func(t *testing.T) { result := preparer.RunTest(t) p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) got := entries[0].OutputFile android.AssertBoolEquals(t, "valid output path", true, got.Valid()) android.AssertSame(t, "output filepath", p.hiddenAPIFlagsCSV, got.Path()) }) t.Run("classpath-fragment-entry", func(t *testing.T) { result := preparer.RunTest(t) want := map[string][]string{ "LOCAL_MODULE": {"platform-bootclasspath"}, "LOCAL_MODULE_CLASS": {"ETC"}, "LOCAL_INSTALLED_MODULE_STEM": {"bootclasspath.pb"}, // Output and Install paths are tested separately in TestPlatformBootclasspath_ClasspathFragmentPaths } p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) got := entries[1] for k, expectedValue := range want { if value, ok := got.EntryMap[k]; ok { android.AssertDeepEquals(t, k, expectedValue, value) } else { t.Errorf("No %s defined, saw %q", k, got.EntryMap) } } }) } func TestPlatformBootclasspath_Dist(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, FixtureConfigureBootJars("platform:foo", "platform:bar"), android.PrepareForTestWithAndroidMk, android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", dists: [ { targets: ["droidcore"], tag: "hiddenapi-flags.csv", }, ], } java_library { name: "bar", srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, } java_library { name: "foo", srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, } `), ).RunTest(t) platformBootclasspath := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) entries := android.AndroidMkEntriesForTest(t, result.TestContext, platformBootclasspath) goals := entries[0].GetDistForGoals(platformBootclasspath) android.AssertStringEquals(t, "platform dist goals phony", ".PHONY: droidcore\n", goals[0]) android.AssertStringDoesContain(t, "platform dist goals meta check", goals[1], "$(if $(strip $(ALL_TARGETS.") android.AssertStringDoesContain(t, "platform dist goals meta assign", goals[1], "),,$(eval ALL_TARGETS.") android.AssertStringEquals(t, "platform dist goals call", "$(call dist-for-goals,droidcore,out/soong/hiddenapi/hiddenapi-flags.csv:hiddenapi-flags.csv)\n", android.StringRelativeToTop(result.Config, goals[2])) } func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("bar"), FixtureConfigureBootJars("platform:foo", "platform:bar"), ).RunTestWithBp(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, } platform_bootclasspath { name: "myplatform-bootclasspath", } `) // Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that // creates the index.csv file. platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common") var rule android.TestingBuildParams // All the intermediate rules use the same inputs. expectedIntermediateInputs := ` out/soong/.intermediates/bar/android_common/javac/bar.jar out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar out/soong/.intermediates/foo/android_common/javac/foo.jar ` // Check flags output. rule = platformBootclasspath.Output("hiddenapi-monolithic/annotation-flags-from-classes.csv") CheckHiddenAPIRuleInputs(t, "intermediate flags", expectedIntermediateInputs, rule) rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-flags.csv") CheckHiddenAPIRuleInputs(t, "monolithic flags", ` out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv out/soong/hiddenapi/hiddenapi-stub-flags.txt `, rule) // Check metadata output. rule = platformBootclasspath.Output("hiddenapi-monolithic/metadata-from-classes.csv") CheckHiddenAPIRuleInputs(t, "intermediate metadata", expectedIntermediateInputs, rule) rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv") CheckHiddenAPIRuleInputs(t, "monolithic metadata", ` out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv `, rule) // Check index output. rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv") CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule) rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-index.csv") CheckHiddenAPIRuleInputs(t, "monolithic index", ` out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv `, rule) }