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 "reflect" 22 "regexp" 23 "sort" 24 "strconv" 25 "strings" 26 "testing" 27 28 "github.com/google/blueprint/proptools" 29 30 "android/soong/android" 31 "android/soong/cc" 32 "android/soong/dexpreopt" 33 "android/soong/genrule" 34) 35 36var buildDir string 37 38func setUp() { 39 var err error 40 buildDir, err = ioutil.TempDir("", "soong_java_test") 41 if err != nil { 42 panic(err) 43 } 44} 45 46func tearDown() { 47 os.RemoveAll(buildDir) 48} 49 50func TestMain(m *testing.M) { 51 run := func() int { 52 setUp() 53 defer tearDown() 54 55 return m.Run() 56 } 57 58 os.Exit(run()) 59} 60 61func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config { 62 bp += dexpreopt.BpToolModulesForTest() 63 64 config := TestConfig(buildDir, env, bp, fs) 65 66 // Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that 67 // it doesn't create a real one, which would fail. 68 _ = dexpreopt.GlobalSoongConfigForTests(config) 69 70 return config 71} 72 73func testContext() *android.TestContext { 74 75 ctx := android.NewTestArchContext() 76 RegisterJavaBuildComponents(ctx) 77 RegisterAppBuildComponents(ctx) 78 RegisterAARBuildComponents(ctx) 79 RegisterGenRuleBuildComponents(ctx) 80 RegisterSystemModulesBuildComponents(ctx) 81 ctx.RegisterModuleType("java_plugin", PluginFactory) 82 ctx.RegisterModuleType("filegroup", android.FileGroupFactory) 83 ctx.RegisterModuleType("genrule", genrule.GenRuleFactory) 84 RegisterDocsBuildComponents(ctx) 85 RegisterStubsBuildComponents(ctx) 86 RegisterSdkLibraryBuildComponents(ctx) 87 ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) 88 89 RegisterPrebuiltApisBuildComponents(ctx) 90 91 ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) 92 ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory)) 93 ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory)) 94 95 // Register module types and mutators from cc needed for JNI testing 96 cc.RegisterRequiredBuildComponentsForTest(ctx) 97 98 dexpreopt.RegisterToolModulesForTest(ctx) 99 100 return ctx 101} 102 103func run(t *testing.T, ctx *android.TestContext, config android.Config) { 104 t.Helper() 105 106 pathCtx := android.PathContextForTesting(config) 107 dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx)) 108 109 ctx.Register(config) 110 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 111 android.FailIfErrored(t, errs) 112 _, errs = ctx.PrepareBuildActions(config) 113 android.FailIfErrored(t, errs) 114} 115 116func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) { 117 t.Helper() 118 return testJavaErrorWithConfig(t, pattern, testConfig(nil, bp, nil)) 119} 120 121func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) { 122 t.Helper() 123 ctx := testContext() 124 125 pathCtx := android.PathContextForTesting(config) 126 dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx)) 127 128 ctx.Register(config) 129 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 130 if len(errs) > 0 { 131 android.FailIfNoMatchingErrors(t, pattern, errs) 132 return ctx, config 133 } 134 _, errs = ctx.PrepareBuildActions(config) 135 if len(errs) > 0 { 136 android.FailIfNoMatchingErrors(t, pattern, errs) 137 return ctx, config 138 } 139 140 t.Fatalf("missing expected error %q (0 errors are returned)", pattern) 141 142 return ctx, config 143} 144 145func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) { 146 t.Helper() 147 return testJavaWithConfig(t, testConfig(nil, bp, fs)) 148} 149 150func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) { 151 t.Helper() 152 return testJavaWithFS(t, bp, nil) 153} 154 155func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) { 156 t.Helper() 157 ctx := testContext() 158 run(t, ctx, config) 159 160 return ctx, config 161} 162 163func moduleToPath(name string) string { 164 switch { 165 case name == `""`: 166 return name 167 case strings.HasSuffix(name, ".jar"): 168 return name 169 default: 170 return filepath.Join(buildDir, ".intermediates", name, "android_common", "turbine-combined", name+".jar") 171 } 172} 173 174func TestJavaLinkType(t *testing.T) { 175 testJava(t, ` 176 java_library { 177 name: "foo", 178 srcs: ["a.java"], 179 libs: ["bar"], 180 static_libs: ["baz"], 181 } 182 183 java_library { 184 name: "bar", 185 sdk_version: "current", 186 srcs: ["b.java"], 187 } 188 189 java_library { 190 name: "baz", 191 sdk_version: "system_current", 192 srcs: ["c.java"], 193 } 194 `) 195 196 testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", ` 197 java_library { 198 name: "foo", 199 srcs: ["a.java"], 200 libs: ["bar"], 201 sdk_version: "current", 202 static_libs: ["baz"], 203 } 204 205 java_library { 206 name: "bar", 207 sdk_version: "current", 208 srcs: ["b.java"], 209 } 210 211 java_library { 212 name: "baz", 213 sdk_version: "system_current", 214 srcs: ["c.java"], 215 } 216 `) 217 218 testJava(t, ` 219 java_library { 220 name: "foo", 221 srcs: ["a.java"], 222 libs: ["bar"], 223 sdk_version: "system_current", 224 static_libs: ["baz"], 225 } 226 227 java_library { 228 name: "bar", 229 sdk_version: "current", 230 srcs: ["b.java"], 231 } 232 233 java_library { 234 name: "baz", 235 sdk_version: "system_current", 236 srcs: ["c.java"], 237 } 238 `) 239 240 testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", ` 241 java_library { 242 name: "foo", 243 srcs: ["a.java"], 244 libs: ["bar"], 245 sdk_version: "system_current", 246 static_libs: ["baz"], 247 } 248 249 java_library { 250 name: "bar", 251 sdk_version: "current", 252 srcs: ["b.java"], 253 } 254 255 java_library { 256 name: "baz", 257 srcs: ["c.java"], 258 } 259 `) 260} 261 262func TestSimple(t *testing.T) { 263 ctx, _ := testJava(t, ` 264 java_library { 265 name: "foo", 266 srcs: ["a.java"], 267 libs: ["bar"], 268 static_libs: ["baz"], 269 } 270 271 java_library { 272 name: "bar", 273 srcs: ["b.java"], 274 } 275 276 java_library { 277 name: "baz", 278 srcs: ["c.java"], 279 } 280 `) 281 282 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 283 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 284 285 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 286 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 287 } 288 289 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 290 barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 291 bazTurbine := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "turbine-combined", "baz.jar") 292 293 if !strings.Contains(javac.Args["classpath"], barTurbine) { 294 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 295 } 296 297 if !strings.Contains(javac.Args["classpath"], bazTurbine) { 298 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bazTurbine) 299 } 300 301 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 302 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 303 } 304} 305 306func TestExportedPlugins(t *testing.T) { 307 type Result struct { 308 library string 309 processors string 310 } 311 var tests = []struct { 312 name string 313 extra string 314 results []Result 315 }{ 316 { 317 name: "Exported plugin is not a direct plugin", 318 extra: `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`, 319 results: []Result{{library: "exports", processors: "-proc:none"}}, 320 }, 321 { 322 name: "Exports plugin to dependee", 323 extra: ` 324 java_library{name: "exports", exported_plugins: ["plugin"]} 325 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 326 java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 327 `, 328 results: []Result{ 329 {library: "foo", processors: "-processor com.android.TestPlugin"}, 330 {library: "bar", processors: "-processor com.android.TestPlugin"}, 331 }, 332 }, 333 { 334 name: "Exports plugin to android_library", 335 extra: ` 336 java_library{name: "exports", exported_plugins: ["plugin"]} 337 android_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 338 android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 339 `, 340 results: []Result{ 341 {library: "foo", processors: "-processor com.android.TestPlugin"}, 342 {library: "bar", processors: "-processor com.android.TestPlugin"}, 343 }, 344 }, 345 { 346 name: "Exports plugin is not propagated via transitive deps", 347 extra: ` 348 java_library{name: "exports", exported_plugins: ["plugin"]} 349 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 350 java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]} 351 `, 352 results: []Result{ 353 {library: "foo", processors: "-processor com.android.TestPlugin"}, 354 {library: "bar", processors: "-proc:none"}, 355 }, 356 }, 357 { 358 name: "Exports plugin appends to plugins", 359 extra: ` 360 java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"} 361 java_library{name: "exports", exported_plugins: ["plugin"]} 362 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]} 363 `, 364 results: []Result{ 365 {library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"}, 366 }, 367 }, 368 } 369 370 for _, test := range tests { 371 t.Run(test.name, func(t *testing.T) { 372 ctx, _ := testJava(t, ` 373 java_plugin { 374 name: "plugin", 375 processor_class: "com.android.TestPlugin", 376 } 377 `+test.extra) 378 379 for _, want := range test.results { 380 javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac") 381 if javac.Args["processor"] != want.processors { 382 t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"]) 383 } 384 } 385 }) 386 } 387} 388 389func TestSdkVersionByPartition(t *testing.T) { 390 testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` 391 java_library { 392 name: "foo", 393 srcs: ["a.java"], 394 vendor: true, 395 } 396 `) 397 398 testJava(t, ` 399 java_library { 400 name: "bar", 401 srcs: ["b.java"], 402 } 403 `) 404 405 for _, enforce := range []bool{true, false} { 406 bp := ` 407 java_library { 408 name: "foo", 409 srcs: ["a.java"], 410 product_specific: true, 411 } 412 ` 413 414 config := testConfig(nil, bp, nil) 415 config.TestProductVariables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce) 416 if enforce { 417 testJavaErrorWithConfig(t, "sdk_version must have a value when the module is located at vendor or product", config) 418 } else { 419 testJavaWithConfig(t, config) 420 } 421 } 422} 423 424func TestArchSpecific(t *testing.T) { 425 ctx, _ := testJava(t, ` 426 java_library { 427 name: "foo", 428 srcs: ["a.java"], 429 target: { 430 android: { 431 srcs: ["b.java"], 432 }, 433 }, 434 } 435 `) 436 437 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 438 if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" { 439 t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs) 440 } 441} 442 443func TestBinary(t *testing.T) { 444 ctx, _ := testJava(t, ` 445 java_library_host { 446 name: "foo", 447 srcs: ["a.java"], 448 } 449 450 java_binary_host { 451 name: "bar", 452 srcs: ["b.java"], 453 static_libs: ["foo"], 454 } 455 `) 456 457 buildOS := android.BuildOs.String() 458 459 bar := ctx.ModuleForTests("bar", buildOS+"_common") 460 barJar := bar.Output("bar.jar").Output.String() 461 barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64") 462 barWrapperDeps := barWrapper.Output("bar").Implicits.Strings() 463 464 // Test that the install binary wrapper depends on the installed jar file 465 if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar { 466 t.Errorf("expected binary wrapper implicits [%q], got %v", 467 barJar, barWrapperDeps) 468 } 469 470} 471 472func TestPrebuilts(t *testing.T) { 473 ctx, _ := testJava(t, ` 474 java_library { 475 name: "foo", 476 srcs: ["a.java", ":stubs-source"], 477 libs: ["bar", "sdklib"], 478 static_libs: ["baz"], 479 } 480 481 java_import { 482 name: "bar", 483 jars: ["a.jar"], 484 } 485 486 java_import { 487 name: "baz", 488 jars: ["b.jar"], 489 } 490 491 dex_import { 492 name: "qux", 493 jars: ["b.jar"], 494 } 495 496 java_sdk_library_import { 497 name: "sdklib", 498 public: { 499 jars: ["c.jar"], 500 }, 501 } 502 503 prebuilt_stubs_sources { 504 name: "stubs-source", 505 srcs: ["stubs/sources"], 506 } 507 508 java_test_import { 509 name: "test", 510 jars: ["a.jar"], 511 test_suites: ["cts"], 512 test_config: "AndroidTest.xml", 513 } 514 `) 515 516 fooModule := ctx.ModuleForTests("foo", "android_common") 517 javac := fooModule.Rule("javac") 518 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 519 barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output 520 bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output 521 sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output 522 523 fooLibrary := fooModule.Module().(*Library) 524 assertDeepEquals(t, "foo java sources incorrect", 525 []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings()) 526 527 assertDeepEquals(t, "foo java source jars incorrect", 528 []string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"}, 529 android.NormalizePathsForTesting(fooLibrary.compiledSrcJars)) 530 531 if !strings.Contains(javac.Args["classpath"], barJar.String()) { 532 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) 533 } 534 535 if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) { 536 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) 537 } 538 539 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() { 540 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) 541 } 542 543 ctx.ModuleForTests("qux", "android_common").Rule("Cp") 544} 545 546func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) { 547 if !reflect.DeepEqual(expected, actual) { 548 t.Errorf("%s: expected %q, found %q", message, expected, actual) 549 } 550} 551 552func TestJavaSdkLibraryImport(t *testing.T) { 553 ctx, _ := testJava(t, ` 554 java_library { 555 name: "foo", 556 srcs: ["a.java"], 557 libs: ["sdklib"], 558 sdk_version: "current", 559 } 560 561 java_library { 562 name: "foo.system", 563 srcs: ["a.java"], 564 libs: ["sdklib"], 565 sdk_version: "system_current", 566 } 567 568 java_library { 569 name: "foo.test", 570 srcs: ["a.java"], 571 libs: ["sdklib"], 572 sdk_version: "test_current", 573 } 574 575 java_sdk_library_import { 576 name: "sdklib", 577 public: { 578 jars: ["a.jar"], 579 }, 580 system: { 581 jars: ["b.jar"], 582 }, 583 test: { 584 jars: ["c.jar"], 585 stub_srcs: ["c.java"], 586 }, 587 } 588 `) 589 590 for _, scope := range []string{"", ".system", ".test"} { 591 fooModule := ctx.ModuleForTests("foo"+scope, "android_common") 592 javac := fooModule.Rule("javac") 593 594 sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output 595 if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) { 596 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) 597 } 598 } 599} 600 601func TestDefaults(t *testing.T) { 602 ctx, _ := testJava(t, ` 603 java_defaults { 604 name: "defaults", 605 srcs: ["a.java"], 606 libs: ["bar"], 607 static_libs: ["baz"], 608 optimize: {enabled: false}, 609 } 610 611 java_library { 612 name: "foo", 613 defaults: ["defaults"], 614 } 615 616 java_library { 617 name: "bar", 618 srcs: ["b.java"], 619 } 620 621 java_library { 622 name: "baz", 623 srcs: ["c.java"], 624 } 625 626 android_test { 627 name: "atestOptimize", 628 defaults: ["defaults"], 629 optimize: {enabled: true}, 630 } 631 632 android_test { 633 name: "atestNoOptimize", 634 defaults: ["defaults"], 635 } 636 637 android_test { 638 name: "atestDefault", 639 srcs: ["a.java"], 640 } 641 `) 642 643 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 644 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 645 646 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 647 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 648 } 649 650 barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 651 if !strings.Contains(javac.Args["classpath"], barTurbine) { 652 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 653 } 654 655 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 656 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 657 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 658 } 659 660 atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8") 661 if atestOptimize.Output == nil { 662 t.Errorf("atestOptimize should optimize APK") 663 } 664 665 atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8") 666 if atestNoOptimize.Output == nil { 667 t.Errorf("atestNoOptimize should not optimize APK") 668 } 669 670 atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("r8") 671 if atestDefault.Output == nil { 672 t.Errorf("atestDefault should optimize APK") 673 } 674} 675 676func TestResources(t *testing.T) { 677 var table = []struct { 678 name string 679 prop string 680 extra string 681 args string 682 }{ 683 { 684 // Test that a module with java_resource_dirs includes the files 685 name: "resource dirs", 686 prop: `java_resource_dirs: ["java-res"]`, 687 args: "-C java-res -f java-res/a/a -f java-res/b/b", 688 }, 689 { 690 // Test that a module with java_resources includes the files 691 name: "resource files", 692 prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`, 693 args: "-C . -f java-res/a/a -f java-res/b/b", 694 }, 695 { 696 // Test that a module with a filegroup in java_resources includes the files with the 697 // path prefix 698 name: "resource filegroup", 699 prop: `java_resources: [":foo-res"]`, 700 extra: ` 701 filegroup { 702 name: "foo-res", 703 path: "java-res", 704 srcs: ["java-res/a/a", "java-res/b/b"], 705 }`, 706 args: "-C java-res -f java-res/a/a -f java-res/b/b", 707 }, 708 { 709 // Test that a module with wildcards in java_resource_dirs has the correct path prefixes 710 name: "wildcard dirs", 711 prop: `java_resource_dirs: ["java-res/*"]`, 712 args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b", 713 }, 714 { 715 // Test that a module exclude_java_resource_dirs excludes the files 716 name: "wildcard dirs", 717 prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`, 718 args: "-C java-res/a -f java-res/a/a", 719 }, 720 { 721 // Test wildcards in java_resources 722 name: "wildcard files", 723 prop: `java_resources: ["java-res/**/*"]`, 724 args: "-C . -f java-res/a/a -f java-res/b/b", 725 }, 726 { 727 // Test exclude_java_resources with java_resources 728 name: "wildcard files with exclude", 729 prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`, 730 args: "-C . -f java-res/a/a", 731 }, 732 { 733 // Test exclude_java_resources with java_resource_dirs 734 name: "resource dirs with exclude files", 735 prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`, 736 args: "-C java-res -f java-res/a/a", 737 }, 738 { 739 // Test exclude_java_resource_dirs with java_resource_dirs 740 name: "resource dirs with exclude files", 741 prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`, 742 args: "-C java-res -f java-res/a/a -f java-res/b/b", 743 }, 744 } 745 746 for _, test := range table { 747 t.Run(test.name, func(t *testing.T) { 748 ctx, _ := testJavaWithFS(t, ` 749 java_library { 750 name: "foo", 751 srcs: [ 752 "a.java", 753 "b.java", 754 "c.java", 755 ], 756 `+test.prop+`, 757 } 758 `+test.extra, 759 map[string][]byte{ 760 "java-res/a/a": nil, 761 "java-res/b/b": nil, 762 "java-res2/a": nil, 763 }, 764 ) 765 766 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 767 fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar") 768 769 if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { 770 t.Errorf("foo combined jars %v does not contain %q", 771 foo.Inputs.Strings(), fooRes.Output.String()) 772 } 773 774 if fooRes.Args["jarArgs"] != test.args { 775 t.Errorf("foo resource jar args %q is not %q", 776 fooRes.Args["jarArgs"], test.args) 777 } 778 }) 779 } 780} 781 782func TestIncludeSrcs(t *testing.T) { 783 ctx, _ := testJavaWithFS(t, ` 784 java_library { 785 name: "foo", 786 srcs: [ 787 "a.java", 788 "b.java", 789 "c.java", 790 ], 791 include_srcs: true, 792 } 793 794 java_library { 795 name: "bar", 796 srcs: [ 797 "a.java", 798 "b.java", 799 "c.java", 800 ], 801 java_resource_dirs: ["java-res"], 802 include_srcs: true, 803 } 804 `, map[string][]byte{ 805 "java-res/a/a": nil, 806 "java-res/b/b": nil, 807 "java-res2/a": nil, 808 }) 809 810 // Test a library with include_srcs: true 811 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 812 fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar") 813 814 if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) { 815 t.Errorf("foo combined jars %v does not contain %q", w, g) 816 } 817 818 if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 819 t.Errorf("foo source jar args %q is not %q", w, g) 820 } 821 822 // Test a library with include_srcs: true and resources 823 bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar") 824 barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar") 825 barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar") 826 barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar") 827 828 if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 829 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 830 } 831 832 if g, w := barRes.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 833 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 834 } 835 836 if g, w := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) { 837 t.Errorf("bar combined jars %v does not contain %q", w, g) 838 } 839 840 if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 841 t.Errorf("bar source jar args %q is not %q", w, g) 842 } 843 844 if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w { 845 t.Errorf("bar resource jar args %q is not %q", w, g) 846 } 847} 848 849func TestGeneratedSources(t *testing.T) { 850 ctx, _ := testJavaWithFS(t, ` 851 java_library { 852 name: "foo", 853 srcs: [ 854 "a*.java", 855 ":gen", 856 "b*.java", 857 ], 858 } 859 860 genrule { 861 name: "gen", 862 tool_files: ["java-res/a"], 863 out: ["gen.java"], 864 } 865 `, map[string][]byte{ 866 "a.java": nil, 867 "b.java": nil, 868 }) 869 870 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 871 genrule := ctx.ModuleForTests("gen", "").Rule("generator") 872 873 if filepath.Base(genrule.Output.String()) != "gen.java" { 874 t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String()) 875 } 876 877 if len(javac.Inputs) != 3 || 878 javac.Inputs[0].String() != "a.java" || 879 javac.Inputs[1].String() != genrule.Output.String() || 880 javac.Inputs[2].String() != "b.java" { 881 t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs) 882 } 883} 884 885func TestTurbine(t *testing.T) { 886 ctx, _ := testJava(t, ` 887 java_library { 888 name: "foo", 889 srcs: ["a.java"], 890 sdk_version: "14", 891 } 892 893 java_library { 894 name: "bar", 895 srcs: ["b.java"], 896 static_libs: ["foo"], 897 sdk_version: "14", 898 } 899 900 java_library { 901 name: "baz", 902 srcs: ["c.java"], 903 libs: ["bar"], 904 sdk_version: "14", 905 } 906 `) 907 908 fooTurbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine") 909 barTurbine := ctx.ModuleForTests("bar", "android_common").Rule("turbine") 910 barJavac := ctx.ModuleForTests("bar", "android_common").Rule("javac") 911 barTurbineCombined := ctx.ModuleForTests("bar", "android_common").Description("for turbine") 912 bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac") 913 914 if len(fooTurbine.Inputs) != 1 || fooTurbine.Inputs[0].String() != "a.java" { 915 t.Errorf(`foo inputs %v != ["a.java"]`, fooTurbine.Inputs) 916 } 917 918 fooHeaderJar := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar") 919 if !strings.Contains(barTurbine.Args["classpath"], fooHeaderJar) { 920 t.Errorf("bar turbine classpath %v does not contain %q", barTurbine.Args["classpath"], fooHeaderJar) 921 } 922 if !strings.Contains(barJavac.Args["classpath"], fooHeaderJar) { 923 t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], fooHeaderJar) 924 } 925 if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar { 926 t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar) 927 } 928 if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") { 929 t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], 930 "prebuilts/sdk/14/public/android.jar") 931 } 932} 933 934func TestSharding(t *testing.T) { 935 ctx, _ := testJava(t, ` 936 java_library { 937 name: "bar", 938 srcs: ["a.java","b.java","c.java"], 939 javac_shard_size: 1 940 } 941 `) 942 943 barHeaderJar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 944 for i := 0; i < 3; i++ { 945 barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)) 946 if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) { 947 t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar) 948 } 949 } 950} 951 952func TestDroiddoc(t *testing.T) { 953 ctx, _ := testJavaWithFS(t, ` 954 droiddoc_exported_dir { 955 name: "droiddoc-templates-sdk", 956 path: ".", 957 } 958 filegroup { 959 name: "bar-doc-aidl-srcs", 960 srcs: ["bar-doc/IBar.aidl"], 961 path: "bar-doc", 962 } 963 droiddoc { 964 name: "bar-doc", 965 srcs: [ 966 "bar-doc/a.java", 967 "bar-doc/IFoo.aidl", 968 ":bar-doc-aidl-srcs", 969 ], 970 exclude_srcs: [ 971 "bar-doc/b.java" 972 ], 973 custom_template: "droiddoc-templates-sdk", 974 hdf: [ 975 "android.whichdoc offline", 976 ], 977 knowntags: [ 978 "bar-doc/known_oj_tags.txt", 979 ], 980 proofread_file: "libcore-proofread.txt", 981 todo_file: "libcore-docs-todo.html", 982 args: "-offlinemode -title \"libcore\"", 983 } 984 `, 985 map[string][]byte{ 986 "bar-doc/a.java": nil, 987 "bar-doc/b.java": nil, 988 }) 989 990 barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc") 991 var javaSrcs []string 992 for _, i := range barDoc.Inputs { 993 javaSrcs = append(javaSrcs, i.Base()) 994 } 995 if len(javaSrcs) != 1 || javaSrcs[0] != "a.java" { 996 t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs) 997 } 998 999 aidl := ctx.ModuleForTests("bar-doc", "android_common").Rule("aidl") 1000 if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) { 1001 t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g) 1002 } 1003 1004 if g, w := aidl.Implicits.Strings(), []string{"bar-doc/IBar.aidl", "bar-doc/IFoo.aidl"}; !reflect.DeepEqual(w, g) { 1005 t.Errorf("aidl inputs must be %q, but was %q", w, g) 1006 } 1007} 1008 1009func TestDroidstubs(t *testing.T) { 1010 ctx, _ := testJavaWithFS(t, ` 1011 droiddoc_exported_dir { 1012 name: "droiddoc-templates-sdk", 1013 path: ".", 1014 } 1015 1016 droidstubs { 1017 name: "bar-stubs", 1018 srcs: [ 1019 "bar-doc/a.java", 1020 ], 1021 api_levels_annotations_dirs: [ 1022 "droiddoc-templates-sdk", 1023 ], 1024 api_levels_annotations_enabled: true, 1025 } 1026 1027 droidstubs { 1028 name: "bar-stubs-other", 1029 srcs: [ 1030 "bar-doc/a.java", 1031 ], 1032 api_levels_annotations_dirs: [ 1033 "droiddoc-templates-sdk", 1034 ], 1035 api_levels_annotations_enabled: true, 1036 api_levels_jar_filename: "android.other.jar", 1037 } 1038 `, 1039 map[string][]byte{ 1040 "bar-doc/a.java": nil, 1041 }) 1042 testcases := []struct { 1043 moduleName string 1044 expectedJarFilename string 1045 }{ 1046 { 1047 moduleName: "bar-stubs", 1048 expectedJarFilename: "android.jar", 1049 }, 1050 { 1051 moduleName: "bar-stubs-other", 1052 expectedJarFilename: "android.other.jar", 1053 }, 1054 } 1055 for _, c := range testcases { 1056 m := ctx.ModuleForTests(c.moduleName, "android_common") 1057 metalava := m.Rule("metalava") 1058 expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename 1059 if actual := metalava.RuleParams.Command; !strings.Contains(actual, expected) { 1060 t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, actual) 1061 } 1062 } 1063} 1064 1065func TestDroidstubsWithSystemModules(t *testing.T) { 1066 ctx, _ := testJava(t, ` 1067 droidstubs { 1068 name: "stubs-source-system-modules", 1069 srcs: [ 1070 "bar-doc/a.java", 1071 ], 1072 sdk_version: "none", 1073 system_modules: "source-system-modules", 1074 } 1075 1076 java_library { 1077 name: "source-jar", 1078 srcs: [ 1079 "a.java", 1080 ], 1081 } 1082 1083 java_system_modules { 1084 name: "source-system-modules", 1085 libs: ["source-jar"], 1086 } 1087 1088 droidstubs { 1089 name: "stubs-prebuilt-system-modules", 1090 srcs: [ 1091 "bar-doc/a.java", 1092 ], 1093 sdk_version: "none", 1094 system_modules: "prebuilt-system-modules", 1095 } 1096 1097 java_import { 1098 name: "prebuilt-jar", 1099 jars: ["a.jar"], 1100 } 1101 1102 java_system_modules_import { 1103 name: "prebuilt-system-modules", 1104 libs: ["prebuilt-jar"], 1105 } 1106 `) 1107 1108 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar") 1109 1110 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar") 1111} 1112 1113func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) { 1114 metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava") 1115 var systemJars []string 1116 for _, i := range metalavaRule.Implicits { 1117 systemJars = append(systemJars, i.Base()) 1118 } 1119 if len(systemJars) < 1 || systemJars[0] != systemJar { 1120 t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars) 1121 } 1122} 1123 1124func TestJarGenrules(t *testing.T) { 1125 ctx, _ := testJava(t, ` 1126 java_library { 1127 name: "foo", 1128 srcs: ["a.java"], 1129 } 1130 1131 java_genrule { 1132 name: "jargen", 1133 tool_files: ["b.java"], 1134 cmd: "$(location b.java) $(in) $(out)", 1135 out: ["jargen.jar"], 1136 srcs: [":foo"], 1137 } 1138 1139 java_library { 1140 name: "bar", 1141 static_libs: ["jargen"], 1142 srcs: ["c.java"], 1143 } 1144 1145 java_library { 1146 name: "baz", 1147 libs: ["jargen"], 1148 srcs: ["c.java"], 1149 } 1150 `) 1151 1152 foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar") 1153 jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar") 1154 bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar") 1155 baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar") 1156 barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar") 1157 1158 if len(jargen.Inputs) != 1 || jargen.Inputs[0].String() != foo.Output.String() { 1159 t.Errorf("expected jargen inputs [%q], got %q", foo.Output.String(), jargen.Inputs.Strings()) 1160 } 1161 1162 if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) { 1163 t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String()) 1164 } 1165 1166 if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) { 1167 t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String()) 1168 } 1169 1170 if len(barCombined.Inputs) != 2 || 1171 barCombined.Inputs[0].String() != bar.Output.String() || 1172 barCombined.Inputs[1].String() != jargen.Output.String() { 1173 t.Errorf("bar combined jar inputs %v is not [%q, %q]", 1174 barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String()) 1175 } 1176} 1177 1178func TestExcludeFileGroupInSrcs(t *testing.T) { 1179 ctx, _ := testJava(t, ` 1180 java_library { 1181 name: "foo", 1182 srcs: ["a.java", ":foo-srcs"], 1183 exclude_srcs: ["a.java", ":foo-excludes"], 1184 } 1185 1186 filegroup { 1187 name: "foo-srcs", 1188 srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"], 1189 } 1190 1191 filegroup { 1192 name: "foo-excludes", 1193 srcs: ["java-fg/a.java", "java-fg/b.java"], 1194 } 1195 `) 1196 1197 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 1198 1199 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" { 1200 t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) 1201 } 1202} 1203 1204func TestJavaLibrary(t *testing.T) { 1205 config := testConfig(nil, "", map[string][]byte{ 1206 "libcore/Android.bp": []byte(` 1207 java_library { 1208 name: "core", 1209 sdk_version: "none", 1210 system_modules: "none", 1211 }`), 1212 }) 1213 ctx := testContext() 1214 run(t, ctx, config) 1215} 1216 1217func TestJavaSdkLibrary(t *testing.T) { 1218 ctx, _ := testJava(t, ` 1219 droiddoc_exported_dir { 1220 name: "droiddoc-templates-sdk", 1221 path: ".", 1222 } 1223 java_sdk_library { 1224 name: "foo", 1225 srcs: ["a.java", "b.java"], 1226 api_packages: ["foo"], 1227 } 1228 java_sdk_library { 1229 name: "bar", 1230 srcs: ["a.java", "b.java"], 1231 api_packages: ["bar"], 1232 } 1233 java_library { 1234 name: "baz", 1235 srcs: ["c.java"], 1236 libs: ["foo", "bar.stubs"], 1237 sdk_version: "system_current", 1238 } 1239 java_sdk_library { 1240 name: "barney", 1241 srcs: ["c.java"], 1242 api_only: true, 1243 } 1244 java_sdk_library { 1245 name: "betty", 1246 srcs: ["c.java"], 1247 shared_library: false, 1248 } 1249 java_sdk_library_import { 1250 name: "quuz", 1251 public: { 1252 jars: ["c.jar"], 1253 }, 1254 } 1255 java_sdk_library_import { 1256 name: "fred", 1257 public: { 1258 jars: ["b.jar"], 1259 }, 1260 } 1261 java_sdk_library_import { 1262 name: "wilma", 1263 public: { 1264 jars: ["b.jar"], 1265 }, 1266 shared_library: false, 1267 } 1268 java_library { 1269 name: "qux", 1270 srcs: ["c.java"], 1271 libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"], 1272 sdk_version: "system_current", 1273 } 1274 java_library { 1275 name: "baz-test", 1276 srcs: ["c.java"], 1277 libs: ["foo"], 1278 sdk_version: "test_current", 1279 } 1280 java_library { 1281 name: "baz-29", 1282 srcs: ["c.java"], 1283 libs: ["foo"], 1284 sdk_version: "system_29", 1285 } 1286 `) 1287 1288 // check the existence of the internal modules 1289 ctx.ModuleForTests("foo", "android_common") 1290 ctx.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common") 1291 ctx.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common") 1292 ctx.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common") 1293 ctx.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common") 1294 ctx.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common") 1295 ctx.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common") 1296 ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common") 1297 ctx.ModuleForTests("foo.api.public.28", "") 1298 ctx.ModuleForTests("foo.api.system.28", "") 1299 ctx.ModuleForTests("foo.api.test.28", "") 1300 1301 bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac") 1302 // tests if baz is actually linked to the stubs lib 1303 if !strings.Contains(bazJavac.Args["classpath"], "foo.stubs.system.jar") { 1304 t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], 1305 "foo.stubs.system.jar") 1306 } 1307 // ... and not to the impl lib 1308 if strings.Contains(bazJavac.Args["classpath"], "foo.jar") { 1309 t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], 1310 "foo.jar") 1311 } 1312 // test if baz is not linked to the system variant of foo 1313 if strings.Contains(bazJavac.Args["classpath"], "foo.stubs.jar") { 1314 t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], 1315 "foo.stubs.jar") 1316 } 1317 1318 bazTestJavac := ctx.ModuleForTests("baz-test", "android_common").Rule("javac") 1319 // tests if baz-test is actually linked to the test stubs lib 1320 if !strings.Contains(bazTestJavac.Args["classpath"], "foo.stubs.test.jar") { 1321 t.Errorf("baz-test javac classpath %v does not contain %q", bazTestJavac.Args["classpath"], 1322 "foo.stubs.test.jar") 1323 } 1324 1325 baz29Javac := ctx.ModuleForTests("baz-29", "android_common").Rule("javac") 1326 // tests if baz-29 is actually linked to the system 29 stubs lib 1327 if !strings.Contains(baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar") { 1328 t.Errorf("baz-29 javac classpath %v does not contain %q", baz29Javac.Args["classpath"], 1329 "prebuilts/sdk/29/system/foo.jar") 1330 } 1331 1332 // test if baz has exported SDK lib names foo and bar to qux 1333 qux := ctx.ModuleForTests("qux", "android_common") 1334 if quxLib, ok := qux.Module().(*Library); ok { 1335 sdkLibs := quxLib.ExportedSdkLibs() 1336 sort.Strings(sdkLibs) 1337 if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { 1338 t.Errorf("qux should export %q but exports %q", w, sdkLibs) 1339 } 1340 } 1341} 1342 1343func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { 1344 ctx, _ := testJava(t, ` 1345 java_sdk_library { 1346 name: "foo", 1347 srcs: ["a.java"], 1348 api_only: true, 1349 public: { 1350 enabled: true, 1351 }, 1352 } 1353 1354 java_library { 1355 name: "bar", 1356 srcs: ["b.java"], 1357 libs: ["foo"], 1358 } 1359 `) 1360 1361 // The bar library should depend on the stubs jar. 1362 barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac") 1363 if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { 1364 t.Errorf("expected %q, found %#q", expected, actual) 1365 } 1366} 1367 1368func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { 1369 testJava(t, ` 1370 java_sdk_library { 1371 name: "foo", 1372 srcs: ["a.java"], 1373 api_packages: ["foo"], 1374 public: { 1375 enabled: true, 1376 }, 1377 } 1378 1379 java_library { 1380 name: "bar", 1381 srcs: ["b.java", ":foo{.public.stubs.source}"], 1382 } 1383 `) 1384} 1385 1386func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { 1387 testJavaError(t, `"foo" does not provide api scope system`, ` 1388 java_sdk_library { 1389 name: "foo", 1390 srcs: ["a.java"], 1391 api_packages: ["foo"], 1392 public: { 1393 enabled: true, 1394 }, 1395 } 1396 1397 java_library { 1398 name: "bar", 1399 srcs: ["b.java", ":foo{.system.stubs.source}"], 1400 } 1401 `) 1402} 1403 1404func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { 1405 testJava(t, ` 1406 java_sdk_library_import { 1407 name: "foo", 1408 public: { 1409 jars: ["a.jar"], 1410 stub_srcs: ["a.java"], 1411 current_api: "api/current.txt", 1412 removed_api: "api/removed.txt", 1413 }, 1414 } 1415 1416 java_library { 1417 name: "bar", 1418 srcs: [":foo{.public.stubs.source}"], 1419 java_resources: [ 1420 ":foo{.public.api.txt}", 1421 ":foo{.public.removed-api.txt}", 1422 ], 1423 } 1424 `) 1425} 1426 1427func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { 1428 bp := ` 1429 java_sdk_library_import { 1430 name: "foo", 1431 public: { 1432 jars: ["a.jar"], 1433 }, 1434 } 1435 ` 1436 1437 t.Run("stubs.source", func(t *testing.T) { 1438 testJavaError(t, `stubs.source not available for api scope public`, bp+` 1439 java_library { 1440 name: "bar", 1441 srcs: [":foo{.public.stubs.source}"], 1442 java_resources: [ 1443 ":foo{.public.api.txt}", 1444 ":foo{.public.removed-api.txt}", 1445 ], 1446 } 1447 `) 1448 }) 1449 1450 t.Run("api.txt", func(t *testing.T) { 1451 testJavaError(t, `api.txt not available for api scope public`, bp+` 1452 java_library { 1453 name: "bar", 1454 srcs: ["a.java"], 1455 java_resources: [ 1456 ":foo{.public.api.txt}", 1457 ], 1458 } 1459 `) 1460 }) 1461 1462 t.Run("removed-api.txt", func(t *testing.T) { 1463 testJavaError(t, `removed-api.txt not available for api scope public`, bp+` 1464 java_library { 1465 name: "bar", 1466 srcs: ["a.java"], 1467 java_resources: [ 1468 ":foo{.public.removed-api.txt}", 1469 ], 1470 } 1471 `) 1472 }) 1473} 1474 1475func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { 1476 testJavaError(t, `module "foo": enabled api scope "system" depends on disabled scope "public"`, ` 1477 java_sdk_library { 1478 name: "foo", 1479 srcs: ["a.java", "b.java"], 1480 api_packages: ["foo"], 1481 // Explicitly disable public to test the check that ensures the set of enabled 1482 // scopes is consistent. 1483 public: { 1484 enabled: false, 1485 }, 1486 system: { 1487 enabled: true, 1488 }, 1489 } 1490 `) 1491} 1492 1493func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { 1494 testJava(t, ` 1495 java_sdk_library { 1496 name: "foo", 1497 srcs: ["a.java", "b.java"], 1498 api_packages: ["foo"], 1499 system: { 1500 enabled: true, 1501 sdk_version: "module_current", 1502 }, 1503 } 1504 `) 1505} 1506 1507func TestJavaSdkLibrary_ModuleLib(t *testing.T) { 1508 testJava(t, ` 1509 java_sdk_library { 1510 name: "foo", 1511 srcs: ["a.java", "b.java"], 1512 api_packages: ["foo"], 1513 system: { 1514 enabled: true, 1515 }, 1516 module_lib: { 1517 enabled: true, 1518 }, 1519 } 1520 `) 1521} 1522 1523func TestJavaSdkLibrary_SystemServer(t *testing.T) { 1524 testJava(t, ` 1525 java_sdk_library { 1526 name: "foo", 1527 srcs: ["a.java", "b.java"], 1528 api_packages: ["foo"], 1529 system: { 1530 enabled: true, 1531 }, 1532 system_server: { 1533 enabled: true, 1534 }, 1535 } 1536 `) 1537} 1538 1539func TestJavaSdkLibrary_MissingScope(t *testing.T) { 1540 testJavaError(t, `requires api scope module-lib from foo but it only has \[\] available`, ` 1541 java_sdk_library { 1542 name: "foo", 1543 srcs: ["a.java"], 1544 public: { 1545 enabled: false, 1546 }, 1547 } 1548 1549 java_library { 1550 name: "baz", 1551 srcs: ["a.java"], 1552 libs: ["foo"], 1553 sdk_version: "module_current", 1554 } 1555 `) 1556} 1557 1558func TestJavaSdkLibrary_FallbackScope(t *testing.T) { 1559 testJava(t, ` 1560 java_sdk_library { 1561 name: "foo", 1562 srcs: ["a.java"], 1563 system: { 1564 enabled: true, 1565 }, 1566 } 1567 1568 java_library { 1569 name: "baz", 1570 srcs: ["a.java"], 1571 libs: ["foo"], 1572 // foo does not have module-lib scope so it should fallback to system 1573 sdk_version: "module_current", 1574 } 1575 `) 1576} 1577 1578func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) { 1579 ctx, _ := testJava(t, ` 1580 java_sdk_library { 1581 name: "foo", 1582 srcs: ["a.java"], 1583 system: { 1584 enabled: true, 1585 }, 1586 default_to_stubs: true, 1587 } 1588 1589 java_library { 1590 name: "baz", 1591 srcs: ["a.java"], 1592 libs: ["foo"], 1593 // does not have sdk_version set, should fallback to module, 1594 // which will then fallback to system because the module scope 1595 // is not enabled. 1596 } 1597 `) 1598 // The baz library should depend on the system stubs jar. 1599 bazLibrary := ctx.ModuleForTests("baz", "android_common").Rule("javac") 1600 if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { 1601 t.Errorf("expected %q, found %#q", expected, actual) 1602 } 1603} 1604 1605var compilerFlagsTestCases = []struct { 1606 in string 1607 out bool 1608}{ 1609 { 1610 in: "a", 1611 out: false, 1612 }, 1613 { 1614 in: "-a", 1615 out: true, 1616 }, 1617 { 1618 in: "-no-jdk", 1619 out: false, 1620 }, 1621 { 1622 in: "-no-stdlib", 1623 out: false, 1624 }, 1625 { 1626 in: "-kotlin-home", 1627 out: false, 1628 }, 1629 { 1630 in: "-kotlin-home /some/path", 1631 out: false, 1632 }, 1633 { 1634 in: "-include-runtime", 1635 out: false, 1636 }, 1637 { 1638 in: "-Xintellij-plugin-root", 1639 out: false, 1640 }, 1641} 1642 1643type mockContext struct { 1644 android.ModuleContext 1645 result bool 1646} 1647 1648func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) { 1649 // CheckBadCompilerFlags calls this function when the flag should be rejected 1650 ctx.result = false 1651} 1652 1653func TestCompilerFlags(t *testing.T) { 1654 for _, testCase := range compilerFlagsTestCases { 1655 ctx := &mockContext{result: true} 1656 CheckKotlincFlags(ctx, []string{testCase.in}) 1657 if ctx.result != testCase.out { 1658 t.Errorf("incorrect output:") 1659 t.Errorf(" input: %#v", testCase.in) 1660 t.Errorf(" expected: %#v", testCase.out) 1661 t.Errorf(" got: %#v", ctx.result) 1662 } 1663 } 1664} 1665 1666// TODO(jungjw): Consider making this more robust by ignoring path order. 1667func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) { 1668 variables := ctx.ModuleForTests(moduleName, "android_common").Module().VariablesForTests() 1669 flags := strings.Split(variables["javacFlags"], " ") 1670 got := "" 1671 for _, flag := range flags { 1672 keyEnd := strings.Index(flag, "=") 1673 if keyEnd > -1 && flag[:keyEnd] == "--patch-module" { 1674 got = flag[keyEnd+1:] 1675 break 1676 } 1677 } 1678 if expected != got { 1679 t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got) 1680 } 1681} 1682 1683func TestPatchModule(t *testing.T) { 1684 t.Run("Java language level 8", func(t *testing.T) { 1685 // Test with legacy javac -source 1.8 -target 1.8 1686 bp := ` 1687 java_library { 1688 name: "foo", 1689 srcs: ["a.java"], 1690 java_version: "1.8", 1691 } 1692 1693 java_library { 1694 name: "bar", 1695 srcs: ["b.java"], 1696 sdk_version: "none", 1697 system_modules: "none", 1698 patch_module: "java.base", 1699 java_version: "1.8", 1700 } 1701 1702 java_library { 1703 name: "baz", 1704 srcs: ["c.java"], 1705 patch_module: "java.base", 1706 java_version: "1.8", 1707 } 1708 ` 1709 ctx, _ := testJava(t, bp) 1710 1711 checkPatchModuleFlag(t, ctx, "foo", "") 1712 checkPatchModuleFlag(t, ctx, "bar", "") 1713 checkPatchModuleFlag(t, ctx, "baz", "") 1714 }) 1715 1716 t.Run("Java language level 9", func(t *testing.T) { 1717 // Test with default javac -source 9 -target 9 1718 bp := ` 1719 java_library { 1720 name: "foo", 1721 srcs: ["a.java"], 1722 } 1723 1724 java_library { 1725 name: "bar", 1726 srcs: ["b.java"], 1727 sdk_version: "none", 1728 system_modules: "none", 1729 patch_module: "java.base", 1730 } 1731 1732 java_library { 1733 name: "baz", 1734 srcs: ["c.java"], 1735 patch_module: "java.base", 1736 } 1737 ` 1738 ctx, _ := testJava(t, bp) 1739 1740 checkPatchModuleFlag(t, ctx, "foo", "") 1741 expected := "java.base=.:" + buildDir 1742 checkPatchModuleFlag(t, ctx, "bar", expected) 1743 expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework")}, ":") 1744 checkPatchModuleFlag(t, ctx, "baz", expected) 1745 }) 1746} 1747 1748func TestJavaSystemModules(t *testing.T) { 1749 ctx, _ := testJava(t, ` 1750 java_system_modules { 1751 name: "system-modules", 1752 libs: ["system-module1", "system-module2"], 1753 } 1754 java_library { 1755 name: "system-module1", 1756 srcs: ["a.java"], 1757 sdk_version: "none", 1758 system_modules: "none", 1759 } 1760 java_library { 1761 name: "system-module2", 1762 srcs: ["b.java"], 1763 sdk_version: "none", 1764 system_modules: "none", 1765 } 1766 `) 1767 1768 // check the existence of the module 1769 systemModules := ctx.ModuleForTests("system-modules", "android_common") 1770 1771 cmd := systemModules.Rule("jarsTosystemModules") 1772 1773 // make sure the command compiles against the supplied modules. 1774 for _, module := range []string{"system-module1.jar", "system-module2.jar"} { 1775 if !strings.Contains(cmd.Args["classpath"], module) { 1776 t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"], 1777 module) 1778 } 1779 } 1780} 1781 1782func TestJavaSystemModulesImport(t *testing.T) { 1783 ctx, _ := testJava(t, ` 1784 java_system_modules_import { 1785 name: "system-modules", 1786 libs: ["system-module1", "system-module2"], 1787 } 1788 java_import { 1789 name: "system-module1", 1790 jars: ["a.jar"], 1791 } 1792 java_import { 1793 name: "system-module2", 1794 jars: ["b.jar"], 1795 } 1796 `) 1797 1798 // check the existence of the module 1799 systemModules := ctx.ModuleForTests("system-modules", "android_common") 1800 1801 cmd := systemModules.Rule("jarsTosystemModules") 1802 1803 // make sure the command compiles against the supplied modules. 1804 for _, module := range []string{"system-module1.jar", "system-module2.jar"} { 1805 if !strings.Contains(cmd.Args["classpath"], module) { 1806 t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"], 1807 module) 1808 } 1809 } 1810} 1811 1812func TestJavaLibraryWithSystemModules(t *testing.T) { 1813 ctx, _ := testJava(t, ` 1814 java_library { 1815 name: "lib-with-source-system-modules", 1816 srcs: [ 1817 "a.java", 1818 ], 1819 sdk_version: "none", 1820 system_modules: "source-system-modules", 1821 } 1822 1823 java_library { 1824 name: "source-jar", 1825 srcs: [ 1826 "a.java", 1827 ], 1828 } 1829 1830 java_system_modules { 1831 name: "source-system-modules", 1832 libs: ["source-jar"], 1833 } 1834 1835 java_library { 1836 name: "lib-with-prebuilt-system-modules", 1837 srcs: [ 1838 "a.java", 1839 ], 1840 sdk_version: "none", 1841 system_modules: "prebuilt-system-modules", 1842 } 1843 1844 java_import { 1845 name: "prebuilt-jar", 1846 jars: ["a.jar"], 1847 } 1848 1849 java_system_modules_import { 1850 name: "prebuilt-system-modules", 1851 libs: ["prebuilt-jar"], 1852 } 1853 `) 1854 1855 checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") 1856 1857 checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") 1858} 1859 1860func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { 1861 javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") 1862 bootClasspath := javacRule.Args["bootClasspath"] 1863 if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { 1864 t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) 1865 } 1866} 1867