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 "strconv" 24 "strings" 25 "testing" 26 27 "github.com/google/blueprint/proptools" 28 29 "android/soong/android" 30 "android/soong/cc" 31 "android/soong/dexpreopt" 32 "android/soong/genrule" 33 "android/soong/python" 34) 35 36// Legacy preparer used for running tests within the java package. 37// 38// This includes everything that was needed to run any test in the java package prior to the 39// introduction of the test fixtures. Tests that are being converted to use fixtures directly 40// rather than through the testJava...() methods should avoid using this and instead use the 41// various preparers directly, using android.GroupFixturePreparers(...) to group them when 42// necessary. 43// 44// deprecated 45var prepareForJavaTest = android.GroupFixturePreparers( 46 genrule.PrepareForTestWithGenRuleBuildComponents, 47 // Get the CC build components but not default modules. 48 cc.PrepareForTestWithCcBuildComponents, 49 // Include all the default java modules. 50 PrepareForTestWithJavaDefaultModules, 51 PrepareForTestWithOverlayBuildComponents, 52 python.PrepareForTestWithPythonBuildComponents, 53 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { 54 ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory) 55 }), 56 PrepareForTestWithDexpreopt, 57) 58 59func TestMain(m *testing.M) { 60 os.Exit(m.Run()) 61} 62 63// testJavaError is a legacy way of running tests of java modules that expect errors. 64// 65// See testJava for an explanation as to how to stop using this deprecated method. 66// 67// deprecated 68func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) { 69 t.Helper() 70 result := android.GroupFixturePreparers( 71 prepareForJavaTest, dexpreopt.PrepareForTestByEnablingDexpreopt). 72 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). 73 RunTestWithBp(t, bp) 74 return result.TestContext, result.Config 75} 76 77// testJavaWithFS runs tests using the prepareForJavaTest 78// 79// See testJava for an explanation as to how to stop using this deprecated method. 80// 81// deprecated 82func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) { 83 t.Helper() 84 result := android.GroupFixturePreparers( 85 prepareForJavaTest, fs.AddToFixture()).RunTestWithBp(t, bp) 86 return result.TestContext, result.Config 87} 88 89// testJava runs tests using the prepareForJavaTest 90// 91// Do not add any new usages of this, instead use the prepareForJavaTest directly as it makes it 92// much easier to customize the test behavior. 93// 94// If it is necessary to customize the behavior of an existing test that uses this then please first 95// convert the test to using prepareForJavaTest first and then in a following change add the 96// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify 97// that it did not change the test behavior unexpectedly. 98// 99// deprecated 100func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) { 101 t.Helper() 102 result := prepareForJavaTest.RunTestWithBp(t, bp) 103 return result.TestContext, result.Config 104} 105 106// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that 107// is defined in PrepareForIntegrationTestWithJava 108func defaultModuleToPath(name string) string { 109 switch { 110 case name == `""`: 111 return name 112 case strings.HasSuffix(name, ".jar"): 113 return name 114 default: 115 return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar") 116 } 117} 118 119// Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by 120// running it in a fixture that requires all source files to exist. 121func TestPrepareForTestWithJavaDefaultModules(t *testing.T) { 122 android.GroupFixturePreparers( 123 PrepareForTestWithJavaDefaultModules, 124 android.PrepareForTestDisallowNonExistentPaths, 125 ).RunTest(t) 126} 127 128func TestJavaLinkType(t *testing.T) { 129 testJava(t, ` 130 java_library { 131 name: "foo", 132 srcs: ["a.java"], 133 libs: ["bar"], 134 static_libs: ["baz"], 135 } 136 137 java_library { 138 name: "bar", 139 sdk_version: "current", 140 srcs: ["b.java"], 141 } 142 143 java_library { 144 name: "baz", 145 sdk_version: "system_current", 146 srcs: ["c.java"], 147 } 148 `) 149 150 testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", ` 151 java_library { 152 name: "foo", 153 srcs: ["a.java"], 154 libs: ["bar"], 155 sdk_version: "current", 156 static_libs: ["baz"], 157 } 158 159 java_library { 160 name: "bar", 161 sdk_version: "current", 162 srcs: ["b.java"], 163 } 164 165 java_library { 166 name: "baz", 167 sdk_version: "system_current", 168 srcs: ["c.java"], 169 } 170 `) 171 172 testJava(t, ` 173 java_library { 174 name: "foo", 175 srcs: ["a.java"], 176 libs: ["bar"], 177 sdk_version: "system_current", 178 static_libs: ["baz"], 179 } 180 181 java_library { 182 name: "bar", 183 sdk_version: "current", 184 srcs: ["b.java"], 185 } 186 187 java_library { 188 name: "baz", 189 sdk_version: "system_current", 190 srcs: ["c.java"], 191 } 192 `) 193 194 testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", ` 195 java_library { 196 name: "foo", 197 srcs: ["a.java"], 198 libs: ["bar"], 199 sdk_version: "system_current", 200 static_libs: ["baz"], 201 } 202 203 java_library { 204 name: "bar", 205 sdk_version: "current", 206 srcs: ["b.java"], 207 } 208 209 java_library { 210 name: "baz", 211 srcs: ["c.java"], 212 } 213 `) 214} 215 216func TestSimple(t *testing.T) { 217 ctx, _ := testJava(t, ` 218 java_library { 219 name: "foo", 220 srcs: ["a.java"], 221 libs: ["bar"], 222 static_libs: ["baz"], 223 } 224 225 java_library { 226 name: "bar", 227 srcs: ["b.java"], 228 } 229 230 java_library { 231 name: "baz", 232 srcs: ["c.java"], 233 } 234 `) 235 236 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 237 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 238 239 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 240 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 241 } 242 243 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 244 barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 245 bazTurbine := filepath.Join("out", "soong", ".intermediates", "baz", "android_common", "turbine-combined", "baz.jar") 246 247 android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barTurbine) 248 249 android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazTurbine) 250 251 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 252 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 253 } 254} 255 256func TestExportedPlugins(t *testing.T) { 257 type Result struct { 258 library string 259 processors string 260 disableTurbine bool 261 } 262 var tests = []struct { 263 name string 264 extra string 265 results []Result 266 }{ 267 { 268 name: "Exported plugin is not a direct plugin", 269 extra: `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`, 270 results: []Result{{library: "exports", processors: "-proc:none"}}, 271 }, 272 { 273 name: "Exports plugin to dependee", 274 extra: ` 275 java_library{name: "exports", exported_plugins: ["plugin"]} 276 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 277 java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 278 `, 279 results: []Result{ 280 {library: "foo", processors: "-processor com.android.TestPlugin"}, 281 {library: "bar", processors: "-processor com.android.TestPlugin"}, 282 }, 283 }, 284 { 285 name: "Exports plugin to android_library", 286 extra: ` 287 java_library{name: "exports", exported_plugins: ["plugin"]} 288 android_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 289 android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 290 `, 291 results: []Result{ 292 {library: "foo", processors: "-processor com.android.TestPlugin"}, 293 {library: "bar", processors: "-processor com.android.TestPlugin"}, 294 }, 295 }, 296 { 297 name: "Exports plugin is not propagated via transitive deps", 298 extra: ` 299 java_library{name: "exports", exported_plugins: ["plugin"]} 300 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 301 java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]} 302 `, 303 results: []Result{ 304 {library: "foo", processors: "-processor com.android.TestPlugin"}, 305 {library: "bar", processors: "-proc:none"}, 306 }, 307 }, 308 { 309 name: "Exports plugin appends to plugins", 310 extra: ` 311 java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"} 312 java_library{name: "exports", exported_plugins: ["plugin"]} 313 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]} 314 `, 315 results: []Result{ 316 {library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"}, 317 }, 318 }, 319 { 320 name: "Exports plugin to with generates_api to dependee", 321 extra: ` 322 java_library{name: "exports", exported_plugins: ["plugin_generates_api"]} 323 java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} 324 java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} 325 `, 326 results: []Result{ 327 {library: "foo", processors: "-processor com.android.TestPlugin", disableTurbine: true}, 328 {library: "bar", processors: "-processor com.android.TestPlugin", disableTurbine: true}, 329 }, 330 }, 331 } 332 333 for _, test := range tests { 334 t.Run(test.name, func(t *testing.T) { 335 ctx, _ := testJava(t, ` 336 java_plugin { 337 name: "plugin", 338 processor_class: "com.android.TestPlugin", 339 } 340 java_plugin { 341 name: "plugin_generates_api", 342 generates_api: true, 343 processor_class: "com.android.TestPlugin", 344 } 345 `+test.extra) 346 347 for _, want := range test.results { 348 javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac") 349 if javac.Args["processor"] != want.processors { 350 t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"]) 351 } 352 turbine := ctx.ModuleForTests(want.library, "android_common").MaybeRule("turbine") 353 disableTurbine := turbine.BuildParams.Rule == nil 354 if disableTurbine != want.disableTurbine { 355 t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine) 356 } 357 } 358 }) 359 } 360} 361 362func TestSdkVersionByPartition(t *testing.T) { 363 testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` 364 java_library { 365 name: "foo", 366 srcs: ["a.java"], 367 vendor: true, 368 } 369 `) 370 371 testJava(t, ` 372 java_library { 373 name: "bar", 374 srcs: ["b.java"], 375 } 376 `) 377 378 for _, enforce := range []bool{true, false} { 379 bp := ` 380 java_library { 381 name: "foo", 382 srcs: ["a.java"], 383 product_specific: true, 384 } 385 ` 386 387 errorHandler := android.FixtureExpectsNoErrors 388 if enforce { 389 errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product") 390 } 391 392 android.GroupFixturePreparers( 393 PrepareForTestWithJavaDefaultModules, 394 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 395 variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce) 396 }), 397 ). 398 ExtendWithErrorHandler(errorHandler). 399 RunTestWithBp(t, bp) 400 } 401} 402 403func TestArchSpecific(t *testing.T) { 404 ctx, _ := testJava(t, ` 405 java_library { 406 name: "foo", 407 srcs: ["a.java"], 408 target: { 409 android: { 410 srcs: ["b.java"], 411 }, 412 }, 413 } 414 `) 415 416 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 417 if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" { 418 t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs) 419 } 420} 421 422func TestBinary(t *testing.T) { 423 ctx, _ := testJava(t, ` 424 java_library_host { 425 name: "foo", 426 srcs: ["a.java"], 427 } 428 429 java_binary_host { 430 name: "bar", 431 srcs: ["b.java"], 432 static_libs: ["foo"], 433 jni_libs: ["libjni"], 434 } 435 436 cc_library_shared { 437 name: "libjni", 438 host_supported: true, 439 device_supported: false, 440 stl: "none", 441 } 442 `) 443 444 buildOS := android.BuildOs.String() 445 446 bar := ctx.ModuleForTests("bar", buildOS+"_common") 447 barJar := bar.Output("bar.jar").Output.String() 448 barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64") 449 barWrapperDeps := barWrapper.Output("bar").Implicits.Strings() 450 451 libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared") 452 libjniSO := libjni.Rule("Cp").Output.String() 453 454 // Test that the install binary wrapper depends on the installed jar file 455 if g, w := barWrapperDeps, barJar; !android.InList(w, g) { 456 t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g) 457 } 458 459 // Test that the install binary wrapper depends on the installed JNI libraries 460 if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) { 461 t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g) 462 } 463} 464 465func TestTest(t *testing.T) { 466 ctx, _ := testJava(t, ` 467 java_test_host { 468 name: "foo", 469 srcs: ["a.java"], 470 jni_libs: ["libjni"], 471 } 472 473 cc_library_shared { 474 name: "libjni", 475 host_supported: true, 476 device_supported: false, 477 stl: "none", 478 } 479 `) 480 481 buildOS := android.BuildOs.String() 482 483 foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 484 485 expected := "lib64/libjni.so" 486 if runtime.GOOS == "darwin" { 487 expected = "lib64/libjni.dylib" 488 } 489 490 fooTestData := foo.data 491 if len(fooTestData) != 1 || fooTestData[0].Rel() != expected { 492 t.Errorf(`expected foo test data relative path [%q], got %q`, 493 expected, fooTestData.Strings()) 494 } 495} 496 497func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { 498 bp := ` 499 java_library { 500 name: "target_library", 501 srcs: ["a.java"], 502 } 503 504 java_binary_host { 505 name: "host_binary", 506 srcs: ["b.java"], 507 } 508 ` 509 510 result := android.GroupFixturePreparers( 511 PrepareForTestWithJavaDefaultModules, 512 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 513 variables.MinimizeJavaDebugInfo = proptools.BoolPtr(true) 514 }), 515 ).RunTestWithBp(t, bp) 516 517 // first, check that the -g flag is added to target modules 518 targetLibrary := result.ModuleForTests("target_library", "android_common") 519 targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"] 520 if !strings.Contains(targetJavaFlags, "-g:source,lines") { 521 t.Errorf("target library javac flags %v should contain "+ 522 "-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags) 523 } 524 525 // check that -g is not overridden for host modules 526 buildOS := android.BuildOs.String() 527 hostBinary := result.ModuleForTests("host_binary", buildOS+"_common") 528 hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"] 529 if strings.Contains(hostJavaFlags, "-g:source,lines") { 530 t.Errorf("java_binary_host javac flags %v should not have "+ 531 "-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags) 532 } 533} 534 535func TestPrebuilts(t *testing.T) { 536 ctx, _ := testJava(t, ` 537 java_library { 538 name: "foo", 539 srcs: ["a.java", ":stubs-source"], 540 libs: ["bar", "sdklib"], 541 static_libs: ["baz"], 542 } 543 544 java_import { 545 name: "bar", 546 jars: ["a.jar"], 547 } 548 549 java_import { 550 name: "baz", 551 jars: ["b.jar"], 552 sdk_version: "current", 553 compile_dex: true, 554 } 555 556 dex_import { 557 name: "qux", 558 jars: ["b.jar"], 559 } 560 561 java_sdk_library_import { 562 name: "sdklib", 563 public: { 564 jars: ["c.jar"], 565 }, 566 } 567 568 prebuilt_stubs_sources { 569 name: "stubs-source", 570 srcs: ["stubs/sources"], 571 } 572 573 java_test_import { 574 name: "test", 575 jars: ["a.jar"], 576 test_suites: ["cts"], 577 test_config: "AndroidTest.xml", 578 } 579 `) 580 581 fooModule := ctx.ModuleForTests("foo", "android_common") 582 javac := fooModule.Rule("javac") 583 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 584 barModule := ctx.ModuleForTests("bar", "android_common") 585 barJar := barModule.Rule("combineJar").Output 586 bazModule := ctx.ModuleForTests("baz", "android_common") 587 bazJar := bazModule.Rule("combineJar").Output 588 sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output 589 590 fooLibrary := fooModule.Module().(*Library) 591 assertDeepEquals(t, "foo java sources incorrect", 592 []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings()) 593 594 assertDeepEquals(t, "foo java source jars incorrect", 595 []string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"}, 596 android.NormalizePathsForTesting(fooLibrary.compiledSrcJars)) 597 598 if !strings.Contains(javac.Args["classpath"], barJar.String()) { 599 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) 600 } 601 602 barDexJar := barModule.Module().(*Import).DexJarBuildPath() 603 if barDexJar != nil { 604 t.Errorf("bar dex jar build path expected to be nil, got %q", barDexJar) 605 } 606 607 if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) { 608 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) 609 } 610 611 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() { 612 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) 613 } 614 615 bazDexJar := bazModule.Module().(*Import).DexJarBuildPath() 616 expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar" 617 android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar) 618 619 ctx.ModuleForTests("qux", "android_common").Rule("Cp") 620} 621 622func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) { 623 if !reflect.DeepEqual(expected, actual) { 624 t.Errorf("%s: expected %q, found %q", message, expected, actual) 625 } 626} 627 628func TestPrebuiltStubsSources(t *testing.T) { 629 test := func(t *testing.T, sourcesPath string, expectedInputs []string) { 630 ctx, _ := testJavaWithFS(t, fmt.Sprintf(` 631prebuilt_stubs_sources { 632 name: "stubs-source", 633 srcs: ["%s"], 634}`, sourcesPath), map[string][]byte{ 635 "stubs/sources/pkg/A.java": nil, 636 "stubs/sources/pkg/B.java": nil, 637 }) 638 639 zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src") 640 if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) { 641 t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual) 642 } 643 } 644 645 t.Run("empty/missing directory", func(t *testing.T) { 646 test(t, "empty-directory", nil) 647 }) 648 649 t.Run("non-empty set of sources", func(t *testing.T) { 650 test(t, "stubs/sources", []string{ 651 "stubs/sources/pkg/A.java", 652 "stubs/sources/pkg/B.java", 653 }) 654 }) 655} 656 657func TestDefaults(t *testing.T) { 658 ctx, _ := testJava(t, ` 659 java_defaults { 660 name: "defaults", 661 srcs: ["a.java"], 662 libs: ["bar"], 663 static_libs: ["baz"], 664 optimize: {enabled: false}, 665 } 666 667 java_library { 668 name: "foo", 669 defaults: ["defaults"], 670 } 671 672 java_library { 673 name: "bar", 674 srcs: ["b.java"], 675 } 676 677 java_library { 678 name: "baz", 679 srcs: ["c.java"], 680 } 681 682 android_test { 683 name: "atestOptimize", 684 defaults: ["defaults"], 685 optimize: {enabled: true}, 686 } 687 688 android_test { 689 name: "atestNoOptimize", 690 defaults: ["defaults"], 691 } 692 693 android_test { 694 name: "atestDefault", 695 srcs: ["a.java"], 696 } 697 `) 698 699 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 700 combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") 701 702 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { 703 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) 704 } 705 706 barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 707 if !strings.Contains(javac.Args["classpath"], barTurbine) { 708 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 709 } 710 711 baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() 712 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { 713 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) 714 } 715 716 atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8") 717 if atestOptimize.Output == nil { 718 t.Errorf("atestOptimize should optimize APK") 719 } 720 721 atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8") 722 if atestNoOptimize.Output == nil { 723 t.Errorf("atestNoOptimize should not optimize APK") 724 } 725 726 atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("r8") 727 if atestDefault.Output == nil { 728 t.Errorf("atestDefault should optimize APK") 729 } 730} 731 732func TestResources(t *testing.T) { 733 var table = []struct { 734 name string 735 prop string 736 extra string 737 args string 738 }{ 739 { 740 // Test that a module with java_resource_dirs includes the files 741 name: "resource dirs", 742 prop: `java_resource_dirs: ["java-res"]`, 743 args: "-C java-res -f java-res/a/a -f java-res/b/b", 744 }, 745 { 746 // Test that a module with java_resources includes the files 747 name: "resource files", 748 prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`, 749 args: "-C . -f java-res/a/a -f java-res/b/b", 750 }, 751 { 752 // Test that a module with a filegroup in java_resources includes the files with the 753 // path prefix 754 name: "resource filegroup", 755 prop: `java_resources: [":foo-res"]`, 756 extra: ` 757 filegroup { 758 name: "foo-res", 759 path: "java-res", 760 srcs: ["java-res/a/a", "java-res/b/b"], 761 }`, 762 args: "-C java-res -f java-res/a/a -f java-res/b/b", 763 }, 764 { 765 // Test that a module with wildcards in java_resource_dirs has the correct path prefixes 766 name: "wildcard dirs", 767 prop: `java_resource_dirs: ["java-res/*"]`, 768 args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b", 769 }, 770 { 771 // Test that a module exclude_java_resource_dirs excludes the files 772 name: "wildcard dirs", 773 prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`, 774 args: "-C java-res/a -f java-res/a/a", 775 }, 776 { 777 // Test wildcards in java_resources 778 name: "wildcard files", 779 prop: `java_resources: ["java-res/**/*"]`, 780 args: "-C . -f java-res/a/a -f java-res/b/b", 781 }, 782 { 783 // Test exclude_java_resources with java_resources 784 name: "wildcard files with exclude", 785 prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`, 786 args: "-C . -f java-res/a/a", 787 }, 788 { 789 // Test exclude_java_resources with java_resource_dirs 790 name: "resource dirs with exclude files", 791 prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`, 792 args: "-C java-res -f java-res/a/a", 793 }, 794 { 795 // Test exclude_java_resource_dirs with java_resource_dirs 796 name: "resource dirs with exclude files", 797 prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`, 798 args: "-C java-res -f java-res/a/a -f java-res/b/b", 799 }, 800 } 801 802 for _, test := range table { 803 t.Run(test.name, func(t *testing.T) { 804 ctx, _ := testJavaWithFS(t, ` 805 java_library { 806 name: "foo", 807 srcs: [ 808 "a.java", 809 "b.java", 810 "c.java", 811 ], 812 `+test.prop+`, 813 } 814 `+test.extra, 815 map[string][]byte{ 816 "java-res/a/a": nil, 817 "java-res/b/b": nil, 818 "java-res2/a": nil, 819 }, 820 ) 821 822 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 823 fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar") 824 825 if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { 826 t.Errorf("foo combined jars %v does not contain %q", 827 foo.Inputs.Strings(), fooRes.Output.String()) 828 } 829 830 if fooRes.Args["jarArgs"] != test.args { 831 t.Errorf("foo resource jar args %q is not %q", 832 fooRes.Args["jarArgs"], test.args) 833 } 834 }) 835 } 836} 837 838func TestIncludeSrcs(t *testing.T) { 839 ctx, _ := testJavaWithFS(t, ` 840 java_library { 841 name: "foo", 842 srcs: [ 843 "a.java", 844 "b.java", 845 "c.java", 846 ], 847 include_srcs: true, 848 } 849 850 java_library { 851 name: "bar", 852 srcs: [ 853 "a.java", 854 "b.java", 855 "c.java", 856 ], 857 java_resource_dirs: ["java-res"], 858 include_srcs: true, 859 } 860 `, map[string][]byte{ 861 "java-res/a/a": nil, 862 "java-res/b/b": nil, 863 "java-res2/a": nil, 864 }) 865 866 // Test a library with include_srcs: true 867 foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") 868 fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar") 869 870 if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) { 871 t.Errorf("foo combined jars %v does not contain %q", w, g) 872 } 873 874 if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 875 t.Errorf("foo source jar args %q is not %q", w, g) 876 } 877 878 // Test a library with include_srcs: true and resources 879 bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar") 880 barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar") 881 barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar") 882 barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar") 883 884 if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 885 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 886 } 887 888 if g, w := barRes.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { 889 t.Errorf("bar combined resource jars %v does not contain %q", w, g) 890 } 891 892 if g, w := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) { 893 t.Errorf("bar combined jars %v does not contain %q", w, g) 894 } 895 896 if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w { 897 t.Errorf("bar source jar args %q is not %q", w, g) 898 } 899 900 if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w { 901 t.Errorf("bar resource jar args %q is not %q", w, g) 902 } 903} 904 905func TestGeneratedSources(t *testing.T) { 906 ctx, _ := testJavaWithFS(t, ` 907 java_library { 908 name: "foo", 909 srcs: [ 910 "a*.java", 911 ":gen", 912 "b*.java", 913 ], 914 } 915 916 genrule { 917 name: "gen", 918 tool_files: ["java-res/a"], 919 out: ["gen.java"], 920 } 921 `, map[string][]byte{ 922 "a.java": nil, 923 "b.java": nil, 924 }) 925 926 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 927 genrule := ctx.ModuleForTests("gen", "").Rule("generator") 928 929 if filepath.Base(genrule.Output.String()) != "gen.java" { 930 t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String()) 931 } 932 933 if len(javac.Inputs) != 3 || 934 javac.Inputs[0].String() != "a.java" || 935 javac.Inputs[1].String() != genrule.Output.String() || 936 javac.Inputs[2].String() != "b.java" { 937 t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs) 938 } 939} 940 941func TestTurbine(t *testing.T) { 942 result := android.GroupFixturePreparers( 943 prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})). 944 RunTestWithBp(t, ` 945 java_library { 946 name: "foo", 947 srcs: ["a.java"], 948 sdk_version: "14", 949 } 950 951 java_library { 952 name: "bar", 953 srcs: ["b.java"], 954 static_libs: ["foo"], 955 sdk_version: "14", 956 } 957 958 java_library { 959 name: "baz", 960 srcs: ["c.java"], 961 libs: ["bar"], 962 sdk_version: "14", 963 } 964 `) 965 966 fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine") 967 barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine") 968 barJavac := result.ModuleForTests("bar", "android_common").Rule("javac") 969 barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine") 970 bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac") 971 972 android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs) 973 974 fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar") 975 barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar") 976 android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["classpath"], fooHeaderJar) 977 android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar) 978 android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs) 979 android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") 980} 981 982func TestSharding(t *testing.T) { 983 ctx, _ := testJava(t, ` 984 java_library { 985 name: "bar", 986 srcs: ["a.java","b.java","c.java"], 987 javac_shard_size: 1 988 } 989 `) 990 991 barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar") 992 for i := 0; i < 3; i++ { 993 barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)) 994 if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) { 995 t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar) 996 } 997 } 998} 999 1000func TestJarGenrules(t *testing.T) { 1001 ctx, _ := testJava(t, ` 1002 java_library { 1003 name: "foo", 1004 srcs: ["a.java"], 1005 } 1006 1007 java_genrule { 1008 name: "jargen", 1009 tool_files: ["b.java"], 1010 cmd: "$(location b.java) $(in) $(out)", 1011 out: ["jargen.jar"], 1012 srcs: [":foo"], 1013 } 1014 1015 java_library { 1016 name: "bar", 1017 static_libs: ["jargen"], 1018 srcs: ["c.java"], 1019 } 1020 1021 java_library { 1022 name: "baz", 1023 libs: ["jargen"], 1024 srcs: ["c.java"], 1025 } 1026 `) 1027 1028 foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar") 1029 jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar") 1030 bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar") 1031 baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar") 1032 barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar") 1033 1034 if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) { 1035 t.Errorf("expected jargen inputs [%q], got %q", w, g) 1036 } 1037 1038 if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) { 1039 t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String()) 1040 } 1041 1042 if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) { 1043 t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String()) 1044 } 1045 1046 if len(barCombined.Inputs) != 2 || 1047 barCombined.Inputs[0].String() != bar.Output.String() || 1048 barCombined.Inputs[1].String() != jargen.Output.String() { 1049 t.Errorf("bar combined jar inputs %v is not [%q, %q]", 1050 barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String()) 1051 } 1052} 1053 1054func TestExcludeFileGroupInSrcs(t *testing.T) { 1055 ctx, _ := testJava(t, ` 1056 java_library { 1057 name: "foo", 1058 srcs: ["a.java", ":foo-srcs"], 1059 exclude_srcs: ["a.java", ":foo-excludes"], 1060 } 1061 1062 filegroup { 1063 name: "foo-srcs", 1064 srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"], 1065 } 1066 1067 filegroup { 1068 name: "foo-excludes", 1069 srcs: ["java-fg/a.java", "java-fg/b.java"], 1070 } 1071 `) 1072 1073 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") 1074 1075 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" { 1076 t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) 1077 } 1078} 1079 1080func TestJavaLibrary(t *testing.T) { 1081 testJavaWithFS(t, "", map[string][]byte{ 1082 "libcore/Android.bp": []byte(` 1083 java_library { 1084 name: "core", 1085 sdk_version: "none", 1086 system_modules: "none", 1087 } 1088 1089 filegroup { 1090 name: "core-jar", 1091 srcs: [":core{.jar}"], 1092 } 1093 `), 1094 }) 1095} 1096 1097func TestJavaImport(t *testing.T) { 1098 testJavaWithFS(t, "", map[string][]byte{ 1099 "libcore/Android.bp": []byte(` 1100 java_import { 1101 name: "core", 1102 sdk_version: "none", 1103 } 1104 1105 filegroup { 1106 name: "core-jar", 1107 srcs: [":core{.jar}"], 1108 } 1109 `), 1110 }) 1111} 1112 1113var compilerFlagsTestCases = []struct { 1114 in string 1115 out bool 1116}{ 1117 { 1118 in: "a", 1119 out: false, 1120 }, 1121 { 1122 in: "-a", 1123 out: true, 1124 }, 1125 { 1126 in: "-no-jdk", 1127 out: false, 1128 }, 1129 { 1130 in: "-no-stdlib", 1131 out: false, 1132 }, 1133 { 1134 in: "-kotlin-home", 1135 out: false, 1136 }, 1137 { 1138 in: "-kotlin-home /some/path", 1139 out: false, 1140 }, 1141 { 1142 in: "-include-runtime", 1143 out: false, 1144 }, 1145 { 1146 in: "-Xintellij-plugin-root", 1147 out: false, 1148 }, 1149} 1150 1151type mockContext struct { 1152 android.ModuleContext 1153 result bool 1154} 1155 1156func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) { 1157 // CheckBadCompilerFlags calls this function when the flag should be rejected 1158 ctx.result = false 1159} 1160 1161func TestCompilerFlags(t *testing.T) { 1162 for _, testCase := range compilerFlagsTestCases { 1163 ctx := &mockContext{result: true} 1164 CheckKotlincFlags(ctx, []string{testCase.in}) 1165 if ctx.result != testCase.out { 1166 t.Errorf("incorrect output:") 1167 t.Errorf(" input: %#v", testCase.in) 1168 t.Errorf(" expected: %#v", testCase.out) 1169 t.Errorf(" got: %#v", ctx.result) 1170 } 1171 } 1172} 1173 1174// TODO(jungjw): Consider making this more robust by ignoring path order. 1175func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) { 1176 variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop() 1177 flags := strings.Split(variables["javacFlags"], " ") 1178 got := "" 1179 for _, flag := range flags { 1180 keyEnd := strings.Index(flag, "=") 1181 if keyEnd > -1 && flag[:keyEnd] == "--patch-module" { 1182 got = flag[keyEnd+1:] 1183 break 1184 } 1185 } 1186 if expected != android.StringPathRelativeToTop(ctx.Config().BuildDir(), got) { 1187 t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got) 1188 } 1189} 1190 1191func TestPatchModule(t *testing.T) { 1192 t.Run("Java language level 8", func(t *testing.T) { 1193 // Test with legacy javac -source 1.8 -target 1.8 1194 bp := ` 1195 java_library { 1196 name: "foo", 1197 srcs: ["a.java"], 1198 java_version: "1.8", 1199 } 1200 1201 java_library { 1202 name: "bar", 1203 srcs: ["b.java"], 1204 sdk_version: "none", 1205 system_modules: "none", 1206 patch_module: "java.base", 1207 java_version: "1.8", 1208 } 1209 1210 java_library { 1211 name: "baz", 1212 srcs: ["c.java"], 1213 patch_module: "java.base", 1214 java_version: "1.8", 1215 } 1216 ` 1217 ctx, _ := testJava(t, bp) 1218 1219 checkPatchModuleFlag(t, ctx, "foo", "") 1220 checkPatchModuleFlag(t, ctx, "bar", "") 1221 checkPatchModuleFlag(t, ctx, "baz", "") 1222 }) 1223 1224 t.Run("Java language level 9", func(t *testing.T) { 1225 // Test with default javac -source 9 -target 9 1226 bp := ` 1227 java_library { 1228 name: "foo", 1229 srcs: ["a.java"], 1230 } 1231 1232 java_library { 1233 name: "bar", 1234 srcs: ["b.java"], 1235 sdk_version: "none", 1236 system_modules: "none", 1237 patch_module: "java.base", 1238 } 1239 1240 java_library { 1241 name: "baz", 1242 srcs: [ 1243 "c.java", 1244 // Tests for b/150878007 1245 "dir/d.java", 1246 "dir2/e.java", 1247 "dir2/f.java", 1248 "nested/dir/g.java" 1249 ], 1250 patch_module: "java.base", 1251 } 1252 ` 1253 ctx, _ := testJava(t, bp) 1254 1255 checkPatchModuleFlag(t, ctx, "foo", "") 1256 expected := "java.base=.:out/soong" 1257 checkPatchModuleFlag(t, ctx, "bar", expected) 1258 expected = "java.base=" + strings.Join([]string{ 1259 ".", "out/soong", "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":") 1260 checkPatchModuleFlag(t, ctx, "baz", expected) 1261 }) 1262} 1263 1264func TestJavaLibraryWithSystemModules(t *testing.T) { 1265 ctx, _ := testJava(t, ` 1266 java_library { 1267 name: "lib-with-source-system-modules", 1268 srcs: [ 1269 "a.java", 1270 ], 1271 sdk_version: "none", 1272 system_modules: "source-system-modules", 1273 } 1274 1275 java_library { 1276 name: "source-jar", 1277 srcs: [ 1278 "a.java", 1279 ], 1280 } 1281 1282 java_system_modules { 1283 name: "source-system-modules", 1284 libs: ["source-jar"], 1285 } 1286 1287 java_library { 1288 name: "lib-with-prebuilt-system-modules", 1289 srcs: [ 1290 "a.java", 1291 ], 1292 sdk_version: "none", 1293 system_modules: "prebuilt-system-modules", 1294 } 1295 1296 java_import { 1297 name: "prebuilt-jar", 1298 jars: ["a.jar"], 1299 } 1300 1301 java_system_modules_import { 1302 name: "prebuilt-system-modules", 1303 libs: ["prebuilt-jar"], 1304 } 1305 `) 1306 1307 checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") 1308 1309 checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") 1310} 1311 1312func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { 1313 javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") 1314 bootClasspath := javacRule.Args["bootClasspath"] 1315 if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { 1316 t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) 1317 } 1318} 1319 1320func TestAidlExportIncludeDirsFromImports(t *testing.T) { 1321 ctx, _ := testJava(t, ` 1322 java_library { 1323 name: "foo", 1324 srcs: ["aidl/foo/IFoo.aidl"], 1325 libs: ["bar"], 1326 } 1327 1328 java_import { 1329 name: "bar", 1330 jars: ["a.jar"], 1331 aidl: { 1332 export_include_dirs: ["aidl/bar"], 1333 }, 1334 } 1335 `) 1336 1337 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1338 expectedAidlFlag := "-Iaidl/bar" 1339 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1340 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1341 } 1342} 1343 1344func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) { 1345 ctx, _ := testJava(t, ` 1346 java_library { 1347 name: "foo", 1348 srcs: ["aidl/foo/IFoo.aidl"], 1349 aidl: { flags: ["-Werror"], }, 1350 } 1351 `) 1352 1353 aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command 1354 expectedAidlFlag := "-Werror" 1355 if !strings.Contains(aidlCommand, expectedAidlFlag) { 1356 t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) 1357 } 1358} 1359 1360func TestDataNativeBinaries(t *testing.T) { 1361 ctx, _ := testJava(t, ` 1362 java_test_host { 1363 name: "foo", 1364 srcs: ["a.java"], 1365 data_native_bins: ["bin"] 1366 } 1367 1368 python_binary_host { 1369 name: "bin", 1370 srcs: ["bin.py"], 1371 } 1372 `) 1373 1374 buildOS := android.BuildOs.String() 1375 1376 test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 1377 entries := android.AndroidMkEntriesForTest(t, ctx, test)[0] 1378 expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64_PY3/bin:bin"} 1379 actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] 1380 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual) 1381} 1382 1383func TestDefaultInstallable(t *testing.T) { 1384 ctx, _ := testJava(t, ` 1385 java_test_host { 1386 name: "foo" 1387 } 1388 `) 1389 1390 buildOS := android.BuildOs.String() 1391 module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) 1392 assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true), 1393 module.properties.Installable) 1394} 1395