1// Copyright 2018 Google Inc. All rights reserved. 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 "fmt" 19 "runtime" 20 "strings" 21 "testing" 22 23 "android/soong/android" 24 "android/soong/cc" 25 "android/soong/dexpreopt" 26) 27 28func init() { 29 RegisterFakeRuntimeApexMutator() 30} 31 32func TestDexpreoptEnabled(t *testing.T) { 33 tests := []struct { 34 name string 35 bp string 36 moduleName string 37 apexVariant bool 38 enabled bool 39 }{ 40 { 41 name: "app", 42 bp: ` 43 android_app { 44 name: "foo", 45 srcs: ["a.java"], 46 sdk_version: "current", 47 }`, 48 enabled: true, 49 }, 50 { 51 name: "installable java library", 52 bp: ` 53 java_library { 54 name: "foo", 55 installable: true, 56 srcs: ["a.java"], 57 }`, 58 enabled: true, 59 }, 60 { 61 name: "java binary", 62 bp: ` 63 java_binary { 64 name: "foo", 65 srcs: ["a.java"], 66 }`, 67 enabled: true, 68 }, 69 { 70 name: "app without sources", 71 bp: ` 72 android_app { 73 name: "foo", 74 sdk_version: "current", 75 }`, 76 enabled: false, 77 }, 78 { 79 name: "app with libraries", 80 bp: ` 81 android_app { 82 name: "foo", 83 static_libs: ["lib"], 84 sdk_version: "current", 85 } 86 87 java_library { 88 name: "lib", 89 srcs: ["a.java"], 90 sdk_version: "current", 91 }`, 92 enabled: true, 93 }, 94 { 95 name: "installable java library without sources", 96 bp: ` 97 java_library { 98 name: "foo", 99 installable: true, 100 }`, 101 enabled: false, 102 }, 103 { 104 name: "static java library", 105 bp: ` 106 java_library { 107 name: "foo", 108 srcs: ["a.java"], 109 }`, 110 enabled: false, 111 }, 112 { 113 name: "java test", 114 bp: ` 115 java_test { 116 name: "foo", 117 srcs: ["a.java"], 118 }`, 119 enabled: false, 120 }, 121 { 122 name: "android test", 123 bp: ` 124 android_test { 125 name: "foo", 126 srcs: ["a.java"], 127 }`, 128 enabled: false, 129 }, 130 { 131 name: "android test helper app", 132 bp: ` 133 android_test_helper_app { 134 name: "foo", 135 srcs: ["a.java"], 136 }`, 137 enabled: false, 138 }, 139 { 140 name: "compile_dex", 141 bp: ` 142 java_library { 143 name: "foo", 144 srcs: ["a.java"], 145 compile_dex: true, 146 }`, 147 enabled: false, 148 }, 149 { 150 name: "dex_import", 151 bp: ` 152 dex_import { 153 name: "foo", 154 jars: ["a.jar"], 155 }`, 156 enabled: true, 157 }, 158 { 159 name: "apex variant", 160 bp: ` 161 java_library { 162 name: "foo", 163 installable: true, 164 srcs: ["a.java"], 165 apex_available: ["com.android.apex1"], 166 }`, 167 apexVariant: true, 168 enabled: false, 169 }, 170 { 171 name: "apex variant of apex system server jar", 172 bp: ` 173 java_library { 174 name: "service-foo", 175 installable: true, 176 srcs: ["a.java"], 177 apex_available: ["com.android.apex1"], 178 }`, 179 moduleName: "service-foo", 180 apexVariant: true, 181 enabled: true, 182 }, 183 { 184 name: "apex variant of prebuilt apex system server jar", 185 bp: ` 186 java_library { 187 name: "prebuilt_service-foo", 188 installable: true, 189 srcs: ["a.java"], 190 apex_available: ["com.android.apex1"], 191 }`, 192 moduleName: "prebuilt_service-foo", 193 apexVariant: true, 194 enabled: true, 195 }, 196 { 197 name: "platform variant of apex system server jar", 198 bp: ` 199 java_library { 200 name: "service-foo", 201 installable: true, 202 srcs: ["a.java"], 203 apex_available: ["com.android.apex1"], 204 }`, 205 moduleName: "service-foo", 206 apexVariant: false, 207 enabled: false, 208 }, 209 } 210 211 for _, test := range tests { 212 t.Run(test.name, func(t *testing.T) { 213 preparers := android.GroupFixturePreparers( 214 PrepareForTestWithJavaDefaultModules, 215 PrepareForTestWithFakeApexMutator, 216 dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"), 217 ) 218 219 result := preparers.RunTestWithBp(t, test.bp) 220 ctx := result.TestContext 221 222 moduleName := "foo" 223 if test.moduleName != "" { 224 moduleName = test.moduleName 225 } 226 227 variant := "android_common" 228 if test.apexVariant { 229 variant += "_apex1000" 230 } 231 232 dexpreopt := ctx.ModuleForTests(moduleName, variant).MaybeRule("dexpreopt") 233 enabled := dexpreopt.Rule != nil 234 235 if enabled != test.enabled { 236 t.Fatalf("want dexpreopt %s, got %s", enabledString(test.enabled), enabledString(enabled)) 237 } 238 }) 239 240 } 241} 242 243func enabledString(enabled bool) string { 244 if enabled { 245 return "enabled" 246 } else { 247 return "disabled" 248 } 249} 250 251func TestDex2oatToolDeps(t *testing.T) { 252 if runtime.GOOS != "linux" { 253 // The host binary paths checked below are build OS dependent. 254 t.Skipf("Unsupported build OS %s", runtime.GOOS) 255 } 256 257 preparers := android.GroupFixturePreparers( 258 cc.PrepareForTestWithCcDefaultModules, 259 PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd, 260 dexpreopt.PrepareForTestByEnablingDexpreopt) 261 262 testDex2oatToolDep := func(sourceEnabled, prebuiltEnabled, prebuiltPreferred bool, 263 expectedDex2oatPath string) { 264 name := fmt.Sprintf("sourceEnabled:%t,prebuiltEnabled:%t,prebuiltPreferred:%t", 265 sourceEnabled, prebuiltEnabled, prebuiltPreferred) 266 t.Run(name, func(t *testing.T) { 267 result := preparers.RunTestWithBp(t, fmt.Sprintf(` 268 cc_binary { 269 name: "dex2oatd", 270 enabled: %t, 271 host_supported: true, 272 } 273 cc_prebuilt_binary { 274 name: "dex2oatd", 275 enabled: %t, 276 prefer: %t, 277 host_supported: true, 278 srcs: ["x86_64/bin/dex2oatd"], 279 } 280 java_library { 281 name: "myjavalib", 282 } 283 `, sourceEnabled, prebuiltEnabled, prebuiltPreferred)) 284 pathContext := android.PathContextForTesting(result.Config) 285 dex2oatPath := dexpreopt.GetCachedGlobalSoongConfig(pathContext).Dex2oat 286 android.AssertStringEquals(t, "Testing "+name, expectedDex2oatPath, android.NormalizePathForTesting(dex2oatPath)) 287 }) 288 } 289 290 sourceDex2oatPath := "host/linux-x86/bin/dex2oatd" 291 prebuiltDex2oatPath := ".intermediates/prebuilt_dex2oatd/linux_glibc_x86_64/dex2oatd" 292 293 testDex2oatToolDep(true, false, false, sourceDex2oatPath) 294 testDex2oatToolDep(true, true, false, sourceDex2oatPath) 295 testDex2oatToolDep(true, true, true, prebuiltDex2oatPath) 296 testDex2oatToolDep(false, true, false, prebuiltDex2oatPath) 297} 298 299func TestDexpreoptBuiltInstalledForApex(t *testing.T) { 300 preparers := android.GroupFixturePreparers( 301 PrepareForTestWithJavaDefaultModules, 302 PrepareForTestWithFakeApexMutator, 303 dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"), 304 ) 305 306 // An APEX system server jar. 307 result := preparers.RunTestWithBp(t, ` 308 java_library { 309 name: "service-foo", 310 installable: true, 311 srcs: ["a.java"], 312 apex_available: ["com.android.apex1"], 313 }`) 314 ctx := result.TestContext 315 module := ctx.ModuleForTests("service-foo", "android_common_apex1000") 316 library := module.Module().(*Library) 317 318 installs := library.dexpreopter.DexpreoptBuiltInstalledForApex() 319 320 android.AssertIntEquals(t, "install count", 2, len(installs)) 321 322 android.AssertStringEquals(t, "installs[0] FullModuleName", 323 "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", 324 installs[0].FullModuleName()) 325 326 android.AssertStringEquals(t, "installs[0] SubModuleName", 327 "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", 328 installs[0].SubModuleName()) 329 330 android.AssertStringEquals(t, "installs[1] FullModuleName", 331 "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", 332 installs[1].FullModuleName()) 333 334 android.AssertStringEquals(t, "installs[1] SubModuleName", 335 "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", 336 installs[1].SubModuleName()) 337 338 // Not an APEX system server jar. 339 result = preparers.RunTestWithBp(t, ` 340 java_library { 341 name: "foo", 342 installable: true, 343 srcs: ["a.java"], 344 }`) 345 ctx = result.TestContext 346 module = ctx.ModuleForTests("foo", "android_common") 347 library = module.Module().(*Library) 348 349 installs = library.dexpreopter.DexpreoptBuiltInstalledForApex() 350 351 android.AssertIntEquals(t, "install count", 0, len(installs)) 352} 353 354func filterDexpreoptEntriesList(entriesList []android.AndroidMkEntries) []android.AndroidMkEntries { 355 var results []android.AndroidMkEntries 356 for _, entries := range entriesList { 357 if strings.Contains(entries.EntryMap["LOCAL_MODULE"][0], "-dexpreopt-") { 358 results = append(results, entries) 359 } 360 } 361 return results 362} 363 364func verifyEntries(t *testing.T, message string, expectedModule string, 365 expectedPrebuiltModuleFile string, expectedModulePath string, expectedInstalledModuleStem string, 366 entries android.AndroidMkEntries) { 367 android.AssertStringEquals(t, message+" LOCAL_MODULE", expectedModule, 368 entries.EntryMap["LOCAL_MODULE"][0]) 369 370 android.AssertStringEquals(t, message+" LOCAL_MODULE_CLASS", "ETC", 371 entries.EntryMap["LOCAL_MODULE_CLASS"][0]) 372 373 android.AssertStringDoesContain(t, message+" LOCAL_PREBUILT_MODULE_FILE", 374 entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"][0], expectedPrebuiltModuleFile) 375 376 android.AssertStringDoesContain(t, message+" LOCAL_MODULE_PATH", 377 entries.EntryMap["LOCAL_MODULE_PATH"][0], expectedModulePath) 378 379 android.AssertStringEquals(t, message+" LOCAL_INSTALLED_MODULE_STEM", 380 expectedInstalledModuleStem, entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0]) 381 382 android.AssertStringEquals(t, message+" LOCAL_NOT_AVAILABLE_FOR_PLATFORM", 383 "false", entries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"][0]) 384} 385 386func TestAndroidMkEntriesForApex(t *testing.T) { 387 preparers := android.GroupFixturePreparers( 388 PrepareForTestWithJavaDefaultModules, 389 PrepareForTestWithFakeApexMutator, 390 dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"), 391 ) 392 393 // An APEX system server jar. 394 result := preparers.RunTestWithBp(t, ` 395 java_library { 396 name: "service-foo", 397 installable: true, 398 srcs: ["a.java"], 399 apex_available: ["com.android.apex1"], 400 }`) 401 ctx := result.TestContext 402 module := ctx.ModuleForTests("service-foo", "android_common_apex1000") 403 404 entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module()) 405 entriesList = filterDexpreoptEntriesList(entriesList) 406 407 android.AssertIntEquals(t, "entries count", 2, len(entriesList)) 408 409 verifyEntries(t, 410 "entriesList[0]", 411 "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", 412 "/dexpreopt/oat/arm64/javalib.odex", 413 "/system/framework/oat/arm64", 414 "apex@com.android.apex1@javalib@service-foo.jar@classes.odex", 415 entriesList[0]) 416 417 verifyEntries(t, 418 "entriesList[1]", 419 "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", 420 "/dexpreopt/oat/arm64/javalib.vdex", 421 "/system/framework/oat/arm64", 422 "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", 423 entriesList[1]) 424 425 // Not an APEX system server jar. 426 result = preparers.RunTestWithBp(t, ` 427 java_library { 428 name: "foo", 429 installable: true, 430 srcs: ["a.java"], 431 }`) 432 ctx = result.TestContext 433 module = ctx.ModuleForTests("foo", "android_common") 434 435 entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module()) 436 entriesList = filterDexpreoptEntriesList(entriesList) 437 438 android.AssertIntEquals(t, "entries count", 0, len(entriesList)) 439} 440