1// Copyright (C) 2021 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "testing" 19 20 "android/soong/android" 21) 22 23// Contains some simple tests for platform_bootclasspath. 24 25var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( 26 PrepareForTestWithJavaDefaultModules, 27) 28 29func TestPlatformBootclasspath(t *testing.T) { 30 preparer := android.GroupFixturePreparers( 31 prepareForTestWithPlatformBootclasspath, 32 FixtureConfigureBootJars("platform:foo", "system_ext:bar"), 33 android.FixtureWithRootAndroidBp(` 34 platform_bootclasspath { 35 name: "platform-bootclasspath", 36 } 37 38 java_library { 39 name: "bar", 40 srcs: ["a.java"], 41 system_modules: "none", 42 sdk_version: "none", 43 compile_dex: true, 44 system_ext_specific: true, 45 } 46 `), 47 ) 48 49 var addSourceBootclassPathModule = android.FixtureAddTextFile("source/Android.bp", ` 50 java_library { 51 name: "foo", 52 host_supported: true, // verify that b/232106778 is fixed 53 srcs: ["a.java"], 54 system_modules: "none", 55 sdk_version: "none", 56 compile_dex: true, 57 } 58 `) 59 60 var addPrebuiltBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", ` 61 java_import { 62 name: "foo", 63 jars: ["a.jar"], 64 compile_dex: true, 65 prefer: false, 66 } 67 `) 68 69 var addPrebuiltPreferredBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", ` 70 java_import { 71 name: "foo", 72 jars: ["a.jar"], 73 compile_dex: true, 74 prefer: true, 75 } 76 `) 77 78 t.Run("missing", func(t *testing.T) { 79 preparer. 80 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"platform-bootclasspath" depends on undefined module "foo"`)). 81 RunTest(t) 82 }) 83 84 fooSourceSrc := "source/a.java" 85 barSrc := "a.java" 86 87 checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) { 88 t.Helper() 89 srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar") 90 android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar") 91 android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings()) 92 } 93 t.Run("source", func(t *testing.T) { 94 result := android.GroupFixturePreparers( 95 preparer, 96 addSourceBootclassPathModule, 97 ).RunTest(t) 98 99 CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ 100 "platform:foo", 101 "platform:bar", 102 }) 103 checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ 104 fooSourceSrc, 105 barSrc, 106 }) 107 }) 108 109 t.Run("prebuilt", func(t *testing.T) { 110 result := android.GroupFixturePreparers( 111 preparer, 112 addPrebuiltBootclassPathModule, 113 ).RunTest(t) 114 115 CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ 116 "platform:prebuilt_foo", 117 "platform:bar", 118 }) 119 checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ 120 // TODO(b/151360309): This should also have the srcs for prebuilt_foo 121 barSrc, 122 }) 123 }) 124 125 t.Run("source+prebuilt - source preferred", func(t *testing.T) { 126 result := android.GroupFixturePreparers( 127 preparer, 128 addSourceBootclassPathModule, 129 addPrebuiltBootclassPathModule, 130 ).RunTest(t) 131 132 CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ 133 "platform:foo", 134 "platform:bar", 135 }) 136 checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ 137 fooSourceSrc, 138 barSrc, 139 }) 140 }) 141 142 t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) { 143 result := android.GroupFixturePreparers( 144 preparer, 145 addSourceBootclassPathModule, 146 addPrebuiltPreferredBootclassPathModule, 147 ).RunTest(t) 148 149 CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ 150 "platform:prebuilt_foo", 151 "platform:bar", 152 }) 153 checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ 154 // TODO(b/151360309): This should also have the srcs for prebuilt_foo 155 barSrc, 156 }) 157 }) 158 159 t.Run("dex import", func(t *testing.T) { 160 result := android.GroupFixturePreparers( 161 preparer, 162 android.FixtureAddTextFile("deximport/Android.bp", ` 163 dex_import { 164 name: "foo", 165 jars: ["a.jar"], 166 } 167 `), 168 ).RunTest(t) 169 170 CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{ 171 "platform:prebuilt_foo", 172 "platform:bar", 173 }) 174 checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ 175 // TODO(b/151360309): This should also have the srcs for prebuilt_foo 176 barSrc, 177 }) 178 }) 179} 180 181func TestPlatformBootclasspathVariant(t *testing.T) { 182 result := android.GroupFixturePreparers( 183 prepareForTestWithPlatformBootclasspath, 184 android.FixtureWithRootAndroidBp(` 185 platform_bootclasspath { 186 name: "platform-bootclasspath", 187 } 188 `), 189 ).RunTest(t) 190 191 variants := result.ModuleVariantsForTests("platform-bootclasspath") 192 android.AssertIntEquals(t, "expect 1 variant", 1, len(variants)) 193} 194 195func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) { 196 result := android.GroupFixturePreparers( 197 prepareForTestWithPlatformBootclasspath, 198 android.FixtureWithRootAndroidBp(` 199 platform_bootclasspath { 200 name: "platform-bootclasspath", 201 } 202 `), 203 ).RunTest(t) 204 205 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 206 android.AssertStringEquals(t, "output filepath", "bootclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base()) 207 android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) 208} 209 210func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { 211 preparer := android.GroupFixturePreparers( 212 prepareForTestWithPlatformBootclasspath, 213 android.FixtureWithRootAndroidBp(` 214 platform_bootclasspath { 215 name: "platform-bootclasspath", 216 } 217 `), 218 ) 219 220 t.Run("AndroidMkEntries", func(t *testing.T) { 221 result := preparer.RunTest(t) 222 223 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 224 225 entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) 226 android.AssertIntEquals(t, "AndroidMkEntries count", 2, len(entries)) 227 }) 228 229 t.Run("hiddenapi-flags-entry", func(t *testing.T) { 230 result := preparer.RunTest(t) 231 232 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 233 234 entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) 235 got := entries[0].OutputFile 236 android.AssertBoolEquals(t, "valid output path", true, got.Valid()) 237 android.AssertSame(t, "output filepath", p.hiddenAPIFlagsCSV, got.Path()) 238 }) 239 240 t.Run("classpath-fragment-entry", func(t *testing.T) { 241 result := preparer.RunTest(t) 242 243 want := map[string][]string{ 244 "LOCAL_MODULE": {"platform-bootclasspath"}, 245 "LOCAL_MODULE_CLASS": {"ETC"}, 246 "LOCAL_INSTALLED_MODULE_STEM": {"bootclasspath.pb"}, 247 // Output and Install paths are tested separately in TestPlatformBootclasspath_ClasspathFragmentPaths 248 } 249 250 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 251 252 entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) 253 got := entries[1] 254 for k, expectedValue := range want { 255 if value, ok := got.EntryMap[k]; ok { 256 android.AssertDeepEquals(t, k, expectedValue, value) 257 } else { 258 t.Errorf("No %s defined, saw %q", k, got.EntryMap) 259 } 260 } 261 }) 262} 263 264func TestPlatformBootclasspath_Dist(t *testing.T) { 265 result := android.GroupFixturePreparers( 266 prepareForTestWithPlatformBootclasspath, 267 FixtureConfigureBootJars("platform:foo", "platform:bar"), 268 android.PrepareForTestWithAndroidMk, 269 android.FixtureWithRootAndroidBp(` 270 platform_bootclasspath { 271 name: "platform-bootclasspath", 272 dists: [ 273 { 274 targets: ["droidcore"], 275 tag: "hiddenapi-flags.csv", 276 }, 277 ], 278 } 279 280 java_library { 281 name: "bar", 282 srcs: ["a.java"], 283 system_modules: "none", 284 sdk_version: "none", 285 compile_dex: true, 286 } 287 288 java_library { 289 name: "foo", 290 srcs: ["a.java"], 291 system_modules: "none", 292 sdk_version: "none", 293 compile_dex: true, 294 } 295 `), 296 ).RunTest(t) 297 298 platformBootclasspath := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 299 entries := android.AndroidMkEntriesForTest(t, result.TestContext, platformBootclasspath) 300 goals := entries[0].GetDistForGoals(platformBootclasspath) 301 android.AssertStringEquals(t, "platform dist goals phony", ".PHONY: droidcore", goals[0]) 302 android.AssertStringDoesContain(t, "platform dist goals meta check", goals[1], "$(if $(strip $(ALL_TARGETS.") 303 android.AssertStringDoesContain(t, "platform dist goals meta assign", goals[1], "),,$(eval ALL_TARGETS.") 304 android.AssertStringEquals(t, "platform dist goals call", "$(call dist-for-goals,droidcore,out/soong/hiddenapi/hiddenapi-flags.csv:hiddenapi-flags.csv)", android.StringRelativeToTop(result.Config, goals[2])) 305} 306 307func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { 308 result := android.GroupFixturePreparers( 309 hiddenApiFixtureFactory, 310 PrepareForTestWithJavaSdkLibraryFiles, 311 FixtureWithLastReleaseApis("bar"), 312 FixtureConfigureBootJars("platform:foo", "platform:bar"), 313 ).RunTestWithBp(t, ` 314 java_library { 315 name: "foo", 316 srcs: ["a.java"], 317 compile_dex: true, 318 319 hiddenapi_additional_annotations: [ 320 "foo-hiddenapi-annotations", 321 ], 322 } 323 324 java_library { 325 name: "foo-hiddenapi-annotations", 326 srcs: ["a.java"], 327 compile_dex: true, 328 } 329 330 java_import { 331 name: "foo", 332 jars: ["a.jar"], 333 compile_dex: true, 334 prefer: false, 335 } 336 337 java_sdk_library { 338 name: "bar", 339 srcs: ["a.java"], 340 compile_dex: true, 341 } 342 343 platform_bootclasspath { 344 name: "myplatform-bootclasspath", 345 } 346 `) 347 348 // Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that 349 // creates the index.csv file. 350 platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common") 351 352 var rule android.TestingBuildParams 353 354 // All the intermediate rules use the same inputs. 355 expectedIntermediateInputs := ` 356 out/soong/.intermediates/bar.impl/android_common/javac/bar.jar 357 out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar 358 out/soong/.intermediates/foo/android_common/javac/foo.jar 359 ` 360 361 // Check flags output. 362 rule = platformBootclasspath.Output("hiddenapi-monolithic/annotation-flags-from-classes.csv") 363 CheckHiddenAPIRuleInputs(t, "intermediate flags", expectedIntermediateInputs, rule) 364 365 rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-flags.csv") 366 CheckHiddenAPIRuleInputs(t, "monolithic flags", ` 367 out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv 368 out/soong/hiddenapi/hiddenapi-stub-flags.txt 369 `, rule) 370 371 // Check metadata output. 372 rule = platformBootclasspath.Output("hiddenapi-monolithic/metadata-from-classes.csv") 373 CheckHiddenAPIRuleInputs(t, "intermediate metadata", expectedIntermediateInputs, rule) 374 375 rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv") 376 CheckHiddenAPIRuleInputs(t, "monolithic metadata", ` 377 out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv 378 `, rule) 379 380 // Check index output. 381 rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv") 382 CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule) 383 384 rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-index.csv") 385 CheckHiddenAPIRuleInputs(t, "monolithic index", ` 386 out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv 387 `, rule) 388} 389