|  | // 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" | 
|  | ) | 
|  |  | 
|  | // Contains some simple tests for platform_bootclasspath. | 
|  |  | 
|  | var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( | 
|  | PrepareForTestWithJavaDefaultModules, | 
|  | ) | 
|  |  | 
|  | 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) | 
|  | }) | 
|  |  | 
|  | fooSourceSrc := "source/a.java" | 
|  | barSrc := "a.java" | 
|  |  | 
|  | checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) { | 
|  | t.Helper() | 
|  | srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar") | 
|  | android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar") | 
|  | android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings()) | 
|  | } | 
|  | t.Run("source", func(t *testing.T) { | 
|  | result := android.GroupFixturePreparers( | 
|  | preparer, | 
|  | addSourceBootclassPathModule, | 
|  | ).RunTest(t) | 
|  |  | 
|  | CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ | 
|  | "platform:foo", | 
|  | "platform:bar", | 
|  | }) | 
|  | checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ | 
|  | fooSourceSrc, | 
|  | barSrc, | 
|  | }) | 
|  | }) | 
|  |  | 
|  | 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", | 
|  | }) | 
|  | checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ | 
|  | // TODO(b/151360309): This should also have the srcs for prebuilt_foo | 
|  | barSrc, | 
|  | }) | 
|  | }) | 
|  |  | 
|  | 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", | 
|  | }) | 
|  | checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ | 
|  | fooSourceSrc, | 
|  | barSrc, | 
|  | }) | 
|  | }) | 
|  |  | 
|  | 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", | 
|  | }) | 
|  | checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ | 
|  | // TODO(b/151360309): This should also have the srcs for prebuilt_foo | 
|  | barSrc, | 
|  | }) | 
|  | }) | 
|  |  | 
|  | 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", | 
|  | }) | 
|  | checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ | 
|  | // TODO(b/151360309): This should also have the srcs for prebuilt_foo | 
|  | barSrc, | 
|  | }) | 
|  | }) | 
|  | } | 
|  |  | 
|  | 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.impl/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) | 
|  | } |