1// Copyright 2017 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 "io/ioutil" 19 "os" 20 "path/filepath" 21 "strconv" 22 "strings" 23 "testing" 24 25 "android/soong/android" 26 "android/soong/cc" 27 "android/soong/dexpreopt" 28 "android/soong/genrule" 29) 30 31var buildDir string 32 33func setUp() { 34 var err error 35 buildDir, err = ioutil.TempDir("", "soong_java_test") 36 if err != nil { 37 panic(err) 38 } 39} 40 41func tearDown() { 42 os.RemoveAll(buildDir) 43} 44 45func TestMain(m *testing.M) { 46 run := func() int { 47 setUp() 48 defer tearDown() 49 50 return m.Run() 51 } 52 53 os.Exit(run()) 54} 55 56func testConfig(env map[string]string) android.Config { 57 return TestConfig(buildDir, env) 58} 59 60func testContext(config android.Config, bp string, 61 fs map[string][]byte) *android.TestContext { 62 63 ctx := android.NewTestArchContext() 64 ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory)) 65 ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(AndroidAppCertificateFactory)) 66 ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory)) 67 ctx.RegisterModuleType("android_test", android.ModuleFactoryAdaptor(AndroidTestFactory)) 68 ctx.RegisterModuleType("android_test_helper_app", android.ModuleFactoryAdaptor(AndroidTestHelperAppFactory)) 69 ctx.RegisterModuleType("java_binary", android.ModuleFactoryAdaptor(BinaryFactory)) 70 ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory)) 71 ctx.RegisterModuleType("java_device_for_host", android.ModuleFactoryAdaptor(DeviceForHostFactory)) 72 ctx.RegisterModuleType("java_host_for_device", android.ModuleFactoryAdaptor(HostForDeviceFactory)) 73 ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory)) 74 ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory)) 75 ctx.RegisterModuleType("java_test", android.ModuleFactoryAdaptor(TestFactory)) 76 ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory)) 77 ctx.RegisterModuleType("java_import_host", android.ModuleFactoryAdaptor(ImportFactoryHost)) 78 ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory)) 79 ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory)) 80 ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory)) 81 ctx.RegisterModuleType("java_plugin", android.ModuleFactoryAdaptor(PluginFactory)) 82 ctx.RegisterModuleType("dex_import", android.ModuleFactoryAdaptor(DexImportFactory)) 83 ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory)) 84 ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory)) 85 ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory)) 86 ctx.RegisterModuleType("droiddoc_host", android.ModuleFactoryAdaptor(DroiddocHostFactory)) 87 ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(ExportedDroiddocDirFactory)) 88 ctx.RegisterModuleType("java_sdk_library", android.ModuleFactoryAdaptor(SdkLibraryFactory)) 89 ctx.RegisterModuleType("override_android_app", android.ModuleFactoryAdaptor(OverrideAndroidAppModuleFactory)) 90 ctx.RegisterModuleType("prebuilt_apis", android.ModuleFactoryAdaptor(PrebuiltApisFactory)) 91 ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators) 92 ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators) 93 ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) 94 ctx.PreArchMutators(android.RegisterOverridePreArchMutators) 95 ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) { 96 ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel() 97 ctx.TopDown("java_sdk_library", SdkLibraryMutator).Parallel() 98 }) 99 ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory)) 100 ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory)) 101 102 // Register module types and mutators from cc needed for JNI testing 103 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory)) 104 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory)) 105 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory)) 106 ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory)) 107 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { 108 ctx.BottomUp("link", cc.LinkageMutator).Parallel() 109 ctx.BottomUp("begin", cc.BeginMutator).Parallel() 110 }) 111 112 bp += GatherRequiredDepsForTest() 113 114 mockFS := map[string][]byte{ 115 "Android.bp": []byte(bp), 116 "a.java": nil, 117 "b.java": nil, 118 "c.java": nil, 119 "b.kt": nil, 120 "a.jar": nil, 121 "b.jar": nil, 122 "APP_NOTICE": nil, 123 "GENRULE_NOTICE": nil, 124 "LIB_NOTICE": nil, 125 "TOOL_NOTICE": nil, 126 "java-res/a/a": nil, 127 "java-res/b/b": nil, 128 "java-res2/a": nil, 129 "java-fg/a.java": nil, 130 "java-fg/b.java": nil, 131 "java-fg/c.java": nil, 132 "api/current.txt": nil, 133 "api/removed.txt": nil, 134 "api/system-current.txt": nil, 135 "api/system-removed.txt": nil, 136 "api/test-current.txt": nil, 137 "api/test-removed.txt": nil, 138 "framework/aidl/a.aidl": nil, 139 140 "prebuilts/sdk/14/public/android.jar": nil, 141 "prebuilts/sdk/14/public/framework.aidl": nil, 142 "prebuilts/sdk/14/system/android.jar": nil, 143 "prebuilts/sdk/17/public/android.jar": nil, 144 "prebuilts/sdk/17/public/framework.aidl": nil, 145 "prebuilts/sdk/17/system/android.jar": nil, 146 "prebuilts/sdk/25/public/android.jar": nil, 147 "prebuilts/sdk/25/public/framework.aidl": nil, 148 "prebuilts/sdk/25/system/android.jar": nil, 149 "prebuilts/sdk/current/core/android.jar": nil, 150 "prebuilts/sdk/current/public/android.jar": nil, 151 "prebuilts/sdk/current/public/framework.aidl": nil, 152 "prebuilts/sdk/current/public/core.jar": nil, 153 "prebuilts/sdk/current/system/android.jar": nil, 154 "prebuilts/sdk/current/test/android.jar": nil, 155 "prebuilts/sdk/28/public/api/foo.txt": nil, 156 "prebuilts/sdk/28/system/api/foo.txt": nil, 157 "prebuilts/sdk/28/test/api/foo.txt": nil, 158 "prebuilts/sdk/28/public/api/foo-removed.txt": nil, 159 "prebuilts/sdk/28/system/api/foo-removed.txt": nil, 160 "prebuilts/sdk/28/test/api/foo-removed.txt": nil, 161 "prebuilts/sdk/28/public/api/bar.txt": nil, 162 "prebuilts/sdk/28/system/api/bar.txt": nil, 163 "prebuilts/sdk/28/test/api/bar.txt": nil, 164 "prebuilts/sdk/28/public/api/bar-removed.txt": nil, 165 "prebuilts/sdk/28/system/api/bar-removed.txt": nil, 166 "prebuilts/sdk/28/test/api/bar-removed.txt": nil, 167 "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, 168 "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), 169 170 // For framework-res, which is an implicit dependency for framework 171 "AndroidManifest.xml": nil, 172 "build/target/product/security/testkey": nil, 173 174 "build/soong/scripts/jar-wrapper.sh": nil, 175 176 "build/make/core/proguard.flags": nil, 177 "build/make/core/proguard_basic_keeps.flags": nil, 178 179 "jdk8/jre/lib/jce.jar": nil, 180 "jdk8/jre/lib/rt.jar": nil, 181 "jdk8/lib/tools.jar": nil, 182 183 "bar-doc/a.java": nil, 184 "bar-doc/b.java": nil, 185 "bar-doc/IFoo.aidl": nil, 186 "bar-doc/known_oj_tags.txt": nil, 187 "external/doclava/templates-sdk": nil, 188 189 "cert/new_cert.x509.pem": nil, 190 "cert/new_cert.pk8": nil, 191 } 192 193 for k, v := range fs { 194 mockFS[k] = v 195 } 196 197 ctx.MockFileSystem(mockFS) 198 199 return ctx 200} 201 202func run(t *testing.T, ctx *android.TestContext, config android.Config) { 203 t.Helper() 204 205 pathCtx := android.PathContextForTesting(config, nil) 206 setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx)) 207 208 ctx.Register() 209 _, errs := ctx.ParseFileList(".", []string{"Android.bp", "prebuilts/sdk/Android.bp"}) 210 android.FailIfErrored(t, errs) 211 _, errs = ctx.PrepareBuildActions(config) 212 android.FailIfErrored(t, errs) 213} 214 215func testJava(t *testing.T, bp string) *android.TestContext { 216 t.Helper() 217 config := testConfig(nil) 218 ctx := testContext(config, bp, nil) 219 run(t, ctx, config) 220 221 return ctx 222} 223 224func moduleToPath(name string) string { 225 switch { 226 case name == `""`: 227 return name 228 case strings.HasSuffix(name, ".jar"): 229 return name 230 default: 231 return filepath.Join(buildDir, ".intermediates", name, "android_common", "turbine-combined", name+".jar") 232 } 233} 234 235func TestSimple(t *testing.T) { 236 ctx := testJava(t, ` 237 java_library { 238 name: "foo", 239 srcs: ["a.java"], 240 libs: ["bar"], 241 static_libs: ["baz"], 242 } 243 244 java_library { 245 name: "bar", 246 srcs: ["b.java"], 247 } 248 249 java_library { 250 name: "baz", 251 srcs: ["c.java"], 252 } 253 `) 254 255 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 256 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 257 258 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 259 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 260 } 261 262 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 263 barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 264 bazTurbine := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "turbine-combined", "baz.jar") 265 266 if !strings.Contains(javac.Args["classpath"], barTurbine) { 267 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 268 } 269 270 if !strings.Contains(javac.Args["classpath"], bazTurbine) { 271 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bazTurbine) 272 } 273 274 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 275 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 276 } 277} 278 279func TestArchSpecific(t *testing.T) { 280 ctx := testJava(t, ` 281 java_library { 282 name: "foo", 283 srcs: ["a.java"], 284 target: { 285 android: { 286 srcs: ["b.java"], 287 }, 288 }, 289 } 290 `) 291 292 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 293 if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" { 294 t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs) 295 } 296} 297 298func TestBinary(t *testing.T) { 299 ctx := testJava(t, ` 300 java_library_host { 301 name: "foo", 302 srcs: ["a.java"], 303 } 304 305 java_binary_host { 306 name: "bar", 307 srcs: ["b.java"], 308 static_libs: ["foo"], 309 } 310 `) 311 312 buildOS := android.BuildOs.String() 313 314 bar := ctx.ModuleForTests("bar", buildOS+"_common") 315 barJar := bar.Output("bar.jar").Output.String() 316 barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64") 317 barWrapperDeps := barWrapper.Output("bar").Implicits.Strings() 318 319 // Test that the install binary wrapper depends on the installed jar file 320 if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar { 321 t.Errorf("expected binary wrapper implicits [%q], got %v", 322 barJar, barWrapperDeps) 323 } 324 325} 326 327func TestPrebuilts(t *testing.T) { 328 ctx := testJava(t, ` 329 java_library { 330 name: "foo", 331 srcs: ["a.java"], 332 libs: ["bar"], 333 static_libs: ["baz"], 334 } 335 336 java_import { 337 name: "bar", 338 jars: ["a.jar"], 339 } 340 341 java_import { 342 name: "baz", 343 jars: ["b.jar"], 344 } 345 346 dex_import { 347 name: "qux", 348 jars: ["b.jar"], 349 } 350 `) 351 352 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 353 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 354 barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output 355 bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output 356 357 if !strings.Contains(javac.Args["classpath"], barJar.String()) { 358 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) 359 } 360 361 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() { 362 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) 363 } 364 365 ctx.ModuleForTests("qux", "android_common").Rule("Cp") 366} 367 368func TestDefaults(t *testing.T) { 369 ctx := testJava(t, ` 370 java_defaults { 371 name: "defaults", 372 srcs: ["a.java"], 373 libs: ["bar"], 374 static_libs: ["baz"], 375 optimize: {enabled: false}, 376 } 377 378 java_library { 379 name: "foo", 380 defaults: ["defaults"], 381 } 382 383 java_library { 384 name: "bar", 385 srcs: ["b.java"], 386 } 387 388 java_library { 389 name: "baz", 390 srcs: ["c.java"], 391 } 392 393 android_test { 394 name: "atestOptimize", 395 defaults: ["defaults"], 396 optimize: {enabled: true}, 397 } 398 399 android_test { 400 name: "atestNoOptimize", 401 defaults: ["defaults"], 402 } 403 404 android_test { 405 name: "atestDefault", 406 srcs: ["a.java"], 407 } 408 `) 409 410 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 411 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 412 413 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 414 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 415 } 416 417 barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 418 if !strings.Contains(javac.Args["classpath"], barTurbine) { 419 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 420 } 421 422 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 423 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 424 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 425 } 426 427 atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8") 428 if atestOptimize.Output == nil { 429 t.Errorf("atestOptimize should optimize APK") 430 } 431 432 atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8") 433 if atestNoOptimize.Output == nil { 434 t.Errorf("atestNoOptimize should not optimize APK") 435 } 436 437 atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("r8") 438 if atestDefault.Output == nil { 439 t.Errorf("atestDefault should optimize APK") 440 } 441} 442 443func TestResources(t *testing.T) { 444 var table = []struct { 445 name string 446 prop string 447 extra string 448 args string 449 }{ 450 { 451 // Test that a module with java_resource_dirs includes the files 452 name: "resource dirs", 453 prop: `java_resource_dirs: ["java-res"]`, 454 args: "-C java-res -f java-res/a/a -f java-res/b/b", 455 }, 456 { 457 // Test that a module with java_resources includes the files 458 name: "resource files", 459 prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`, 460 args: "-C . -f java-res/a/a -f java-res/b/b", 461 }, 462 { 463 // Test that a module with a filegroup in java_resources includes the files with the 464 // path prefix 465 name: "resource filegroup", 466 prop: `java_resources: [":foo-res"]`, 467 extra: ` 468 filegroup { 469 name: "foo-res", 470 path: "java-res", 471 srcs: ["java-res/a/a", "java-res/b/b"], 472 }`, 473 args: "-C java-res -f java-res/a/a -f java-res/b/b", 474 }, 475 { 476 // Test that a module with "include_srcs: true" includes its source files in the resources jar 477 name: "include sources", 478 prop: `include_srcs: true`, 479 args: "-C . -f a.java -f b.java -f c.java", 480 }, 481 { 482 // Test that a module with wildcards in java_resource_dirs has the correct path prefixes 483 name: "wildcard dirs", 484 prop: `java_resource_dirs: ["java-res/*"]`, 485 args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b", 486 }, 487 { 488 // Test that a module exclude_java_resource_dirs excludes the files 489 name: "wildcard dirs", 490 prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`, 491 args: "-C java-res/a -f java-res/a/a", 492 }, 493 { 494 // Test wildcards in java_resources 495 name: "wildcard files", 496 prop: `java_resources: ["java-res/**/*"]`, 497 args: "-C . -f java-res/a/a -f java-res/b/b", 498 }, 499 { 500 // Test exclude_java_resources with java_resources 501 name: "wildcard files with exclude", 502 prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`, 503 args: "-C . -f java-res/a/a", 504 }, 505 { 506 // Test exclude_java_resources with java_resource_dirs 507 name: "resource dirs with exclude files", 508 prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`, 509 args: "-C java-res -f java-res/a/a", 510 }, 511 { 512 // Test exclude_java_resource_dirs with java_resource_dirs 513 name: "resource dirs with exclude files", 514 prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`, 515 args: "-C java-res -f java-res/a/a -f java-res/b/b", 516 }, 517 } 518 519 for _, test := range table { 520 t.Run(test.name, func(t *testing.T) { 521 ctx := testJava(t, ` 522 java_library { 523 name: "foo", 524 srcs: [ 525 "a.java", 526 "b.java", 527 "c.java", 528 ], 529 `+test.prop+`, 530 } 531 `+test.extra) 532 533 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 534 fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar") 535 536 if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { 537 t.Errorf("foo combined jars %v does not contain %q", 538 foo.Inputs.Strings(), fooRes.Output.String()) 539 } 540 541 if fooRes.Args["jarArgs"] != test.args { 542 t.Errorf("foo resource jar args %q is not %q", 543 fooRes.Args["jarArgs"], test.args) 544 } 545 }) 546 } 547} 548 549func TestGeneratedSources(t *testing.T) { 550 ctx := testJava(t, ` 551 java_library { 552 name: "foo", 553 srcs: [ 554 "a*.java", 555 ":gen", 556 "b*.java", 557 ], 558 } 559 560 genrule { 561 name: "gen", 562 tool_files: ["java-res/a"], 563 out: ["gen.java"], 564 } 565 `) 566 567 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 568 genrule := ctx.ModuleForTests("gen", "").Rule("generator") 569 570 if filepath.Base(genrule.Output.String()) != "gen.java" { 571 t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String()) 572 } 573 574 if len(javac.Inputs) != 3 || 575 javac.Inputs[0].String() != "a.java" || 576 javac.Inputs[1].String() != genrule.Output.String() || 577 javac.Inputs[2].String() != "b.java" { 578 t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs) 579 } 580} 581 582func TestTurbine(t *testing.T) { 583 ctx := testJava(t, ` 584 java_library { 585 name: "foo", 586 srcs: ["a.java"], 587 sdk_version: "14", 588 } 589 590 java_library { 591 name: "bar", 592 srcs: ["b.java"], 593 static_libs: ["foo"], 594 sdk_version: "14", 595 } 596 597 java_library { 598 name: "baz", 599 srcs: ["c.java"], 600 libs: ["bar"], 601 sdk_version: "14", 602 } 603 `) 604 605 fooTurbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine") 606 barTurbine := ctx.ModuleForTests("bar", "android_common").Rule("turbine") 607 barJavac := ctx.ModuleForTests("bar", "android_common").Rule("javac") 608 barTurbineCombined := ctx.ModuleForTests("bar", "android_common").Description("for turbine") 609 bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac") 610 611 if len(fooTurbine.Inputs) != 1 || fooTurbine.Inputs[0].String() != "a.java" { 612 t.Errorf(`foo inputs %v != ["a.java"]`, fooTurbine.Inputs) 613 } 614 615 fooHeaderJar := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar") 616 if !strings.Contains(barTurbine.Args["classpath"], fooHeaderJar) { 617 t.Errorf("bar turbine classpath %v does not contain %q", barTurbine.Args["classpath"], fooHeaderJar) 618 } 619 if !strings.Contains(barJavac.Args["classpath"], fooHeaderJar) { 620 t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], fooHeaderJar) 621 } 622 if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar { 623 t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar) 624 } 625 if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") { 626 t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], 627 "prebuilts/sdk/14/public/android.jar") 628 } 629} 630 631func TestSharding(t *testing.T) { 632 ctx := testJava(t, ` 633 java_library { 634 name: "bar", 635 srcs: ["a.java","b.java","c.java"], 636 javac_shard_size: 1 637 } 638 `) 639 640 barHeaderJar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 641 for i := 0; i < 3; i++ { 642 barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)) 643 if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) { 644 t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar) 645 } 646 } 647} 648 649func TestDroiddoc(t *testing.T) { 650 ctx := testJava(t, ` 651 droiddoc_template { 652 name: "droiddoc-templates-sdk", 653 path: ".", 654 } 655 droiddoc { 656 name: "bar-doc", 657 srcs: [ 658 "bar-doc/*.java", 659 "bar-doc/IFoo.aidl", 660 ], 661 exclude_srcs: [ 662 "bar-doc/b.java" 663 ], 664 custom_template: "droiddoc-templates-sdk", 665 hdf: [ 666 "android.whichdoc offline", 667 ], 668 knowntags: [ 669 "bar-doc/known_oj_tags.txt", 670 ], 671 proofread_file: "libcore-proofread.txt", 672 todo_file: "libcore-docs-todo.html", 673 args: "-offlinemode -title \"libcore\"", 674 } 675 `) 676 677 stubsJar := filepath.Join(buildDir, ".intermediates", "bar-doc", "android_common", "bar-doc-stubs.srcjar") 678 barDoc := ctx.ModuleForTests("bar-doc", "android_common").Output("bar-doc-stubs.srcjar") 679 if stubsJar != barDoc.Output.String() { 680 t.Errorf("expected stubs Jar [%q], got %q", stubsJar, barDoc.Output.String()) 681 } 682 inputs := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc").Inputs 683 var javaSrcs []string 684 for _, i := range inputs { 685 javaSrcs = append(javaSrcs, i.Base()) 686 } 687 if len(javaSrcs) != 2 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" { 688 t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", but was %#v.", javaSrcs) 689 } 690} 691 692func TestJarGenrules(t *testing.T) { 693 ctx := testJava(t, ` 694 java_library { 695 name: "foo", 696 srcs: ["a.java"], 697 } 698 699 java_genrule { 700 name: "jargen", 701 tool_files: ["b.java"], 702 cmd: "$(location b.java) $(in) $(out)", 703 out: ["jargen.jar"], 704 srcs: [":foo"], 705 } 706 707 java_library { 708 name: "bar", 709 static_libs: ["jargen"], 710 srcs: ["c.java"], 711 } 712 713 java_library { 714 name: "baz", 715 libs: ["jargen"], 716 srcs: ["c.java"], 717 } 718 `) 719 720 foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar") 721 jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar") 722 bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar") 723 baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar") 724 barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar") 725 726 if len(jargen.Inputs) != 1 || jargen.Inputs[0].String() != foo.Output.String() { 727 t.Errorf("expected jargen inputs [%q], got %q", foo.Output.String(), jargen.Inputs.Strings()) 728 } 729 730 if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) { 731 t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String()) 732 } 733 734 if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) { 735 t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String()) 736 } 737 738 if len(barCombined.Inputs) != 2 || 739 barCombined.Inputs[0].String() != bar.Output.String() || 740 barCombined.Inputs[1].String() != jargen.Output.String() { 741 t.Errorf("bar combined jar inputs %v is not [%q, %q]", 742 barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String()) 743 } 744} 745 746func TestExcludeFileGroupInSrcs(t *testing.T) { 747 ctx := testJava(t, ` 748 java_library { 749 name: "foo", 750 srcs: ["a.java", ":foo-srcs"], 751 exclude_srcs: ["a.java", ":foo-excludes"], 752 } 753 754 filegroup { 755 name: "foo-srcs", 756 srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"], 757 } 758 759 filegroup { 760 name: "foo-excludes", 761 srcs: ["java-fg/a.java", "java-fg/b.java"], 762 } 763 `) 764 765 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 766 767 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" { 768 t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) 769 } 770} 771 772func TestJavaSdkLibrary(t *testing.T) { 773 ctx := testJava(t, ` 774 droiddoc_template { 775 name: "droiddoc-templates-sdk", 776 path: ".", 777 } 778 java_sdk_library { 779 name: "foo", 780 srcs: ["a.java", "b.java"], 781 api_packages: ["foo"], 782 } 783 java_sdk_library { 784 name: "bar", 785 srcs: ["a.java", "b.java"], 786 api_packages: ["bar"], 787 } 788 java_library { 789 name: "baz", 790 srcs: ["c.java"], 791 libs: ["foo", "bar"], 792 sdk_version: "system_current", 793 } 794 java_library { 795 name: "qux", 796 srcs: ["c.java"], 797 libs: ["baz"], 798 sdk_version: "system_current", 799 } 800 `) 801 802 // check the existence of the internal modules 803 ctx.ModuleForTests("foo", "android_common") 804 ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common") 805 ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common") 806 ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkTestApiSuffix, "android_common") 807 ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common") 808 ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common") 809 ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkTestApiSuffix, "android_common") 810 ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_arm64_armv8-a") 811 ctx.ModuleForTests("foo.api.public.28", "") 812 ctx.ModuleForTests("foo.api.system.28", "") 813 ctx.ModuleForTests("foo.api.test.28", "") 814 815 bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac") 816 // tests if baz is actually linked to the stubs lib 817 if !strings.Contains(bazJavac.Args["classpath"], "foo.stubs.system.jar") { 818 t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], 819 "foo.stubs.system.jar") 820 } 821 // ... and not to the impl lib 822 if strings.Contains(bazJavac.Args["classpath"], "foo.jar") { 823 t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], 824 "foo.jar") 825 } 826 // test if baz is not linked to the system variant of foo 827 if strings.Contains(bazJavac.Args["classpath"], "foo.stubs.jar") { 828 t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], 829 "foo.stubs.jar") 830 } 831 832 // test if baz has exported SDK lib names foo and bar to qux 833 qux := ctx.ModuleForTests("qux", "android_common") 834 if quxLib, ok := qux.Module().(*Library); ok { 835 sdkLibs := quxLib.ExportedSdkLibs() 836 if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { 837 t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) 838 } 839 } 840} 841 842var compilerFlagsTestCases = []struct { 843 in string 844 out bool 845}{ 846 { 847 in: "a", 848 out: false, 849 }, 850 { 851 in: "-a", 852 out: true, 853 }, 854 { 855 in: "-no-jdk", 856 out: false, 857 }, 858 { 859 in: "-no-stdlib", 860 out: false, 861 }, 862 { 863 in: "-kotlin-home", 864 out: false, 865 }, 866 { 867 in: "-kotlin-home /some/path", 868 out: false, 869 }, 870 { 871 in: "-include-runtime", 872 out: false, 873 }, 874 { 875 in: "-Xintellij-plugin-root", 876 out: false, 877 }, 878} 879 880type mockContext struct { 881 android.ModuleContext 882 result bool 883} 884 885func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) { 886 // CheckBadCompilerFlags calls this function when the flag should be rejected 887 ctx.result = false 888} 889 890func TestCompilerFlags(t *testing.T) { 891 for _, testCase := range compilerFlagsTestCases { 892 ctx := &mockContext{result: true} 893 CheckKotlincFlags(ctx, []string{testCase.in}) 894 if ctx.result != testCase.out { 895 t.Errorf("incorrect output:") 896 t.Errorf(" input: %#v", testCase.in) 897 t.Errorf(" expected: %#v", testCase.out) 898 t.Errorf(" got: %#v", ctx.result) 899 } 900 } 901} 902 903// TODO(jungjw): Consider making this more robust by ignoring path order. 904func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) { 905 variables := ctx.ModuleForTests(moduleName, "android_common").Module().VariablesForTests() 906 flags := strings.Split(variables["javacFlags"], " ") 907 got := "" 908 for _, flag := range flags { 909 keyEnd := strings.Index(flag, "=") 910 if keyEnd > -1 && flag[:keyEnd] == "--patch-module" { 911 got = flag[keyEnd+1:] 912 break 913 } 914 } 915 if expected != got { 916 t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got) 917 } 918} 919 920func TestPatchModule(t *testing.T) { 921 bp := ` 922 java_library { 923 name: "foo", 924 srcs: ["a.java"], 925 } 926 927 java_library { 928 name: "bar", 929 srcs: ["b.java"], 930 no_standard_libs: true, 931 system_modules: "none", 932 patch_module: "java.base", 933 } 934 935 java_library { 936 name: "baz", 937 srcs: ["c.java"], 938 patch_module: "java.base", 939 } 940 ` 941 942 t.Run("1.8", func(t *testing.T) { 943 // Test default javac 1.8 944 ctx := testJava(t, bp) 945 946 checkPatchModuleFlag(t, ctx, "foo", "") 947 checkPatchModuleFlag(t, ctx, "bar", "") 948 checkPatchModuleFlag(t, ctx, "baz", "") 949 }) 950 951 t.Run("1.9", func(t *testing.T) { 952 // Test again with javac 1.9 953 config := testConfig(map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"}) 954 ctx := testContext(config, bp, nil) 955 run(t, ctx, config) 956 957 checkPatchModuleFlag(t, ctx, "foo", "") 958 expected := "java.base=.:" + buildDir 959 checkPatchModuleFlag(t, ctx, "bar", expected) 960 expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework"), moduleToPath("updatable_media_stubs")}, ":") 961 checkPatchModuleFlag(t, ctx, "baz", expected) 962 }) 963} 964