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 "fmt" 19 "os" 20 "path/filepath" 21 "reflect" 22 "runtime" 23 "slices" 24 "strconv" 25 "strings" 26 "testing" 27 28 "github.com/google/blueprint" 29 "github.com/google/blueprint/proptools" 30 31 "android/soong/aconfig" 32 "android/soong/android" 33 "android/soong/cc" 34 "android/soong/dexpreopt" 35 "android/soong/genrule" 36) 37 38// Legacy preparer used for running tests within the java package. 39// 40// This includes everything that was needed to run any test in the java package prior to the 41// introduction of the test fixtures. Tests that are being converted to use fixtures directly 42// rather than through the testJava...() methods should avoid using this and instead use the 43// various preparers directly, using android.GroupFixturePreparers(...) to group them when 44// necessary. 45// 46// deprecated 47var prepareForJavaTest = android.GroupFixturePreparers( 48 genrule.PrepareForTestWithGenRuleBuildComponents, 49 // Get the CC build components but not default modules. 50 cc.PrepareForTestWithCcBuildComponents, 51 // Include all the default java modules. 52 PrepareForTestWithDexpreopt, 53 // Include aconfig modules. 54 aconfig.PrepareForTestWithAconfigBuildComponents, 55) 56 57func TestMain(m *testing.M) { 58 os.Exit(m.Run()) 59} 60 61// testJavaError is a legacy way of running tests of java modules that expect errors. 62// 63// See testJava for an explanation as to how to stop using this deprecated method. 64// 65// deprecated 66func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) { 67 t.Helper() 68 result := android.GroupFixturePreparers( 69 prepareForJavaTest, dexpreopt.PrepareForTestByEnablingDexpreopt). 70 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). 71 RunTestWithBp(t, bp) 72 return result.TestContext, result.Config 73} 74 75// testJavaWithFS runs tests using the prepareForJavaTest 76// 77// See testJava for an explanation as to how to stop using this deprecated method. 78// 79// deprecated 80func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) { 81 t.Helper() 82 result := android.GroupFixturePreparers( 83 prepareForJavaTest, fs.AddToFixture()).RunTestWithBp(t, bp) 84 return result.TestContext, result.Config 85} 86 87// testJava runs tests using the prepareForJavaTest 88// 89// Do not add any new usages of this, instead use the prepareForJavaTest directly as it makes it 90// much easier to customize the test behavior. 91// 92// If it is necessary to customize the behavior of an existing test that uses this then please first 93// convert the test to using prepareForJavaTest first and then in a following change add the 94// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify 95// that it did not change the test behavior unexpectedly. 96// 97// deprecated 98func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) { 99 t.Helper() 100 result := prepareForJavaTest.RunTestWithBp(t, bp) 101 return result.TestContext, result.Config 102} 103 104// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that 105// is defined in PrepareForIntegrationTestWithJava 106func defaultModuleToPath(name string) string { 107 switch { 108 case name == `""`: 109 return name 110 case strings.HasSuffix(name, ".jar"): 111 return name 112 default: 113 return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar") 114 } 115} 116 117// Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by 118// running it in a fixture that requires all source files to exist. 119func TestPrepareForTestWithJavaDefaultModules(t *testing.T) { 120 android.GroupFixturePreparers( 121 PrepareForTestWithJavaDefaultModules, 122 android.PrepareForTestDisallowNonExistentPaths, 123 ).RunTest(t) 124} 125 126func TestJavaLinkType(t *testing.T) { 127 testJava(t, ` 128 java_library { 129 name: "foo", 130 srcs: ["a.java"], 131 libs: ["bar"], 132 static_libs: ["baz"], 133 } 134 135 java_library { 136 name: "bar", 137 sdk_version: "current", 138 srcs: ["b.java"], 139 } 140 141 java_library { 142 name: "baz", 143 sdk_version: "system_current", 144 srcs: ["c.java"], 145 } 146 `) 147 148 testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", ` 149 java_library { 150 name: "foo", 151 srcs: ["a.java"], 152 libs: ["bar"], 153 sdk_version: "current", 154 static_libs: ["baz"], 155 } 156 157 java_library { 158 name: "bar", 159 sdk_version: "current", 160 srcs: ["b.java"], 161 } 162 163 java_library { 164 name: "baz", 165 sdk_version: "system_current", 166 srcs: ["c.java"], 167 } 168 `) 169 170 testJava(t, ` 171 java_library { 172 name: "foo", 173 srcs: ["a.java"], 174 libs: ["bar"], 175 sdk_version: "system_current", 176 static_libs: ["baz"], 177 } 178 179 java_library { 180 name: "bar", 181 sdk_version: "current", 182 srcs: ["b.java"], 183 } 184 185 java_library { 186 name: "baz", 187 sdk_version: "system_current", 188 srcs: ["c.java"], 189 } 190 `) 191 192 testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", ` 193 java_library { 194 name: "foo", 195 srcs: ["a.java"], 196 libs: ["bar"], 197 sdk_version: "system_current", 198 static_libs: ["baz"], 199 } 200 201 java_library { 202 name: "bar", 203 sdk_version: "current", 204 srcs: ["b.java"], 205 } 206 207 java_library { 208 name: "baz", 209 srcs: ["c.java"], 210 } 211 `) 212} 213 214func TestSimple(t *testing.T) { 215 bp := ` 216 java_library { 217 name: "foo", 218 srcs: ["a.java"], 219 libs: ["bar"], 220 static_libs: ["baz"], 221 } 222 223 java_library { 224 name: "bar", 225 srcs: ["b.java"], 226 static_libs: ["quz"], 227 } 228 229 java_library { 230 name: "baz", 231 srcs: ["c.java"], 232 static_libs: ["quz"], 233 } 234 235 java_library { 236 name: "quz", 237 srcs: ["d.java"], 238 }` 239 240 frameworkTurbineCombinedJars := []string{ 241 "out/soong/.intermediates/default/java/ext/android_common/turbine-combined/ext.jar", 242 "out/soong/.intermediates/default/java/framework/android_common/turbine-combined/framework.jar", 243 } 244 245 frameworkTurbineJars := []string{ 246 "out/soong/.intermediates/default/java/ext/android_common/turbine/ext.jar", 247 "out/soong/.intermediates/default/java/framework/android_common/turbine/framework.jar", 248 } 249 250 testCases := []struct { 251 name string 252 253 preparer android.FixturePreparer 254 255 fooJavacInputs []string 256 fooJavacClasspath []string 257 fooCombinedInputs []string 258 fooHeaderCombinedInputs []string 259 260 barJavacInputs []string 261 barJavacClasspath []string 262 barCombinedInputs []string 263 barHeaderCombinedInputs []string 264 }{ 265 { 266 name: "normal", 267 preparer: android.NullFixturePreparer, 268 fooJavacInputs: []string{"a.java"}, 269 fooJavacClasspath: slices.Concat( 270 frameworkTurbineCombinedJars, 271 []string{ 272 "out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar", 273 "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar", 274 }, 275 ), 276 fooCombinedInputs: []string{ 277 "out/soong/.intermediates/foo/android_common/javac/foo.jar", 278 "out/soong/.intermediates/baz/android_common/combined/baz.jar", 279 }, 280 281 fooHeaderCombinedInputs: []string{ 282 "out/soong/.intermediates/foo/android_common/turbine/foo.jar", 283 "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar", 284 }, 285 286 barJavacInputs: []string{"b.java"}, 287 barJavacClasspath: slices.Concat( 288 frameworkTurbineCombinedJars, 289 []string{ 290 "out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar", 291 }, 292 ), 293 barCombinedInputs: []string{ 294 "out/soong/.intermediates/bar/android_common/javac/bar.jar", 295 "out/soong/.intermediates/quz/android_common/javac/quz.jar", 296 }, 297 barHeaderCombinedInputs: []string{ 298 "out/soong/.intermediates/bar/android_common/turbine/bar.jar", 299 "out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar", 300 }, 301 }, 302 { 303 name: "transitive classpath", 304 preparer: PrepareForTestWithTransitiveClasspathEnabled, 305 fooJavacInputs: []string{"a.java"}, 306 fooJavacClasspath: slices.Concat( 307 frameworkTurbineJars, 308 []string{ 309 "out/soong/.intermediates/bar/android_common/turbine/bar.jar", 310 "out/soong/.intermediates/quz/android_common/turbine/quz.jar", 311 "out/soong/.intermediates/baz/android_common/turbine/baz.jar", 312 }, 313 ), 314 fooCombinedInputs: []string{ 315 "out/soong/.intermediates/foo/android_common/javac/foo.jar", 316 "out/soong/.intermediates/baz/android_common/javac/baz.jar", 317 "out/soong/.intermediates/quz/android_common/javac/quz.jar", 318 }, 319 320 fooHeaderCombinedInputs: []string{ 321 "out/soong/.intermediates/foo/android_common/turbine/foo.jar", 322 "out/soong/.intermediates/baz/android_common/turbine/baz.jar", 323 "out/soong/.intermediates/quz/android_common/turbine/quz.jar", 324 }, 325 326 barJavacInputs: []string{"b.java"}, 327 barJavacClasspath: slices.Concat( 328 frameworkTurbineJars, 329 []string{"out/soong/.intermediates/quz/android_common/turbine/quz.jar"}, 330 ), 331 barCombinedInputs: []string{ 332 "out/soong/.intermediates/bar/android_common/javac/bar.jar", 333 "out/soong/.intermediates/quz/android_common/javac/quz.jar", 334 }, 335 barHeaderCombinedInputs: []string{ 336 "out/soong/.intermediates/bar/android_common/turbine/bar.jar", 337 "out/soong/.intermediates/quz/android_common/turbine/quz.jar", 338 }, 339 }, 340 } 341 342 for _, tt := range testCases { 343 t.Run(tt.name, func(t *testing.T) { 344 result := android.GroupFixturePreparers( 345 PrepareForTestWithJavaDefaultModules, 346 tt.preparer, 347 ).RunTestWithBp(t, bp) 348 foo := result.ModuleForTests("foo", "android_common") 349 350 fooJavac := foo.Rule("javac") 351 android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs) 352 353 fooJavacClasspath := fooJavac.Args["classpath"] 354 android.AssertStringPathsRelativeToTopEquals(t, "foo javac classpath", result.Config, tt.fooJavacClasspath, 355 strings.Split(strings.TrimPrefix(fooJavacClasspath, "-classpath "), ":")) 356 357 fooCombinedJar := foo.Output("combined/foo.jar") 358 android.AssertPathsRelativeToTopEquals(t, "foo combined inputs", tt.fooCombinedInputs, fooCombinedJar.Inputs) 359 360 fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar") 361 android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs) 362 363 bar := result.ModuleForTests("bar", "android_common") 364 barJavac := bar.Rule("javac") 365 android.AssertPathsRelativeToTopEquals(t, "bar javac inputs", tt.barJavacInputs, barJavac.Inputs) 366 367 barJavacClasspath := barJavac.Args["classpath"] 368 android.AssertStringPathsRelativeToTopEquals(t, "bar javac classpath", result.Config, tt.barJavacClasspath, 369 strings.Split(strings.TrimPrefix(barJavacClasspath, "-classpath "), ":")) 370 371 barCombinedJar := bar.Output("combined/bar.jar") 372 android.AssertPathsRelativeToTopEquals(t, "bar combined inputs", tt.barCombinedInputs, barCombinedJar.Inputs) 373 374 barCombinedHeaderJar := bar.Output("turbine-combined/bar.jar") 375 android.AssertPathsRelativeToTopEquals(t, "bar header combined inputs", tt.barHeaderCombinedInputs, barCombinedHeaderJar.Inputs) 376 }) 377 } 378} 379 380func TestExportedPlugins(t *testing.T) { 381 type Result struct { 382 library string 383 processors string 384 disableTurbine bool 385 } 386 var tests = []struct { 387 name string 388 extra string 389 results []Result 390 }{ 391 { 392 name: "Exported plugin is not a direct plugin", 393 extra: `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`, 394 results: []Result{{library: "exports", processors: "-proc:none"}}, 395 }, 396 { 397 name: "Exports plugin to dependee", 398 extra: ` 399 java_library{name: "exports", exported_plugins: ["plugin"]} 400 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 401 java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 402 `, 403 results: []Result{ 404 {library: "foo", processors: "-processor com.android.TestPlugin"}, 405 {library: "bar", processors: "-processor com.android.TestPlugin"}, 406 }, 407 }, 408 { 409 name: "Exports plugin to android_library", 410 extra: ` 411 java_library{name: "exports", exported_plugins: ["plugin"]} 412 android_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 413 android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 414 `, 415 results: []Result{ 416 {library: "foo", processors: "-processor com.android.TestPlugin"}, 417 {library: "bar", processors: "-processor com.android.TestPlugin"}, 418 }, 419 }, 420 { 421 name: "Exports plugin is not propagated via transitive deps", 422 extra: ` 423 java_library{name: "exports", exported_plugins: ["plugin"]} 424 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 425 java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]} 426 `, 427 results: []Result{ 428 {library: "foo", processors: "-processor com.android.TestPlugin"}, 429 {library: "bar", processors: "-proc:none"}, 430 }, 431 }, 432 { 433 name: "Exports plugin appends to plugins", 434 extra: ` 435 java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"} 436 java_library{name: "exports", exported_plugins: ["plugin"]} 437 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]} 438 `, 439 results: []Result{ 440 {library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"}, 441 }, 442 }, 443 { 444 name: "Exports plugin to with generates_api to dependee", 445 extra: ` 446 java_library{name: "exports", exported_plugins: ["plugin_generates_api"]} 447 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 448 java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 449 `, 450 results: []Result{ 451 {library: "foo", processors: "-processor com.android.TestPlugin", disableTurbine: true}, 452 {library: "bar", processors: "-processor com.android.TestPlugin", disableTurbine: true}, 453 }, 454 }, 455 } 456 457 for _, test := range tests { 458 t.Run(test.name, func(t *testing.T) { 459 ctx, _ := testJava(t, ` 460 java_plugin { 461 name: "plugin", 462 processor_class: "com.android.TestPlugin", 463 } 464 java_plugin { 465 name: "plugin_generates_api", 466 generates_api: true, 467 processor_class: "com.android.TestPlugin", 468 } 469 `+test.extra) 470 471 for _, want := range test.results { 472 javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac") 473 if javac.Args["processor"] != want.processors { 474 t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"]) 475 } 476 turbine := ctx.ModuleForTests(want.library, "android_common").MaybeRule("turbine") 477 disableTurbine := turbine.BuildParams.Rule == nil 478 if disableTurbine != want.disableTurbine { 479 t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine) 480 } 481 } 482 }) 483 } 484} 485 486func TestSdkVersionByPartition(t *testing.T) { 487 testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` 488 java_library { 489 name: "foo", 490 srcs: ["a.java"], 491 vendor: true, 492 } 493 `) 494 495 testJava(t, ` 496 java_library { 497 name: "bar", 498 srcs: ["b.java"], 499 } 500 `) 501 502 for _, enforce := range []bool{true, false} { 503 bp := ` 504 java_library { 505 name: "foo", 506 srcs: ["a.java"], 507 product_specific: true, 508 } 509 ` 510 511 errorHandler := android.FixtureExpectsNoErrors 512 if enforce { 513 errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product") 514 } 515 516 android.GroupFixturePreparers( 517 PrepareForTestWithJavaDefaultModules, 518 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 519 variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce) 520 }), 521 ). 522 ExtendWithErrorHandler(errorHandler). 523 RunTestWithBp(t, bp) 524 } 525} 526 527func TestArchSpecific(t *testing.T) { 528 ctx, _ := testJava(t, ` 529 java_library { 530 name: "foo", 531 srcs: ["a.java"], 532 target: { 533 android: { 534 srcs: ["b.java"], 535 }, 536 }, 537 } 538 `) 539 540 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 541 if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" { 542 t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs) 543 } 544} 545 546func TestBinary(t *testing.T) { 547 ctx, _ := testJava(t, ` 548 java_library_host { 549 name: "foo", 550 srcs: ["a.java"], 551 } 552 553 java_binary_host { 554 name: "bar", 555 srcs: ["b.java"], 556 static_libs: ["foo"], 557 jni_libs: ["libjni"], 558 } 559 560 cc_library_shared { 561 name: "libjni", 562 host_supported: true, 563 device_supported: false, 564 stl: "none", 565 } 566 `) 567 568 buildOS := ctx.Config().BuildOS.String() 569 570 bar := ctx.ModuleForTests("bar", buildOS+"_common") 571 barJar := bar.Output("bar.jar").Output.String() 572 barWrapperDeps := bar.Output("bar").Implicits.Strings() 573 574 libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared") 575 libjniSO := libjni.Rule("Cp").Output.String() 576 577 // Test that the install binary wrapper depends on the installed jar file 578 if g, w := barWrapperDeps, barJar; !android.InList(w, g) { 579 t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g) 580 } 581 582 // Test that the install binary wrapper depends on the installed JNI libraries 583 if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) { 584 t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g) 585 } 586} 587 588func TestTest(t *testing.T) { 589 ctx, _ := testJava(t, ` 590 java_test_host { 591 name: "foo", 592 srcs: ["a.java"], 593 jni_libs: ["libjni"], 594 } 595 596 cc_library_shared { 597 name: "libjni", 598 host_supported: true, 599 device_supported: false, 600 stl: "none", 601 } 602 `) 603 604 buildOS := ctx.Config().BuildOS.String() 605 606 foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 607 608 expected := "lib64/libjni.so" 609 if runtime.GOOS == "darwin" { 610 expected = "lib64/libjni.dylib" 611 } 612 613 fooTestData := foo.data 614 if len(fooTestData) != 1 || fooTestData[0].Rel() != expected { 615 t.Errorf(`expected foo test data relative path [%q], got %q`, 616 expected, fooTestData.Strings()) 617 } 618} 619 620func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { 621 bp := ` 622 java_library { 623 name: "target_library", 624 srcs: ["a.java"], 625 } 626 627 java_binary_host { 628 name: "host_binary", 629 srcs: ["b.java"], 630 } 631 ` 632 633 result := android.GroupFixturePreparers( 634 PrepareForTestWithJavaDefaultModules, 635 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 636 variables.MinimizeJavaDebugInfo = proptools.BoolPtr(true) 637 }), 638 ).RunTestWithBp(t, bp) 639 640 // first, check that the -g flag is added to target modules 641 targetLibrary := result.ModuleForTests("target_library", "android_common") 642 targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"] 643 if !strings.Contains(targetJavaFlags, "-g:source,lines") { 644 t.Errorf("target library javac flags %v should contain "+ 645 "-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags) 646 } 647 648 // check that -g is not overridden for host modules 649 buildOS := result.Config.BuildOS.String() 650 hostBinary := result.ModuleForTests("host_binary", buildOS+"_common") 651 hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"] 652 if strings.Contains(hostJavaFlags, "-g:source,lines") { 653 t.Errorf("java_binary_host javac flags %v should not have "+ 654 "-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags) 655 } 656} 657 658// A minimal context object for use with DexJarBuildPath 659type moduleErrorfTestCtx struct { 660} 661 662func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) { 663} 664 665var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil) 666 667func TestPrebuilts(t *testing.T) { 668 ctx, _ := testJava(t, ` 669 java_library { 670 name: "foo", 671 srcs: ["a.java", ":stubs-source"], 672 libs: ["bar", "sdklib.stubs"], 673 static_libs: ["baz"], 674 } 675 676 java_import { 677 name: "bar", 678 jars: ["a.jar"], 679 } 680 681 java_import { 682 name: "baz", 683 jars: ["b.jar"], 684 sdk_version: "current", 685 compile_dex: true, 686 } 687 688 dex_import { 689 name: "qux", 690 jars: ["b.jar"], 691 } 692 693 java_sdk_library_import { 694 name: "sdklib", 695 public: { 696 jars: ["c.jar"], 697 }, 698 } 699 700 prebuilt_stubs_sources { 701 name: "stubs-source", 702 srcs: ["stubs/sources"], 703 } 704 705 java_test_import { 706 name: "test", 707 jars: ["a.jar"], 708 test_suites: ["cts"], 709 test_config: "AndroidTest.xml", 710 } 711 `) 712 713 fooModule := ctx.ModuleForTests("foo", "android_common") 714 javac := fooModule.Rule("javac") 715 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 716 barModule := ctx.ModuleForTests("bar", "android_common") 717 barJar := barModule.Output("combined/bar.jar").Output 718 bazModule := ctx.ModuleForTests("baz", "android_common") 719 bazJar := bazModule.Output("combined/baz.jar").Output 720 sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common"). 721 Output("combined/sdklib.stubs.jar").Output 722 723 fooLibrary := fooModule.Module().(*Library) 724 assertDeepEquals(t, "foo unique sources incorrect", 725 []string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings()) 726 727 assertDeepEquals(t, "foo java source jars incorrect", 728 []string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"}, 729 android.NormalizePathsForTesting(fooLibrary.compiledSrcJars)) 730 731 if !strings.Contains(javac.Args["classpath"], barJar.String()) { 732 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) 733 } 734 735 errCtx := moduleErrorfTestCtx{} 736 barDexJar := barModule.Module().(*Import).DexJarBuildPath(errCtx) 737 if barDexJar.IsSet() { 738 t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar) 739 } 740 741 if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) { 742 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) 743 } 744 745 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() { 746 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) 747 } 748 749 bazDexJar := bazModule.Module().(*Import).DexJarBuildPath(errCtx).Path() 750 expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar" 751 android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar) 752 753 ctx.ModuleForTests("qux", "android_common").Rule("Cp") 754 755 entries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0] 756 android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0]) 757 entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0] 758 android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0]) 759} 760 761func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) { 762 if !reflect.DeepEqual(expected, actual) { 763 t.Errorf("%s: expected %q, found %q", message, expected, actual) 764 } 765} 766 767func TestPrebuiltStubsSources(t *testing.T) { 768 test := func(t *testing.T, sourcesPath string, expectedInputs []string) { 769 ctx, _ := testJavaWithFS(t, fmt.Sprintf(` 770prebuilt_stubs_sources { 771 name: "stubs-source", 772 srcs: ["%s"], 773}`, sourcesPath), map[string][]byte{ 774 "stubs/sources/pkg/A.java": nil, 775 "stubs/sources/pkg/B.java": nil, 776 }) 777 778 zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src") 779 if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) { 780 t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual) 781 } 782 } 783 784 t.Run("empty/missing directory", func(t *testing.T) { 785 test(t, "empty-directory", nil) 786 }) 787 788 t.Run("non-empty set of sources", func(t *testing.T) { 789 test(t, "stubs/sources", []string{ 790 "stubs/sources/pkg/A.java", 791 "stubs/sources/pkg/B.java", 792 }) 793 }) 794} 795 796func TestDefaults(t *testing.T) { 797 ctx, _ := testJava(t, ` 798 java_defaults { 799 name: "defaults", 800 srcs: ["a.java"], 801 libs: ["bar"], 802 static_libs: ["baz"], 803 optimize: {enabled: false}, 804 } 805 806 java_library { 807 name: "foo", 808 defaults: ["defaults"], 809 } 810 811 java_library { 812 name: "bar", 813 srcs: ["b.java"], 814 } 815 816 java_library { 817 name: "baz", 818 srcs: ["c.java"], 819 } 820 821 android_test { 822 name: "atestOptimize", 823 defaults: ["defaults"], 824 optimize: {enabled: true}, 825 } 826 827 android_test { 828 name: "atestNoOptimize", 829 defaults: ["defaults"], 830 } 831 832 android_test { 833 name: "atestDefault", 834 srcs: ["a.java"], 835 } 836 `) 837 838 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 839 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 840 841 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 842 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 843 } 844 845 barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 846 if !strings.Contains(javac.Args["classpath"], barTurbine) { 847 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 848 } 849 850 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 851 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 852 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 853 } 854 855 atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8") 856 if atestOptimize.Output == nil { 857 t.Errorf("atestOptimize should optimize APK") 858 } 859 860 atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8") 861 if atestNoOptimize.Output == nil { 862 t.Errorf("atestNoOptimize should not optimize APK") 863 } 864 865 atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("d8") 866 if atestDefault.Output == nil { 867 t.Errorf("atestDefault should not optimize APK") 868 } 869} 870 871func TestResources(t *testing.T) { 872 var table = []struct { 873 name string 874 prop string 875 extra string 876 args string 877 }{ 878 { 879 // Test that a module with java_resource_dirs includes the files 880 name: "resource dirs", 881 prop: `java_resource_dirs: ["java-res"]`, 882 args: "-C java-res -f java-res/a/a -f java-res/b/b", 883 }, 884 { 885 // Test that a module with java_resources includes the files 886 name: "resource files", 887 prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`, 888 args: "-C . -f java-res/a/a -f java-res/b/b", 889 }, 890 { 891 // Test that a module with a filegroup in java_resources includes the files with the 892 // path prefix 893 name: "resource filegroup", 894 prop: `java_resources: [":foo-res"]`, 895 extra: ` 896 filegroup { 897 name: "foo-res", 898 path: "java-res", 899 srcs: ["java-res/a/a", "java-res/b/b"], 900 }`, 901 args: "-C java-res -f java-res/a/a -f java-res/b/b", 902 }, 903 { 904 // Test that a module with wildcards in java_resource_dirs has the correct path prefixes 905 name: "wildcard dirs", 906 prop: `java_resource_dirs: ["java-res/*"]`, 907 args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b", 908 }, 909 { 910 // Test that a module exclude_java_resource_dirs excludes the files 911 name: "wildcard dirs", 912 prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`, 913 args: "-C java-res/a -f java-res/a/a", 914 }, 915 { 916 // Test wildcards in java_resources 917 name: "wildcard files", 918 prop: `java_resources: ["java-res/**/*"]`, 919 args: "-C . -f java-res/a/a -f java-res/b/b", 920 }, 921 { 922 // Test exclude_java_resources with java_resources 923 name: "wildcard files with exclude", 924 prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`, 925 args: "-C . -f java-res/a/a", 926 }, 927 { 928 // Test exclude_java_resources with java_resource_dirs 929 name: "resource dirs with exclude files", 930 prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`, 931 args: "-C java-res -f java-res/a/a", 932 }, 933 { 934 // Test exclude_java_resource_dirs with java_resource_dirs 935 name: "resource dirs with exclude files", 936 prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`, 937 args: "-C java-res -f java-res/a/a -f java-res/b/b", 938 }, 939 } 940 941 for _, test := range table { 942 t.Run(test.name, func(t *testing.T) { 943 ctx, _ := testJavaWithFS(t, ` 944 java_library { 945 name: "foo", 946 srcs: [ 947 "a.java", 948 "b.java", 949 "c.java", 950 ], 951 `+test.prop+`, 952 } 953 `+test.extra, 954 map[string][]byte{ 955 "java-res/a/a": nil, 956 "java-res/b/b": nil, 957 "java-res2/a": nil, 958 }, 959 ) 960 961 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 962 fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar") 963 964 if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { 965 t.Errorf("foo combined jars %v does not contain %q", 966 foo.Inputs.Strings(), fooRes.Output.String()) 967 } 968 969 if fooRes.Args["jarArgs"] != test.args { 970 t.Errorf("foo resource jar args %q is not %q", 971 fooRes.Args["jarArgs"], test.args) 972 } 973 }) 974 } 975} 976 977func TestIncludeSrcs(t *testing.T) { 978 ctx, _ := testJavaWithFS(t, ` 979 java_library { 980 name: "foo", 981 srcs: [ 982 "a.java", 983 "b.java", 984 "c.java", 985 ], 986 include_srcs: true, 987 } 988 989 java_library { 990 name: "bar", 991 srcs: [ 992 "a.java", 993 "b.java", 994 "c.java", 995 ], 996 java_resource_dirs: ["java-res"], 997 include_srcs: true, 998 } 999 `, map[string][]byte{ 1000 "java-res/a/a": nil, 1001 "java-res/b/b": nil, 1002 "java-res2/a": nil, 1003 }) 1004 1005 // Test a library with include_srcs: true 1006 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 1007 fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar") 1008 1009 if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) { 1010 t.Errorf("foo combined jars %v does not contain %q", w, g) 1011 } 1012 1013 if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 1014 t.Errorf("foo source jar args %q is not %q", w, g) 1015 } 1016 1017 // Test a library with include_srcs: true and resources 1018 bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar") 1019 barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar") 1020 barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar") 1021 barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar") 1022 1023 if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 1024 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 1025 } 1026 1027 if g, w := barRes.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 1028 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 1029 } 1030 1031 if g, w := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) { 1032 t.Errorf("bar combined jars %v does not contain %q", w, g) 1033 } 1034 1035 if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 1036 t.Errorf("bar source jar args %q is not %q", w, g) 1037 } 1038 1039 if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w { 1040 t.Errorf("bar resource jar args %q is not %q", w, g) 1041 } 1042} 1043 1044func TestGeneratedSources(t *testing.T) { 1045 ctx, _ := testJavaWithFS(t, ` 1046 java_library { 1047 name: "foo", 1048 srcs: [ 1049 "a*.java", 1050 ":gen", 1051 "b*.java", 1052 ], 1053 } 1054 1055 genrule { 1056 name: "gen", 1057 tool_files: ["java-res/a"], 1058 out: ["gen.java"], 1059 } 1060 `, map[string][]byte{ 1061 "a.java": nil, 1062 "b.java": nil, 1063 }) 1064 1065 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 1066 genrule := ctx.ModuleForTests("gen", "").Rule("generator") 1067 1068 if filepath.Base(genrule.Output.String()) != "gen.java" { 1069 t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String()) 1070 } 1071 1072 if len(javac.Inputs) != 3 || 1073 javac.Inputs[0].String() != "a.java" || 1074 javac.Inputs[1].String() != genrule.Output.String() || 1075 javac.Inputs[2].String() != "b.java" { 1076 t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs) 1077 } 1078} 1079 1080func TestTurbine(t *testing.T) { 1081 result := android.GroupFixturePreparers( 1082 prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})). 1083 RunTestWithBp(t, ` 1084 java_library { 1085 name: "foo", 1086 srcs: ["a.java"], 1087 sdk_version: "14", 1088 } 1089 1090 java_library { 1091 name: "bar", 1092 srcs: ["b.java"], 1093 static_libs: ["foo"], 1094 sdk_version: "14", 1095 } 1096 1097 java_library { 1098 name: "baz", 1099 srcs: ["c.java"], 1100 libs: ["bar"], 1101 sdk_version: "14", 1102 } 1103 `) 1104 1105 fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine") 1106 barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine") 1107 barJavac := result.ModuleForTests("bar", "android_common").Rule("javac") 1108 barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine") 1109 bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac") 1110 1111 android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs) 1112 1113 fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar") 1114 barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar") 1115 android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar) 1116 android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar) 1117 android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs) 1118 android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") 1119} 1120 1121func TestSharding(t *testing.T) { 1122 ctx, _ := testJava(t, ` 1123 java_library { 1124 name: "bar", 1125 srcs: ["a.java","b.java","c.java"], 1126 javac_shard_size: 1 1127 } 1128 `) 1129 1130 barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar") 1131 for i := 0; i < 3; i++ { 1132 barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)) 1133 if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") { 1134 t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar) 1135 } 1136 } 1137} 1138 1139func TestExcludeFileGroupInSrcs(t *testing.T) { 1140 ctx, _ := testJava(t, ` 1141 java_library { 1142 name: "foo", 1143 srcs: ["a.java", ":foo-srcs"], 1144 exclude_srcs: ["a.java", ":foo-excludes"], 1145 } 1146 1147 filegroup { 1148 name: "foo-srcs", 1149 srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"], 1150 } 1151 1152 filegroup { 1153 name: "foo-excludes", 1154 srcs: ["java-fg/a.java", "java-fg/b.java"], 1155 } 1156 `) 1157 1158 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 1159 1160 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" { 1161 t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) 1162 } 1163} 1164 1165func TestJavaLibraryOutputFiles(t *testing.T) { 1166 testJavaWithFS(t, "", map[string][]byte{ 1167 "libcore/Android.bp": []byte(` 1168 java_library { 1169 name: "core", 1170 sdk_version: "none", 1171 system_modules: "none", 1172 } 1173 1174 filegroup { 1175 name: "core-jar", 1176 device_common_srcs: [":core{.jar}"], 1177 } 1178 `), 1179 }) 1180} 1181 1182func TestJavaImportOutputFiles(t *testing.T) { 1183 testJavaWithFS(t, "", map[string][]byte{ 1184 "libcore/Android.bp": []byte(` 1185 java_import { 1186 name: "core", 1187 sdk_version: "none", 1188 } 1189 1190 filegroup { 1191 name: "core-jar", 1192 device_common_srcs: [":core{.jar}"], 1193 } 1194 `), 1195 }) 1196} 1197 1198func TestJavaImport(t *testing.T) { 1199 bp := ` 1200 java_library { 1201 name: "source_library", 1202 srcs: ["source.java"], 1203 } 1204 1205 java_import { 1206 name: "import_with_no_deps", 1207 jars: ["no_deps.jar"], 1208 } 1209 1210 java_import { 1211 name: "import_with_source_deps", 1212 jars: ["source_deps.jar"], 1213 static_libs: ["source_library"], 1214 } 1215 1216 java_import { 1217 name: "import_with_import_deps", 1218 jars: ["import_deps.jar"], 1219 static_libs: ["import_with_no_deps"], 1220 } 1221 ` 1222 ctx := android.GroupFixturePreparers( 1223 PrepareForTestWithJavaDefaultModules, 1224 ).RunTestWithBp(t, bp) 1225 1226 source := ctx.ModuleForTests("source_library", "android_common") 1227 sourceJar := source.Output("javac/source_library.jar") 1228 sourceHeaderJar := source.Output("turbine-combined/source_library.jar") 1229 sourceJavaInfo, _ := android.OtherModuleProvider(ctx, source.Module(), JavaInfoProvider) 1230 1231 // The source library produces separate implementation and header jars 1232 android.AssertPathsRelativeToTopEquals(t, "source library implementation jar", 1233 []string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars) 1234 android.AssertPathsRelativeToTopEquals(t, "source library header jar", 1235 []string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars) 1236 1237 importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common") 1238 importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar") 1239 importWithNoDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider) 1240 1241 // An import with no deps produces a single jar used as both the header and implementation jar. 1242 android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar", 1243 []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars) 1244 android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar", 1245 []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars) 1246 android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs", 1247 []string{"no_deps.jar"}, importWithNoDepsJar.Inputs) 1248 1249 importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common") 1250 importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar") 1251 importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar") 1252 importWithSourceDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider) 1253 1254 // An import with source deps produces separate header and implementation jars. 1255 android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar", 1256 []string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars) 1257 android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar", 1258 []string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars) 1259 android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs", 1260 []string{"source_deps.jar", sourceJar.Output.String()}, importWithSourceDepsJar.Inputs) 1261 android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs", 1262 []string{"source_deps.jar", sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs) 1263 1264 importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common") 1265 importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar") 1266 importWithImportDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider) 1267 1268 // An import with only import deps produces a single jar used as both the header and implementation jar. 1269 android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar", 1270 []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars) 1271 android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar", 1272 []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars) 1273 android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs", 1274 []string{"import_deps.jar", importWithNoDepsJar.Output.String()}, importWithImportDepsJar.Inputs) 1275} 1276 1277var compilerFlagsTestCases = []struct { 1278 in string 1279 out bool 1280}{ 1281 { 1282 in: "a", 1283 out: false, 1284 }, 1285 { 1286 in: "-a", 1287 out: true, 1288 }, 1289 { 1290 in: "-no-jdk", 1291 out: false, 1292 }, 1293 { 1294 in: "-no-stdlib", 1295 out: false, 1296 }, 1297 { 1298 in: "-kotlin-home", 1299 out: false, 1300 }, 1301 { 1302 in: "-kotlin-home /some/path", 1303 out: false, 1304 }, 1305 { 1306 in: "-include-runtime", 1307 out: false, 1308 }, 1309 { 1310 in: "-Xintellij-plugin-root", 1311 out: false, 1312 }, 1313} 1314 1315type mockContext struct { 1316 android.ModuleContext 1317 result bool 1318} 1319 1320func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) { 1321 // CheckBadCompilerFlags calls this function when the flag should be rejected 1322 ctx.result = false 1323} 1324 1325func TestCompilerFlags(t *testing.T) { 1326 for _, testCase := range compilerFlagsTestCases { 1327 ctx := &mockContext{result: true} 1328 CheckKotlincFlags(ctx, []string{testCase.in}) 1329 if ctx.result != testCase.out { 1330 t.Errorf("incorrect output:") 1331 t.Errorf(" input: %#v", testCase.in) 1332 t.Errorf(" expected: %#v", testCase.out) 1333 t.Errorf(" got: %#v", ctx.result) 1334 } 1335 } 1336} 1337 1338// TODO(jungjw): Consider making this more robust by ignoring path order. 1339func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) { 1340 variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop() 1341 flags := strings.Split(variables["javacFlags"], " ") 1342 got := "" 1343 for _, flag := range flags { 1344 keyEnd := strings.Index(flag, "=") 1345 if keyEnd > -1 && flag[:keyEnd] == "--patch-module" { 1346 got = flag[keyEnd+1:] 1347 break 1348 } 1349 } 1350 if expected != android.StringPathRelativeToTop(ctx.Config().SoongOutDir(), got) { 1351 t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got) 1352 } 1353} 1354 1355func TestPatchModule(t *testing.T) { 1356 t.Run("Java language level 8", func(t *testing.T) { 1357 // Test with legacy javac -source 1.8 -target 1.8 1358 bp := ` 1359 java_library { 1360 name: "foo", 1361 srcs: ["a.java"], 1362 java_version: "1.8", 1363 } 1364 1365 java_library { 1366 name: "bar", 1367 srcs: ["b.java"], 1368 sdk_version: "none", 1369 system_modules: "none", 1370 patch_module: "java.base", 1371 java_version: "1.8", 1372 } 1373 1374 java_library { 1375 name: "baz", 1376 srcs: ["c.java"], 1377 patch_module: "java.base", 1378 java_version: "1.8", 1379 } 1380 ` 1381 ctx, _ := testJava(t, bp) 1382 1383 checkPatchModuleFlag(t, ctx, "foo", "") 1384 checkPatchModuleFlag(t, ctx, "bar", "") 1385 checkPatchModuleFlag(t, ctx, "baz", "") 1386 }) 1387 1388 t.Run("Java language level 9", func(t *testing.T) { 1389 // Test with default javac -source 9 -target 9 1390 bp := ` 1391 java_library { 1392 name: "foo", 1393 srcs: ["a.java"], 1394 } 1395 1396 java_library { 1397 name: "bar", 1398 srcs: ["b.java"], 1399 sdk_version: "none", 1400 system_modules: "none", 1401 patch_module: "java.base", 1402 } 1403 1404 java_library { 1405 name: "baz", 1406 srcs: [ 1407 "c.java", 1408 // Tests for b/150878007 1409 "dir/d.java", 1410 "dir2/e.java", 1411 "dir2/f.java", 1412 "nested/dir/g.java" 1413 ], 1414 patch_module: "java.base", 1415 } 1416 ` 1417 ctx, _ := testJava(t, bp) 1418 1419 checkPatchModuleFlag(t, ctx, "foo", "") 1420 expected := "java.base=.:out/soong" 1421 checkPatchModuleFlag(t, ctx, "bar", expected) 1422 expected = "java.base=" + strings.Join([]string{ 1423 ".", "out/soong", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":") 1424 checkPatchModuleFlag(t, ctx, "baz", expected) 1425 }) 1426} 1427 1428func TestJavaLibraryWithSystemModules(t *testing.T) { 1429 ctx, _ := testJava(t, ` 1430 java_library { 1431 name: "lib-with-source-system-modules", 1432 srcs: [ 1433 "a.java", 1434 ], 1435 sdk_version: "none", 1436 system_modules: "source-system-modules", 1437 } 1438 1439 java_library { 1440 name: "source-jar", 1441 srcs: [ 1442 "a.java", 1443 ], 1444 } 1445 1446 java_system_modules { 1447 name: "source-system-modules", 1448 libs: ["source-jar"], 1449 } 1450 1451 java_library { 1452 name: "lib-with-prebuilt-system-modules", 1453 srcs: [ 1454 "a.java", 1455 ], 1456 sdk_version: "none", 1457 system_modules: "prebuilt-system-modules", 1458 } 1459 1460 java_import { 1461 name: "prebuilt-jar", 1462 jars: ["a.jar"], 1463 } 1464 1465 java_system_modules_import { 1466 name: "prebuilt-system-modules", 1467 libs: ["prebuilt-jar"], 1468 } 1469 `) 1470 1471 checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") 1472 1473 checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") 1474} 1475 1476func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { 1477 javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") 1478 bootClasspath := javacRule.Args["bootClasspath"] 1479 if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { 1480 t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) 1481 } 1482} 1483 1484func TestAidlExportIncludeDirsFromImports(t *testing.T) { 1485 ctx, _ := testJava(t, ` 1486 java_library { 1487 name: "foo", 1488 srcs: ["aidl/foo/IFoo.aidl"], 1489 libs: ["bar"], 1490 } 1491 1492 java_import { 1493 name: "bar", 1494 jars: ["a.jar"], 1495 aidl: { 1496 export_include_dirs: ["aidl/bar"], 1497 }, 1498 } 1499 `) 1500 1501 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1502 expectedAidlFlag := "-Iaidl/bar" 1503 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1504 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1505 } 1506} 1507 1508func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) { 1509 ctx, _ := testJava(t, ` 1510 java_library { 1511 name: "foo", 1512 srcs: ["aidl/foo/IFoo.aidl"], 1513 aidl: { flags: ["-Werror"], }, 1514 } 1515 `) 1516 1517 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1518 expectedAidlFlag := "-Werror" 1519 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1520 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1521 } 1522} 1523 1524func TestAidlFlagsWithMinSdkVersion(t *testing.T) { 1525 fixture := android.GroupFixturePreparers( 1526 prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})) 1527 1528 for _, tc := range []struct { 1529 name string 1530 sdkVersion string 1531 expected string 1532 }{ 1533 {"default is current", "", "current"}, 1534 {"use sdk_version", `sdk_version: "14"`, "14"}, 1535 {"system_current", `sdk_version: "system_current"`, "current"}, 1536 } { 1537 t.Run(tc.name, func(t *testing.T) { 1538 ctx := fixture.RunTestWithBp(t, ` 1539 java_library { 1540 name: "foo", 1541 srcs: ["aidl/foo/IFoo.aidl"], 1542 `+tc.sdkVersion+` 1543 } 1544 `) 1545 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1546 expectedAidlFlag := "--min_sdk_version=" + tc.expected 1547 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1548 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1549 } 1550 }) 1551 } 1552} 1553 1554func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) { 1555 bpTemplate := ` 1556 droidstubs { 1557 name: "foo-stubs", 1558 srcs: ["foo.aidl"], 1559 %s 1560 system_modules: "none", 1561 } 1562 ` 1563 testCases := []struct { 1564 desc string 1565 sdkVersionBp string 1566 minSdkVersionExpected string 1567 }{ 1568 { 1569 desc: "sdk_version not set, module compiles against private platform APIs", 1570 sdkVersionBp: ``, 1571 minSdkVersionExpected: "10000", 1572 }, 1573 { 1574 desc: "sdk_version set to none, module does not build against an SDK", 1575 sdkVersionBp: `sdk_version: "none",`, 1576 minSdkVersionExpected: "10000", 1577 }, 1578 } 1579 for _, tc := range testCases { 1580 ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp)) 1581 aidlCmd := ctx.ModuleForTests("foo-stubs", "android_common").Rule("aidl").RuleParams.Command 1582 expected := "--min_sdk_version=" + tc.minSdkVersionExpected 1583 android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected) 1584 } 1585} 1586 1587func TestAidlEnforcePermissions(t *testing.T) { 1588 ctx, _ := testJava(t, ` 1589 java_library { 1590 name: "foo", 1591 srcs: ["aidl/foo/IFoo.aidl"], 1592 aidl: { enforce_permissions: true }, 1593 } 1594 `) 1595 1596 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1597 expectedAidlFlag := "-Wmissing-permission-annotation -Werror" 1598 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1599 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1600 } 1601} 1602 1603func TestAidlEnforcePermissionsException(t *testing.T) { 1604 ctx, _ := testJava(t, ` 1605 java_library { 1606 name: "foo", 1607 srcs: ["aidl/foo/IFoo.aidl", "aidl/foo/IFoo2.aidl"], 1608 aidl: { enforce_permissions: true, enforce_permissions_exceptions: ["aidl/foo/IFoo2.aidl"] }, 1609 } 1610 `) 1611 1612 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1613 expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl" 1614 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1615 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1616 } 1617 expectedAidlFlag = "$$FLAGS aidl/foo/IFoo2.aidl" 1618 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1619 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1620 } 1621} 1622 1623func TestDataNativeBinaries(t *testing.T) { 1624 ctx := android.GroupFixturePreparers( 1625 prepareForJavaTest, 1626 android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, ` 1627 java_test_host { 1628 name: "foo", 1629 srcs: ["a.java"], 1630 data_native_bins: ["bin"] 1631 } 1632 1633 cc_binary_host { 1634 name: "bin", 1635 srcs: ["bin.cpp"], 1636 } 1637 `).TestContext 1638 1639 buildOS := ctx.Config().BuildOS.String() 1640 1641 test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 1642 entries := android.AndroidMkEntriesForTest(t, ctx, test)[0] 1643 expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"} 1644 actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] 1645 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual) 1646} 1647 1648func TestDefaultInstallable(t *testing.T) { 1649 ctx, _ := testJava(t, ` 1650 java_test_host { 1651 name: "foo" 1652 } 1653 `) 1654 1655 buildOS := ctx.Config().BuildOS.String() 1656 module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 1657 assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true), 1658 module.properties.Installable) 1659} 1660 1661func TestErrorproneEnabled(t *testing.T) { 1662 ctx, _ := testJava(t, ` 1663 java_library { 1664 name: "foo", 1665 srcs: ["a.java"], 1666 errorprone: { 1667 enabled: true, 1668 }, 1669 } 1670 `) 1671 1672 javac := ctx.ModuleForTests("foo", "android_common").Description("javac") 1673 1674 // Test that the errorprone plugins are passed to javac 1675 expectedSubstring := "-Xplugin:ErrorProne" 1676 if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) { 1677 t.Errorf("expected javacFlags to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"]) 1678 } 1679 1680 // Modules with errorprone { enabled: true } will include errorprone checks 1681 // in the main javac build rule. Only when RUN_ERROR_PRONE is true will 1682 // the explicit errorprone build rule be created. 1683 errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone") 1684 if errorprone.RuleParams.Description != "" { 1685 t.Errorf("expected errorprone build rule to not exist, but it did") 1686 } 1687} 1688 1689func TestErrorproneDisabled(t *testing.T) { 1690 bp := ` 1691 java_library { 1692 name: "foo", 1693 srcs: ["a.java"], 1694 errorprone: { 1695 enabled: false, 1696 }, 1697 } 1698 ` 1699 ctx := android.GroupFixturePreparers( 1700 PrepareForTestWithJavaDefaultModules, 1701 android.FixtureMergeEnv(map[string]string{ 1702 "RUN_ERROR_PRONE": "true", 1703 }), 1704 ).RunTestWithBp(t, bp) 1705 1706 javac := ctx.ModuleForTests("foo", "android_common").Description("javac") 1707 1708 // Test that the errorprone plugins are not passed to javac, like they would 1709 // be if enabled was true. 1710 expectedSubstring := "-Xplugin:ErrorProne" 1711 if strings.Contains(javac.Args["javacFlags"], expectedSubstring) { 1712 t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"]) 1713 } 1714 1715 // Check that no errorprone build rule is created, like there would be 1716 // if enabled was unset and RUN_ERROR_PRONE was true. 1717 errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone") 1718 if errorprone.RuleParams.Description != "" { 1719 t.Errorf("expected errorprone build rule to not exist, but it did") 1720 } 1721} 1722 1723func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) { 1724 bp := ` 1725 java_library { 1726 name: "foo", 1727 srcs: ["a.java"], 1728 } 1729 ` 1730 ctx := android.GroupFixturePreparers( 1731 PrepareForTestWithJavaDefaultModules, 1732 android.FixtureMergeEnv(map[string]string{ 1733 "RUN_ERROR_PRONE": "true", 1734 }), 1735 ).RunTestWithBp(t, bp) 1736 1737 javac := ctx.ModuleForTests("foo", "android_common").Description("javac") 1738 errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone") 1739 1740 // Check that the errorprone plugins are not passed to javac, because they 1741 // will instead be passed to the separate errorprone compilation 1742 expectedSubstring := "-Xplugin:ErrorProne" 1743 if strings.Contains(javac.Args["javacFlags"], expectedSubstring) { 1744 t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"]) 1745 } 1746 1747 // Check that the errorprone plugin is enabled 1748 if !strings.Contains(errorprone.Args["javacFlags"], expectedSubstring) { 1749 t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"]) 1750 } 1751} 1752 1753func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { 1754 testCases := []struct { 1755 dataDeviceBinType string 1756 depCompileMultilib string 1757 variants []string 1758 expectedError string 1759 }{ 1760 { 1761 dataDeviceBinType: "first", 1762 depCompileMultilib: "first", 1763 variants: []string{"android_arm64_armv8-a"}, 1764 }, 1765 { 1766 dataDeviceBinType: "first", 1767 depCompileMultilib: "both", 1768 variants: []string{"android_arm64_armv8-a"}, 1769 }, 1770 { 1771 // this is true because our testing framework is set up with 1772 // Targets ~ [<64bit target>, <32bit target>], where 64bit is "first" 1773 dataDeviceBinType: "first", 1774 depCompileMultilib: "32", 1775 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1776 }, 1777 { 1778 dataDeviceBinType: "first", 1779 depCompileMultilib: "64", 1780 variants: []string{"android_arm64_armv8-a"}, 1781 }, 1782 { 1783 dataDeviceBinType: "both", 1784 depCompileMultilib: "both", 1785 variants: []string{ 1786 "android_arm_armv7-a-neon", 1787 "android_arm64_armv8-a", 1788 }, 1789 }, 1790 { 1791 dataDeviceBinType: "both", 1792 depCompileMultilib: "32", 1793 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1794 }, 1795 { 1796 dataDeviceBinType: "both", 1797 depCompileMultilib: "64", 1798 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1799 }, 1800 { 1801 dataDeviceBinType: "both", 1802 depCompileMultilib: "first", 1803 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1804 }, 1805 { 1806 dataDeviceBinType: "32", 1807 depCompileMultilib: "32", 1808 variants: []string{"android_arm_armv7-a-neon"}, 1809 }, 1810 { 1811 dataDeviceBinType: "32", 1812 depCompileMultilib: "first", 1813 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1814 }, 1815 { 1816 dataDeviceBinType: "32", 1817 depCompileMultilib: "both", 1818 variants: []string{"android_arm_armv7-a-neon"}, 1819 }, 1820 { 1821 dataDeviceBinType: "32", 1822 depCompileMultilib: "64", 1823 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1824 }, 1825 { 1826 dataDeviceBinType: "64", 1827 depCompileMultilib: "64", 1828 variants: []string{"android_arm64_armv8-a"}, 1829 }, 1830 { 1831 dataDeviceBinType: "64", 1832 depCompileMultilib: "both", 1833 variants: []string{"android_arm64_armv8-a"}, 1834 }, 1835 { 1836 dataDeviceBinType: "64", 1837 depCompileMultilib: "first", 1838 variants: []string{"android_arm64_armv8-a"}, 1839 }, 1840 { 1841 dataDeviceBinType: "64", 1842 depCompileMultilib: "32", 1843 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1844 }, 1845 { 1846 dataDeviceBinType: "prefer32", 1847 depCompileMultilib: "32", 1848 variants: []string{"android_arm_armv7-a-neon"}, 1849 }, 1850 { 1851 dataDeviceBinType: "prefer32", 1852 depCompileMultilib: "both", 1853 variants: []string{"android_arm_armv7-a-neon"}, 1854 }, 1855 { 1856 dataDeviceBinType: "prefer32", 1857 depCompileMultilib: "first", 1858 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1859 }, 1860 { 1861 dataDeviceBinType: "prefer32", 1862 depCompileMultilib: "64", 1863 expectedError: `Android.bp:2:3: dependency "bar" of "foo" missing variant`, 1864 }, 1865 } 1866 1867 bpTemplate := ` 1868 java_test_host { 1869 name: "foo", 1870 srcs: ["test.java"], 1871 data_device_bins_%s: ["bar"], 1872 } 1873 1874 cc_binary { 1875 name: "bar", 1876 compile_multilib: "%s", 1877 } 1878 ` 1879 1880 for _, tc := range testCases { 1881 bp := fmt.Sprintf(bpTemplate, tc.dataDeviceBinType, tc.depCompileMultilib) 1882 1883 errorHandler := android.FixtureExpectsNoErrors 1884 if tc.expectedError != "" { 1885 errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError) 1886 } 1887 1888 testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib) 1889 t.Run(testName, func(t *testing.T) { 1890 ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava). 1891 ExtendWithErrorHandler(errorHandler). 1892 RunTestWithBp(t, bp) 1893 if tc.expectedError != "" { 1894 return 1895 } 1896 1897 buildOS := ctx.Config.BuildOS.String() 1898 fooVariant := ctx.ModuleForTests("foo", buildOS+"_common") 1899 fooMod := fooVariant.Module().(*TestHost) 1900 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0] 1901 1902 expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />` 1903 autogen := fooVariant.Rule("autogen") 1904 if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) { 1905 t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig) 1906 } 1907 1908 expectedData := []string{} 1909 for _, variant := range tc.variants { 1910 barVariant := ctx.ModuleForTests("bar", variant) 1911 relocated := barVariant.Output("bar") 1912 expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant) 1913 android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) 1914 1915 expectedData = append(expectedData, fmt.Sprintf("out/soong/.intermediates/bar/%s/bar:bar", variant)) 1916 } 1917 1918 actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] 1919 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData) 1920 }) 1921 } 1922} 1923 1924func TestDeviceBinaryWrapperGeneration(t *testing.T) { 1925 // Scenario 1: java_binary has main_class property in its bp 1926 ctx, _ := testJava(t, ` 1927 java_binary { 1928 name: "foo", 1929 srcs: ["foo.java"], 1930 main_class: "foo.bar.jb", 1931 } 1932 `) 1933 wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_common").AllOutputs()) 1934 if !strings.Contains(wrapperPath, "foo.sh") { 1935 t.Errorf("wrapper file foo.sh is not generated") 1936 } 1937 1938 // Scenario 2: java_binary has neither wrapper nor main_class, its build 1939 // is expected to be failed. 1940 testJavaError(t, "main_class property is required for device binary if no default wrapper is assigned", ` 1941 java_binary { 1942 name: "foo", 1943 srcs: ["foo.java"], 1944 }`) 1945} 1946 1947func TestJavaApiContributionEmptyApiFile(t *testing.T) { 1948 android.GroupFixturePreparers( 1949 prepareForJavaTest, 1950 android.FixtureMergeEnv( 1951 map[string]string{ 1952 "DISABLE_STUB_VALIDATION": "true", 1953 }, 1954 ), 1955 ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( 1956 "Error: foo has an empty api file.", 1957 )).RunTestWithBp(t, ` 1958 java_api_contribution { 1959 name: "foo", 1960 } 1961 java_api_library { 1962 name: "bar", 1963 api_surface: "public", 1964 api_contributions: ["foo"], 1965 stubs_type: "everything", 1966 } 1967 `) 1968} 1969 1970func TestJavaApiLibraryAndProviderLink(t *testing.T) { 1971 provider_bp_a := ` 1972 java_api_contribution { 1973 name: "foo1", 1974 api_file: "current.txt", 1975 api_surface: "public", 1976 } 1977 ` 1978 provider_bp_b := `java_api_contribution { 1979 name: "foo2", 1980 api_file: "current.txt", 1981 api_surface: "public", 1982 } 1983 ` 1984 ctx := android.GroupFixturePreparers( 1985 prepareForJavaTest, 1986 android.FixtureMergeMockFs( 1987 map[string][]byte{ 1988 "a/Android.bp": []byte(provider_bp_a), 1989 "b/Android.bp": []byte(provider_bp_b), 1990 }, 1991 ), 1992 android.FixtureMergeEnv( 1993 map[string]string{ 1994 "DISABLE_STUB_VALIDATION": "true", 1995 }, 1996 ), 1997 ).RunTestWithBp(t, ` 1998 java_api_library { 1999 name: "bar1", 2000 api_surface: "public", 2001 api_contributions: ["foo1"], 2002 stubs_type: "everything", 2003 } 2004 2005 java_api_library { 2006 name: "bar2", 2007 api_surface: "system", 2008 api_contributions: ["foo1", "foo2"], 2009 stubs_type: "everything", 2010 } 2011 `) 2012 2013 testcases := []struct { 2014 moduleName string 2015 sourceTextFileDirs []string 2016 }{ 2017 { 2018 moduleName: "bar1", 2019 sourceTextFileDirs: []string{"a/current.txt"}, 2020 }, 2021 { 2022 moduleName: "bar2", 2023 sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"}, 2024 }, 2025 } 2026 for _, c := range testcases { 2027 m := ctx.ModuleForTests(c.moduleName, "android_common") 2028 manifest := m.Output("metalava.sbox.textproto") 2029 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) 2030 manifestCommand := sboxProto.Commands[0].GetCommand() 2031 sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ") 2032 android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) 2033 } 2034} 2035 2036func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { 2037 provider_bp_a := ` 2038 java_api_contribution { 2039 name: "foo1", 2040 api_file: "current.txt", 2041 api_surface: "public", 2042 } 2043 ` 2044 provider_bp_b := ` 2045 java_api_contribution { 2046 name: "foo2", 2047 api_file: "current.txt", 2048 api_surface: "public", 2049 } 2050 ` 2051 provider_bp_c := ` 2052 java_api_contribution { 2053 name: "foo3", 2054 api_file: "system-current.txt", 2055 api_surface: "system", 2056 } 2057 ` 2058 provider_bp_d := ` 2059 java_api_contribution { 2060 name: "foo4", 2061 api_file: "system-current.txt", 2062 api_surface: "system", 2063 } 2064 ` 2065 ctx := android.GroupFixturePreparers( 2066 prepareForJavaTest, 2067 android.FixtureMergeMockFs( 2068 map[string][]byte{ 2069 "a/Android.bp": []byte(provider_bp_a), 2070 "b/Android.bp": []byte(provider_bp_b), 2071 "c/Android.bp": []byte(provider_bp_c), 2072 "d/Android.bp": []byte(provider_bp_d), 2073 }, 2074 ), 2075 android.FixtureMergeEnv( 2076 map[string]string{ 2077 "DISABLE_STUB_VALIDATION": "true", 2078 }, 2079 ), 2080 ).RunTestWithBp(t, ` 2081 java_defaults { 2082 name: "baz1", 2083 api_surface: "public", 2084 api_contributions: ["foo1", "foo2"], 2085 } 2086 2087 java_defaults { 2088 name: "baz2", 2089 api_surface: "system", 2090 api_contributions: ["foo3"], 2091 } 2092 2093 java_api_library { 2094 name: "bar1", 2095 api_surface: "public", 2096 api_contributions: ["foo1"], 2097 stubs_type: "everything", 2098 } 2099 2100 java_api_library { 2101 name: "bar2", 2102 api_surface: "public", 2103 defaults:["baz1"], 2104 stubs_type: "everything", 2105 } 2106 2107 java_api_library { 2108 name: "bar3", 2109 api_surface: "system", 2110 defaults:["baz1", "baz2"], 2111 api_contributions: ["foo4"], 2112 stubs_type: "everything", 2113 } 2114 `) 2115 2116 testcases := []struct { 2117 moduleName string 2118 sourceTextFileDirs []string 2119 }{ 2120 { 2121 moduleName: "bar1", 2122 sourceTextFileDirs: []string{"a/current.txt"}, 2123 }, 2124 { 2125 moduleName: "bar2", 2126 sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"}, 2127 }, 2128 { 2129 moduleName: "bar3", 2130 // API text files need to be sorted from the narrower api scope to the wider api scope 2131 sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"}, 2132 }, 2133 } 2134 for _, c := range testcases { 2135 m := ctx.ModuleForTests(c.moduleName, "android_common") 2136 manifest := m.Output("metalava.sbox.textproto") 2137 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) 2138 manifestCommand := sboxProto.Commands[0].GetCommand() 2139 sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ") 2140 android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) 2141 } 2142} 2143 2144func TestJavaApiLibraryJarGeneration(t *testing.T) { 2145 provider_bp_a := ` 2146 java_api_contribution { 2147 name: "foo1", 2148 api_file: "current.txt", 2149 api_surface: "public", 2150 } 2151 ` 2152 provider_bp_b := ` 2153 java_api_contribution { 2154 name: "foo2", 2155 api_file: "current.txt", 2156 api_surface: "public", 2157 } 2158 ` 2159 ctx := android.GroupFixturePreparers( 2160 prepareForJavaTest, 2161 android.FixtureMergeMockFs( 2162 map[string][]byte{ 2163 "a/Android.bp": []byte(provider_bp_a), 2164 "b/Android.bp": []byte(provider_bp_b), 2165 }, 2166 ), 2167 android.FixtureMergeEnv( 2168 map[string]string{ 2169 "DISABLE_STUB_VALIDATION": "true", 2170 }, 2171 ), 2172 ).RunTestWithBp(t, ` 2173 java_api_library { 2174 name: "bar1", 2175 api_surface: "public", 2176 api_contributions: ["foo1"], 2177 stubs_type: "everything", 2178 } 2179 2180 java_api_library { 2181 name: "bar2", 2182 api_surface: "system", 2183 api_contributions: ["foo1", "foo2"], 2184 stubs_type: "everything", 2185 } 2186 `) 2187 2188 testcases := []struct { 2189 moduleName string 2190 outputJarName string 2191 }{ 2192 { 2193 moduleName: "bar1", 2194 outputJarName: "bar1/bar1.jar", 2195 }, 2196 { 2197 moduleName: "bar2", 2198 outputJarName: "bar2/bar2.jar", 2199 }, 2200 } 2201 for _, c := range testcases { 2202 m := ctx.ModuleForTests(c.moduleName, "android_common") 2203 outputs := fmt.Sprint(m.AllOutputs()) 2204 if !strings.Contains(outputs, c.outputJarName) { 2205 t.Errorf("Module output does not contain expected jar %s", c.outputJarName) 2206 } 2207 } 2208} 2209 2210func TestJavaApiLibraryLibsLink(t *testing.T) { 2211 provider_bp_a := ` 2212 java_api_contribution { 2213 name: "foo1", 2214 api_file: "current.txt", 2215 api_surface: "public", 2216 } 2217 ` 2218 provider_bp_b := ` 2219 java_api_contribution { 2220 name: "foo2", 2221 api_file: "current.txt", 2222 api_surface: "public", 2223 } 2224 ` 2225 lib_bp_a := ` 2226 java_library { 2227 name: "lib1", 2228 srcs: ["Lib.java"], 2229 } 2230 ` 2231 lib_bp_b := ` 2232 java_library { 2233 name: "lib2", 2234 srcs: ["Lib.java"], 2235 } 2236 ` 2237 2238 ctx := android.GroupFixturePreparers( 2239 prepareForJavaTest, 2240 android.FixtureMergeMockFs( 2241 map[string][]byte{ 2242 "a/Android.bp": []byte(provider_bp_a), 2243 "b/Android.bp": []byte(provider_bp_b), 2244 "c/Android.bp": []byte(lib_bp_a), 2245 "c/Lib.java": {}, 2246 "d/Android.bp": []byte(lib_bp_b), 2247 "d/Lib.java": {}, 2248 }, 2249 ), 2250 android.FixtureMergeEnv( 2251 map[string]string{ 2252 "DISABLE_STUB_VALIDATION": "true", 2253 }, 2254 ), 2255 ).RunTestWithBp(t, ` 2256 java_api_library { 2257 name: "bar1", 2258 api_surface: "public", 2259 api_contributions: ["foo1"], 2260 libs: ["lib1"], 2261 stubs_type: "everything", 2262 } 2263 2264 java_api_library { 2265 name: "bar2", 2266 api_surface: "system", 2267 api_contributions: ["foo1", "foo2"], 2268 libs: ["lib1", "lib2", "bar1"], 2269 stubs_type: "everything", 2270 } 2271 `) 2272 2273 testcases := []struct { 2274 moduleName string 2275 classPathJarNames []string 2276 }{ 2277 { 2278 moduleName: "bar1", 2279 classPathJarNames: []string{"lib1.jar"}, 2280 }, 2281 { 2282 moduleName: "bar2", 2283 classPathJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"}, 2284 }, 2285 } 2286 for _, c := range testcases { 2287 m := ctx.ModuleForTests(c.moduleName, "android_common") 2288 javacRules := m.Rule("javac") 2289 classPathArgs := javacRules.Args["classpath"] 2290 for _, jarName := range c.classPathJarNames { 2291 if !strings.Contains(classPathArgs, jarName) { 2292 t.Errorf("Module output does not contain expected jar %s", jarName) 2293 } 2294 } 2295 } 2296} 2297 2298func TestJavaApiLibraryStaticLibsLink(t *testing.T) { 2299 provider_bp_a := ` 2300 java_api_contribution { 2301 name: "foo1", 2302 api_file: "current.txt", 2303 api_surface: "public", 2304 } 2305 ` 2306 provider_bp_b := ` 2307 java_api_contribution { 2308 name: "foo2", 2309 api_file: "current.txt", 2310 api_surface: "public", 2311 } 2312 ` 2313 lib_bp_a := ` 2314 java_library { 2315 name: "lib1", 2316 srcs: ["Lib.java"], 2317 } 2318 ` 2319 lib_bp_b := ` 2320 java_library { 2321 name: "lib2", 2322 srcs: ["Lib.java"], 2323 } 2324 ` 2325 2326 ctx := android.GroupFixturePreparers( 2327 prepareForJavaTest, 2328 android.FixtureMergeMockFs( 2329 map[string][]byte{ 2330 "a/Android.bp": []byte(provider_bp_a), 2331 "b/Android.bp": []byte(provider_bp_b), 2332 "c/Android.bp": []byte(lib_bp_a), 2333 "c/Lib.java": {}, 2334 "d/Android.bp": []byte(lib_bp_b), 2335 "d/Lib.java": {}, 2336 }, 2337 ), 2338 android.FixtureMergeEnv( 2339 map[string]string{ 2340 "DISABLE_STUB_VALIDATION": "true", 2341 }, 2342 ), 2343 ).RunTestWithBp(t, ` 2344 java_api_library { 2345 name: "bar1", 2346 api_surface: "public", 2347 api_contributions: ["foo1"], 2348 static_libs: ["lib1"], 2349 stubs_type: "everything", 2350 } 2351 2352 java_api_library { 2353 name: "bar2", 2354 api_surface: "system", 2355 api_contributions: ["foo1", "foo2"], 2356 static_libs: ["lib1", "lib2", "bar1"], 2357 stubs_type: "everything", 2358 } 2359 `) 2360 2361 testcases := []struct { 2362 moduleName string 2363 staticLibJarNames []string 2364 }{ 2365 { 2366 moduleName: "bar1", 2367 staticLibJarNames: []string{"lib1.jar"}, 2368 }, 2369 { 2370 moduleName: "bar2", 2371 staticLibJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"}, 2372 }, 2373 } 2374 for _, c := range testcases { 2375 m := ctx.ModuleForTests(c.moduleName, "android_common") 2376 mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command 2377 for _, jarName := range c.staticLibJarNames { 2378 if !strings.Contains(mergeZipsCommand, jarName) { 2379 t.Errorf("merge_zips command does not contain expected jar %s", jarName) 2380 } 2381 } 2382 } 2383} 2384 2385func TestTransitiveSrcFiles(t *testing.T) { 2386 ctx, _ := testJava(t, ` 2387 java_library { 2388 name: "a", 2389 srcs: ["a.java"], 2390 } 2391 java_library { 2392 name: "b", 2393 srcs: ["b.java"], 2394 } 2395 java_library { 2396 name: "c", 2397 srcs: ["c.java"], 2398 libs: ["a"], 2399 static_libs: ["b"], 2400 } 2401 `) 2402 c := ctx.ModuleForTests("c", "android_common").Module() 2403 javaInfo, _ := android.OtherModuleProvider(ctx, c, JavaInfoProvider) 2404 transitiveSrcFiles := android.Paths(javaInfo.TransitiveSrcFiles.ToList()) 2405 android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings()) 2406} 2407 2408func TestTradefedOptions(t *testing.T) { 2409 result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` 2410java_test_host { 2411 name: "foo", 2412 test_options: { 2413 tradefed_options: [ 2414 { 2415 name: "exclude-path", 2416 value: "org/apache" 2417 } 2418 ] 2419 } 2420} 2421`) 2422 2423 buildOS := result.Config.BuildOS.String() 2424 args := result.ModuleForTests("foo", buildOS+"_common"). 2425 Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args 2426 expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />") 2427 if args["extraConfigs"] != expected { 2428 t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"]) 2429 } 2430} 2431 2432func TestTestRunnerOptions(t *testing.T) { 2433 result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` 2434java_test_host { 2435 name: "foo", 2436 test_options: { 2437 test_runner_options: [ 2438 { 2439 name: "test-timeout", 2440 value: "10m" 2441 } 2442 ] 2443 } 2444} 2445`) 2446 2447 buildOS := result.Config.BuildOS.String() 2448 args := result.ModuleForTests("foo", buildOS+"_common"). 2449 Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args 2450 expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n ") 2451 if args["extraTestRunnerConfigs"] != expected { 2452 t.Errorf("Expected args[\"extraTestRunnerConfigs\"] to equal %q, was %q", expected, args["extraTestRunnerConfigs"]) 2453 } 2454} 2455 2456func TestJavaLibraryWithResourcesStem(t *testing.T) { 2457 ctx, _ := testJavaWithFS(t, ` 2458 java_library { 2459 name: "foo", 2460 java_resource_dirs: ["test-jar"], 2461 stem: "test", 2462 } 2463 `, 2464 map[string][]byte{ 2465 "test-jar/test/resource.txt": nil, 2466 }) 2467 2468 m := ctx.ModuleForTests("foo", "android_common") 2469 outputs := fmt.Sprint(m.AllOutputs()) 2470 if !strings.Contains(outputs, "test.jar") { 2471 t.Errorf("Module output does not contain expected jar %s", "test.jar") 2472 } 2473} 2474 2475func TestHeadersOnly(t *testing.T) { 2476 ctx, _ := testJava(t, ` 2477 java_library { 2478 name: "foo", 2479 srcs: ["a.java"], 2480 headers_only: true, 2481 } 2482 `) 2483 2484 turbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine") 2485 if len(turbine.Inputs) != 1 || turbine.Inputs[0].String() != "a.java" { 2486 t.Errorf(`foo inputs %v != ["a.java"]`, turbine.Inputs) 2487 } 2488 2489 javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac") 2490 android.AssertDeepEquals(t, "javac rule", nil, javac.Rule) 2491} 2492 2493func TestJavaApiContributionImport(t *testing.T) { 2494 ctx := android.GroupFixturePreparers( 2495 prepareForJavaTest, 2496 android.FixtureMergeEnv( 2497 map[string]string{ 2498 "DISABLE_STUB_VALIDATION": "true", 2499 }, 2500 ), 2501 ).RunTestWithBp(t, ` 2502 java_api_library { 2503 name: "foo", 2504 api_contributions: ["bar"], 2505 stubs_type: "everything", 2506 } 2507 java_api_contribution_import { 2508 name: "bar", 2509 api_file: "current.txt", 2510 api_surface: "public", 2511 } 2512 `) 2513 m := ctx.ModuleForTests("foo", "android_common") 2514 manifest := m.Output("metalava.sbox.textproto") 2515 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) 2516 manifestCommand := sboxProto.Commands[0].GetCommand() 2517 sourceFilesFlag := "--source-files current.txt" 2518 android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) 2519} 2520 2521func TestJavaApiLibraryApiFilesSorting(t *testing.T) { 2522 ctx, _ := testJava(t, ` 2523 java_api_library { 2524 name: "foo", 2525 api_contributions: [ 2526 "system-server-api-stubs-docs-non-updatable.api.contribution", 2527 "test-api-stubs-docs-non-updatable.api.contribution", 2528 "system-api-stubs-docs-non-updatable.api.contribution", 2529 "module-lib-api-stubs-docs-non-updatable.api.contribution", 2530 "api-stubs-docs-non-updatable.api.contribution", 2531 ], 2532 stubs_type: "everything", 2533 } 2534 `) 2535 m := ctx.ModuleForTests("foo", "android_common") 2536 manifest := m.Output("metalava.sbox.textproto") 2537 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest) 2538 manifestCommand := sboxProto.Commands[0].GetCommand() 2539 2540 // Api files are sorted from the narrowest api scope to the widest api scope. 2541 // test api and module lib api surface do not have subset/superset relationship, 2542 // but they will never be passed as inputs at the same time. 2543 sourceFilesFlag := "--source-files default/java/api/current.txt " + 2544 "default/java/api/system-current.txt default/java/api/test-current.txt " + 2545 "default/java/api/module-lib-current.txt default/java/api/system-server-current.txt" 2546 android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag) 2547} 2548 2549func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { 2550 result := android.GroupFixturePreparers( 2551 prepareForJavaTest, 2552 PrepareForTestWithJavaSdkLibraryFiles, 2553 FixtureWithLastReleaseApis("foo"), 2554 android.FixtureMergeMockFs( 2555 map[string][]byte{ 2556 "A.java": nil, 2557 }, 2558 ), 2559 ).RunTestWithBp(t, ` 2560 java_library { 2561 name: "bar", 2562 srcs: ["a.java"], 2563 } 2564 java_system_modules { 2565 name: "baz", 2566 libs: ["bar"], 2567 } 2568 java_sdk_library { 2569 name: "foo", 2570 srcs: ["A.java"], 2571 system_modules: "baz", 2572 } 2573 `) 2574 2575 checkBootClasspathForLibWithSystemModule(t, result.TestContext, apiScopePublic.apiLibraryModuleName("foo"), "/bar.jar") 2576} 2577 2578func TestApiLibraryDroidstubsDependency(t *testing.T) { 2579 result := android.GroupFixturePreparers( 2580 prepareForJavaTest, 2581 PrepareForTestWithJavaSdkLibraryFiles, 2582 FixtureWithLastReleaseApis("foo"), 2583 android.FixtureMergeMockFs( 2584 map[string][]byte{ 2585 "A.java": nil, 2586 }, 2587 ), 2588 ).RunTestWithBp(t, ` 2589 java_api_library { 2590 name: "foo", 2591 api_contributions: [ 2592 "api-stubs-docs-non-updatable.api.contribution", 2593 ], 2594 enable_validation: true, 2595 stubs_type: "everything", 2596 } 2597 java_api_library { 2598 name: "bar", 2599 api_contributions: [ 2600 "api-stubs-docs-non-updatable.api.contribution", 2601 ], 2602 enable_validation: false, 2603 stubs_type: "everything", 2604 } 2605 `) 2606 2607 currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp" 2608 foo := result.ModuleForTests("foo", "android_common").Module().(*ApiLibrary) 2609 fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ") 2610 bar := result.ModuleForTests("bar", "android_common").Module().(*ApiLibrary) 2611 barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ") 2612 android.AssertStringDoesContain(t, 2613 "Module expected to have validation", 2614 fooValidationPathsString, 2615 currentApiTimestampPath, 2616 ) 2617 android.AssertStringDoesNotContain(t, 2618 "Module expected to not have validation", 2619 barValidationPathsString, 2620 currentApiTimestampPath, 2621 ) 2622} 2623 2624func TestDisableFromTextStubForCoverageBuild(t *testing.T) { 2625 result := android.GroupFixturePreparers( 2626 prepareForJavaTest, 2627 PrepareForTestWithJavaSdkLibraryFiles, 2628 PrepareForTestWithJacocoInstrumentation, 2629 FixtureWithLastReleaseApis("foo"), 2630 android.FixtureModifyConfig(func(config android.Config) { 2631 config.SetBuildFromTextStub(true) 2632 }), 2633 android.FixtureModifyEnv(func(env map[string]string) { 2634 env["EMMA_INSTRUMENT"] = "true" 2635 }), 2636 ).RunTestWithBp(t, ` 2637 java_sdk_library { 2638 name: "foo", 2639 srcs: ["A.java"], 2640 } 2641 `) 2642 android.AssertBoolEquals(t, "stub module expected to depend on from-source stub", 2643 true, CheckModuleHasDependency(t, result.TestContext, 2644 apiScopePublic.stubsLibraryModuleName("foo"), "android_common", 2645 apiScopePublic.sourceStubsLibraryModuleName("foo"))) 2646 2647 android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub", 2648 false, CheckModuleHasDependency(t, result.TestContext, 2649 apiScopePublic.stubsLibraryModuleName("foo"), "android_common", 2650 apiScopePublic.apiLibraryModuleName("foo"))) 2651} 2652 2653func TestMultiplePrebuilts(t *testing.T) { 2654 bp := ` 2655 // an rdep 2656 java_library { 2657 name: "foo", 2658 libs: ["bar"], 2659 } 2660 2661 // multiple variations of dep 2662 // source 2663 java_library { 2664 name: "bar", 2665 srcs: ["bar.java"], 2666 } 2667 // prebuilt "v1" 2668 java_import { 2669 name: "bar", 2670 jars: ["bar.jar"], 2671 } 2672 // prebuilt "v2" 2673 java_import { 2674 name: "bar.v2", 2675 source_module_name: "bar", 2676 jars: ["bar.v1.jar"], 2677 } 2678 2679 // selectors 2680 apex_contributions { 2681 name: "myapex_contributions", 2682 contents: ["%v"], 2683 } 2684 ` 2685 hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool { 2686 t.Helper() 2687 var found bool 2688 ctx.VisitDirectDeps(m, func(dep blueprint.Module) { 2689 if dep == wantDep { 2690 found = true 2691 } 2692 }) 2693 return found 2694 } 2695 2696 hasFileWithStem := func(m android.TestingModule, stem string) bool { 2697 t.Helper() 2698 for _, o := range m.AllOutputs() { 2699 _, file := filepath.Split(o) 2700 if file == stem+".jar" { 2701 return true 2702 } 2703 } 2704 return false 2705 } 2706 2707 testCases := []struct { 2708 desc string 2709 selectedDependencyName string 2710 expectedDependencyName string 2711 }{ 2712 { 2713 desc: "Source library is selected using apex_contributions", 2714 selectedDependencyName: "bar", 2715 expectedDependencyName: "bar", 2716 }, 2717 { 2718 desc: "Prebuilt library v1 is selected using apex_contributions", 2719 selectedDependencyName: "prebuilt_bar", 2720 expectedDependencyName: "prebuilt_bar", 2721 }, 2722 { 2723 desc: "Prebuilt library v2 is selected using apex_contributions", 2724 selectedDependencyName: "prebuilt_bar.v2", 2725 expectedDependencyName: "prebuilt_bar.v2", 2726 }, 2727 } 2728 2729 for _, tc := range testCases { 2730 ctx := android.GroupFixturePreparers( 2731 prepareForJavaTest, 2732 android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"), 2733 ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName)) 2734 2735 // check that rdep gets the correct variation of dep 2736 foo := ctx.ModuleForTests("foo", "android_common") 2737 expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common") 2738 android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module())) 2739 2740 // check that output file of dep is always bar.jar 2741 // The filename should be agnostic to source/prebuilt/prebuilt_version 2742 android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar")) 2743 2744 // check LOCAL_MODULE of the selected module name 2745 // the prebuilt should have the same LOCAL_MODULE when exported to make 2746 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0] 2747 android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0]) 2748 } 2749} 2750 2751func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) { 2752 bp := ` 2753 // multiple variations of platform_compat_config 2754 // source 2755 platform_compat_config { 2756 name: "myconfig", 2757 } 2758 // prebuilt "v1" 2759 prebuilt_platform_compat_config { 2760 name: "myconfig", 2761 metadata: "myconfig.xml", 2762 } 2763 // prebuilt "v2" 2764 prebuilt_platform_compat_config { 2765 name: "myconfig.v2", 2766 source_module_name: "myconfig", // without source_module_name, the singleton will merge two .xml files 2767 metadata: "myconfig.v2.xml", 2768 } 2769 2770 // selectors 2771 apex_contributions { 2772 name: "myapex_contributions", 2773 contents: ["%v"], 2774 } 2775 ` 2776 testCases := []struct { 2777 desc string 2778 selectedDependencyName string 2779 expectedPlatformCompatConfigXml string 2780 }{ 2781 { 2782 desc: "Source platform_compat_config is selected using apex_contributions", 2783 selectedDependencyName: "myconfig", 2784 expectedPlatformCompatConfigXml: "out/soong/.intermediates/myconfig/android_common/myconfig_meta.xml", 2785 }, 2786 { 2787 desc: "Prebuilt platform_compat_config v1 is selected using apex_contributions", 2788 selectedDependencyName: "prebuilt_myconfig", 2789 expectedPlatformCompatConfigXml: "myconfig.xml", 2790 }, 2791 { 2792 desc: "Prebuilt platform_compat_config v2 is selected using apex_contributions", 2793 selectedDependencyName: "prebuilt_myconfig.v2", 2794 expectedPlatformCompatConfigXml: "myconfig.v2.xml", 2795 }, 2796 } 2797 2798 for _, tc := range testCases { 2799 ctx := android.GroupFixturePreparers( 2800 prepareForJavaTest, 2801 PrepareForTestWithPlatformCompatConfig, 2802 android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"), 2803 ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName)) 2804 2805 mergedGlobalConfig := ctx.SingletonForTests("platform_compat_config_singleton").Output("compat_config/merged_compat_config.xml") 2806 android.AssertIntEquals(t, "The merged compat config file should only have a single dependency", 1, len(mergedGlobalConfig.Implicits)) 2807 android.AssertStringEquals(t, "The merged compat config file is missing the appropriate platform compat config", mergedGlobalConfig.Implicits[0].String(), tc.expectedPlatformCompatConfigXml) 2808 } 2809} 2810 2811func TestApiLibraryAconfigDeclarations(t *testing.T) { 2812 result := android.GroupFixturePreparers( 2813 prepareForJavaTest, 2814 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 2815 }), 2816 android.FixtureMergeMockFs(map[string][]byte{ 2817 "a/A.java": nil, 2818 "a/current.txt": nil, 2819 "a/removed.txt": nil, 2820 }), 2821 ).RunTestWithBp(t, ` 2822 aconfig_declarations { 2823 name: "bar", 2824 package: "com.example.package", 2825 container: "com.android.foo", 2826 srcs: [ 2827 "bar.aconfig", 2828 ], 2829 } 2830 java_api_contribution { 2831 name: "baz", 2832 api_file: "a/current.txt", 2833 api_surface: "public", 2834 } 2835 java_api_library { 2836 name: "foo", 2837 api_surface: "public", 2838 api_contributions: [ 2839 "baz", 2840 ], 2841 aconfig_declarations: [ 2842 "bar", 2843 ], 2844 stubs_type: "exportable", 2845 enable_validation: false, 2846 } 2847 `) 2848 2849 // Check if java_api_library depends on aconfig_declarations 2850 android.AssertBoolEquals(t, "foo expected to depend on bar", 2851 CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true) 2852 2853 m := result.ModuleForTests("foo", "android_common") 2854 android.AssertStringDoesContain(t, "foo generates revert annotations file", 2855 strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") 2856 2857 // revert-annotations.txt passed to exportable stubs generation metalava command 2858 manifest := m.Output("metalava.sbox.textproto") 2859 cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) 2860 android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") 2861} 2862 2863func TestTestOnly(t *testing.T) { 2864 t.Parallel() 2865 ctx := android.GroupFixturePreparers( 2866 prepareForJavaTest, 2867 ).RunTestWithBp(t, ` 2868 // These should be test-only 2869 java_library { 2870 name: "lib1-test-only", 2871 srcs: ["a.java"], 2872 test_only: true, 2873 } 2874 java_test { 2875 name: "java-test", 2876 } 2877 java_test_host { 2878 name: "java-test-host", 2879 } 2880 java_test_helper_library { 2881 name: "helper-library", 2882 } 2883 java_binary { 2884 name: "java-data-binary", 2885 srcs: ["foo.java"], 2886 main_class: "foo.bar.jb", 2887 test_only: true, 2888 } 2889 2890 // These are NOT 2891 java_library { 2892 name: "lib2-app", 2893 srcs: ["b.java"], 2894 } 2895 java_import { 2896 name: "bar", 2897 jars: ["bar.jar"], 2898 } 2899 java_binary { 2900 name: "java-binary", 2901 srcs: ["foo.java"], 2902 main_class: "foo.bar.jb", 2903 } 2904 `) 2905 2906 expectedTestOnlyModules := []string{ 2907 "lib1-test-only", 2908 "java-test", 2909 "java-test-host", 2910 "helper-library", 2911 "java-data-binary", 2912 } 2913 expectedTopLevelTests := []string{ 2914 "java-test", 2915 "java-test-host", 2916 } 2917 assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests) 2918} 2919 2920// Don't allow setting test-only on things that are always tests or never tests. 2921func TestInvalidTestOnlyTargets(t *testing.T) { 2922 testCases := []string{ 2923 ` java_test { name: "java-test", test_only: true, srcs: ["foo.java"], } `, 2924 ` java_test_host { name: "java-test-host", test_only: true, srcs: ["foo.java"], } `, 2925 ` java_test_import { name: "java-test-import", test_only: true, } `, 2926 ` java_api_library { name: "java-api-library", test_only: true, } `, 2927 ` java_test_helper_library { name: "test-help-lib", test_only: true, } `, 2928 ` java_defaults { name: "java-defaults", test_only: true, } `, 2929 } 2930 2931 for i, bp := range testCases { 2932 android.GroupFixturePreparers(prepareForJavaTest). 2933 ExtendWithErrorHandler( 2934 expectOneError("unrecognized property \"test_only\"", 2935 fmt.Sprintf("testcase: %d", i))). 2936 RunTestWithBp(t, bp) 2937 } 2938} 2939 2940// Expect exactly one that matches 'expected'. 2941// Append 'msg' to the Errorf that printed. 2942func expectOneError(expected string, msg string) android.FixtureErrorHandler { 2943 return android.FixtureCustomErrorHandler(func(t *testing.T, result *android.TestResult) { 2944 t.Helper() 2945 if len(result.Errs) != 1 { 2946 t.Errorf("Expected exactly one error, but found: %d when setting test_only on: %s", len(result.Errs), msg) 2947 return 2948 } 2949 actualErrMsg := result.Errs[0].Error() 2950 if !strings.Contains(actualErrMsg, expected) { 2951 t.Errorf("Different error than expected. Received: [%v] on %s expected: %s", actualErrMsg, msg, expected) 2952 } 2953 }) 2954} 2955 2956func TestJavaLibHostWithStem(t *testing.T) { 2957 ctx, _ := testJava(t, ` 2958 java_library_host { 2959 name: "foo", 2960 srcs: ["a.java"], 2961 stem: "foo-new", 2962 } 2963 `) 2964 2965 buildOS := ctx.Config().BuildOS.String() 2966 foo := ctx.ModuleForTests("foo", buildOS+"_common") 2967 2968 outputs := fmt.Sprint(foo.AllOutputs()) 2969 if !strings.Contains(outputs, "foo-new.jar") { 2970 t.Errorf("Module output does not contain expected jar %s", "foo-new.jar") 2971 } 2972} 2973 2974func TestJavaLibWithStem(t *testing.T) { 2975 ctx, _ := testJava(t, ` 2976 java_library { 2977 name: "foo", 2978 srcs: ["a.java"], 2979 stem: "foo-new", 2980 } 2981 `) 2982 2983 foo := ctx.ModuleForTests("foo", "android_common") 2984 2985 outputs := fmt.Sprint(foo.AllOutputs()) 2986 if !strings.Contains(outputs, "foo-new.jar") { 2987 t.Errorf("Module output does not contain expected jar %s", "foo-new.jar") 2988 } 2989} 2990 2991func TestJavaLibraryOutputFilesRel(t *testing.T) { 2992 result := android.GroupFixturePreparers( 2993 PrepareForTestWithJavaDefaultModules, 2994 ).RunTestWithBp(t, ` 2995 java_library { 2996 name: "foo", 2997 srcs: ["a.java"], 2998 } 2999 3000 java_import { 3001 name: "bar", 3002 jars: ["bar.aar"], 3003 3004 } 3005 3006 java_import { 3007 name: "baz", 3008 jars: ["baz.aar"], 3009 static_libs: ["bar"], 3010 } 3011 `) 3012 3013 foo := result.ModuleForTests("foo", "android_common") 3014 bar := result.ModuleForTests("bar", "android_common") 3015 baz := result.ModuleForTests("baz", "android_common") 3016 3017 fooOutputPaths := foo.OutputFiles(result.TestContext, t, "") 3018 barOutputPaths := bar.OutputFiles(result.TestContext, t, "") 3019 bazOutputPaths := baz.OutputFiles(result.TestContext, t, "") 3020 3021 android.AssertPathsRelativeToTopEquals(t, "foo output path", 3022 []string{"out/soong/.intermediates/foo/android_common/javac/foo.jar"}, fooOutputPaths) 3023 android.AssertPathsRelativeToTopEquals(t, "bar output path", 3024 []string{"out/soong/.intermediates/bar/android_common/combined/bar.jar"}, barOutputPaths) 3025 android.AssertPathsRelativeToTopEquals(t, "baz output path", 3026 []string{"out/soong/.intermediates/baz/android_common/combined/baz.jar"}, bazOutputPaths) 3027 3028 android.AssertStringEquals(t, "foo relative output path", 3029 "foo.jar", fooOutputPaths[0].Rel()) 3030 android.AssertStringEquals(t, "bar relative output path", 3031 "bar.jar", barOutputPaths[0].Rel()) 3032 android.AssertStringEquals(t, "baz relative output path", 3033 "baz.jar", bazOutputPaths[0].Rel()) 3034} 3035 3036func TestCoverage(t *testing.T) { 3037 result := android.GroupFixturePreparers( 3038 PrepareForTestWithJavaDefaultModules, 3039 prepareForTestWithFrameworkJacocoInstrumentation, 3040 PrepareForTestWithTransitiveClasspathEnabled, 3041 ).RunTestWithBp(t, ` 3042 android_app { 3043 name: "foo", 3044 srcs: ["foo.java"], 3045 static_libs: ["android.car"], 3046 platform_apis: true, 3047 } 3048 3049 // A library in InstrumentFrameworkModules 3050 java_library { 3051 name: "android.car", 3052 srcs: ["android.car.java"], 3053 installable: true, 3054 } 3055 `) 3056 3057 foo := result.ModuleForTests("foo", "android_common") 3058 androidCar := result.ModuleForTests("android.car", "android_common") 3059 3060 fooJacoco := foo.Rule("jacoco") 3061 fooCombine := foo.Description("for javac") 3062 3063 androidCarJacoco := androidCar.Rule("jacoco") 3064 androidCarJavac := androidCar.Rule("javac") 3065 3066 android.AssertStringEquals(t, "foo instrumentation rule inputs", fooJacoco.Input.String(), fooCombine.Output.String()) 3067 android.AssertStringEquals(t, "android.car instrumentation rule inputs", androidCarJacoco.Input.String(), androidCarJavac.Output.String()) 3068 3069 // The input to instrumentation for the `foo` app contains the non-instrumented android.car classes. 3070 android.AssertStringListContains(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJavac.Output.String()) 3071 android.AssertStringListDoesNotContain(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJacoco.Output.String()) 3072} 3073 3074func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTestOnly []string, expectedTopLevel []string) { 3075 t.Helper() 3076 actualTrueModules := []string{} 3077 actualTopLevelTests := []string{} 3078 addActuals := func(m blueprint.Module, key blueprint.ProviderKey[android.TestModuleInformation]) { 3079 if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, key); ok { 3080 if provider.TestOnly { 3081 actualTrueModules = append(actualTrueModules, m.Name()) 3082 } 3083 if provider.TopLevelTarget { 3084 actualTopLevelTests = append(actualTopLevelTests, m.Name()) 3085 } 3086 } 3087 } 3088 3089 ctx.VisitAllModules(func(m blueprint.Module) { 3090 addActuals(m, android.TestOnlyProviderKey) 3091 3092 }) 3093 3094 notEqual, left, right := android.ListSetDifference(expectedTestOnly, actualTrueModules) 3095 if notEqual { 3096 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right) 3097 } 3098 3099 notEqual, left, right = android.ListSetDifference(expectedTopLevel, actualTopLevelTests) 3100 if notEqual { 3101 t.Errorf("top-level: Expected but not found: %v, Found but not expected: %v", left, right) 3102 } 3103} 3104 3105// Test that a dependency edge is created to the matching variant of a native library listed in `jni_libs` of java_binary 3106func TestNativeRequiredDepOfJavaBinary(t *testing.T) { 3107 findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module { 3108 var ret []blueprint.Module 3109 ctx.VisitDirectDeps(module, func(dep blueprint.Module) { 3110 if dep.Name() == depName { 3111 ret = append(ret, dep) 3112 } 3113 }) 3114 return ret 3115 } 3116 3117 bp := cc.GatherRequiredDepsForTest(android.Android) + ` 3118java_binary { 3119 name: "myjavabin", 3120 main_class: "com.android.MyJava", 3121 jni_libs: ["mynativelib"], 3122} 3123cc_library_shared { 3124 name: "mynativelib", 3125} 3126` 3127 res, _ := testJava(t, bp) 3128 deps := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib") 3129 android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps)) 3130} 3131