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