1// Copyright 2019 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 sdk 16 17import ( 18 "android/soong/android" 19 "log" 20 "os" 21 "testing" 22 23 "github.com/google/blueprint/proptools" 24) 25 26// Needed in an _test.go file in this package to ensure tests run correctly, particularly in IDE. 27func TestMain(m *testing.M) { 28 if android.BuildOs != android.Linux { 29 // b/145598135 - Generating host snapshots for anything other than linux is not supported. 30 log.Printf("Skipping as sdk snapshot generation is only supported on %s not %s", android.Linux, android.BuildOs) 31 os.Exit(0) 32 } 33 34 os.Exit(m.Run()) 35} 36 37func TestDepNotInRequiredSdks(t *testing.T) { 38 testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, ` 39 sdk { 40 name: "mysdk", 41 java_header_libs: ["sdkmember"], 42 } 43 44 sdk_snapshot { 45 name: "mysdk@1", 46 java_header_libs: ["sdkmember_mysdk_1"], 47 } 48 49 java_import { 50 name: "sdkmember", 51 prefer: false, 52 host_supported: true, 53 } 54 55 java_import { 56 name: "sdkmember_mysdk_1", 57 sdk_member_name: "sdkmember", 58 host_supported: true, 59 } 60 61 java_library { 62 name: "myjavalib", 63 srcs: ["Test.java"], 64 libs: [ 65 "sdkmember", 66 "otherlib", 67 ], 68 system_modules: "none", 69 sdk_version: "none", 70 compile_dex: true, 71 host_supported: true, 72 apex_available: ["myapex"], 73 } 74 75 // this lib is no in mysdk 76 java_library { 77 name: "otherlib", 78 srcs: ["Test.java"], 79 system_modules: "none", 80 sdk_version: "none", 81 compile_dex: true, 82 host_supported: true, 83 } 84 85 apex { 86 name: "myapex", 87 java_libs: ["myjavalib"], 88 uses_sdks: ["mysdk@1"], 89 key: "myapex.key", 90 certificate: ":myapex.cert", 91 } 92 `) 93} 94 95// Ensure that prebuilt modules have the same effective visibility as the source 96// modules. 97func TestSnapshotVisibility(t *testing.T) { 98 packageBp := ` 99 package { 100 default_visibility: ["//other/foo"], 101 } 102 103 sdk { 104 name: "mysdk", 105 visibility: [ 106 "//other/foo", 107 // This short form will be replaced with //package:__subpackages__ in the 108 // generated sdk_snapshot. 109 ":__subpackages__", 110 ], 111 prebuilt_visibility: [ 112 "//prebuilts/mysdk", 113 ], 114 java_header_libs: [ 115 "myjavalib", 116 "mypublicjavalib", 117 "mydefaultedjavalib", 118 "myprivatejavalib", 119 ], 120 } 121 122 java_library { 123 name: "myjavalib", 124 // Uses package default visibility 125 srcs: ["Test.java"], 126 system_modules: "none", 127 sdk_version: "none", 128 } 129 130 java_defaults { 131 name: "java-defaults", 132 visibility: ["//other/bar"], 133 } 134 135 java_library { 136 name: "mypublicjavalib", 137 defaults: ["java-defaults"], 138 visibility: ["//visibility:public"], 139 srcs: ["Test.java"], 140 system_modules: "none", 141 sdk_version: "none", 142 } 143 144 java_defaults { 145 name: "myjavadefaults", 146 visibility: ["//other/bar"], 147 } 148 149 java_library { 150 name: "mydefaultedjavalib", 151 defaults: ["myjavadefaults"], 152 srcs: ["Test.java"], 153 system_modules: "none", 154 sdk_version: "none", 155 } 156 157 java_library { 158 name: "myprivatejavalib", 159 srcs: ["Test.java"], 160 visibility: ["//visibility:private"], 161 system_modules: "none", 162 sdk_version: "none", 163 } 164 ` 165 166 result := testSdkWithFs(t, ``, 167 map[string][]byte{ 168 "package/Test.java": nil, 169 "package/Android.bp": []byte(packageBp), 170 }) 171 172 CheckSnapshot(t, result, "mysdk", "package", 173 checkAndroidBpContents(` 174// This is auto-generated. DO NOT EDIT. 175 176java_import { 177 name: "mysdk_myjavalib@current", 178 sdk_member_name: "myjavalib", 179 visibility: [ 180 "//other/foo", 181 "//package", 182 "//prebuilts/mysdk", 183 ], 184 apex_available: ["//apex_available:platform"], 185 jars: ["java/myjavalib.jar"], 186} 187 188java_import { 189 name: "myjavalib", 190 prefer: false, 191 visibility: [ 192 "//other/foo", 193 "//package", 194 "//prebuilts/mysdk", 195 ], 196 apex_available: ["//apex_available:platform"], 197 jars: ["java/myjavalib.jar"], 198} 199 200java_import { 201 name: "mysdk_mypublicjavalib@current", 202 sdk_member_name: "mypublicjavalib", 203 visibility: ["//visibility:public"], 204 apex_available: ["//apex_available:platform"], 205 jars: ["java/mypublicjavalib.jar"], 206} 207 208java_import { 209 name: "mypublicjavalib", 210 prefer: false, 211 visibility: ["//visibility:public"], 212 apex_available: ["//apex_available:platform"], 213 jars: ["java/mypublicjavalib.jar"], 214} 215 216java_import { 217 name: "mysdk_mydefaultedjavalib@current", 218 sdk_member_name: "mydefaultedjavalib", 219 visibility: [ 220 "//other/bar", 221 "//package", 222 "//prebuilts/mysdk", 223 ], 224 apex_available: ["//apex_available:platform"], 225 jars: ["java/mydefaultedjavalib.jar"], 226} 227 228java_import { 229 name: "mydefaultedjavalib", 230 prefer: false, 231 visibility: [ 232 "//other/bar", 233 "//package", 234 "//prebuilts/mysdk", 235 ], 236 apex_available: ["//apex_available:platform"], 237 jars: ["java/mydefaultedjavalib.jar"], 238} 239 240java_import { 241 name: "mysdk_myprivatejavalib@current", 242 sdk_member_name: "myprivatejavalib", 243 visibility: [ 244 "//package", 245 "//prebuilts/mysdk", 246 ], 247 apex_available: ["//apex_available:platform"], 248 jars: ["java/myprivatejavalib.jar"], 249} 250 251java_import { 252 name: "myprivatejavalib", 253 prefer: false, 254 visibility: [ 255 "//package", 256 "//prebuilts/mysdk", 257 ], 258 apex_available: ["//apex_available:platform"], 259 jars: ["java/myprivatejavalib.jar"], 260} 261 262sdk_snapshot { 263 name: "mysdk@current", 264 visibility: [ 265 "//other/foo", 266 "//package:__subpackages__", 267 ], 268 java_header_libs: [ 269 "mysdk_myjavalib@current", 270 "mysdk_mypublicjavalib@current", 271 "mysdk_mydefaultedjavalib@current", 272 "mysdk_myprivatejavalib@current", 273 ], 274} 275`)) 276} 277 278func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) { 279 testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, ` 280 sdk { 281 name: "mysdk", 282 prebuilt_visibility: [ 283 "//foo", 284 "//visibility:private", 285 ], 286 } 287`) 288} 289 290func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) { 291 testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, ` 292 sdk { 293 name: "mysdk", 294 prebuilt_visibility: [ 295 "//visibility:private", 296 ], 297 java_header_libs: [ 298 "myjavalib", 299 ], 300 } 301 302 java_library { 303 name: "myjavalib", 304 // Uses package default visibility 305 srcs: ["Test.java"], 306 system_modules: "none", 307 sdk_version: "none", 308 } 309`) 310} 311 312func TestSdkInstall(t *testing.T) { 313 sdk := ` 314 sdk { 315 name: "mysdk", 316 } 317 ` 318 result := testSdkWithFs(t, sdk, nil) 319 320 CheckSnapshot(t, result, "mysdk", "", 321 checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`)) 322} 323 324type EmbeddedPropertiesStruct struct { 325 S_Embedded_Common string `android:"arch_variant"` 326 S_Embedded_Different string `android:"arch_variant"` 327} 328 329type testPropertiesStruct struct { 330 name string 331 private string 332 Public_Kept string `sdk:"keep"` 333 S_Common string 334 S_Different string `android:"arch_variant"` 335 A_Common []string 336 A_Different []string `android:"arch_variant"` 337 F_Common *bool 338 F_Different *bool `android:"arch_variant"` 339 EmbeddedPropertiesStruct 340} 341 342func (p *testPropertiesStruct) optimizableProperties() interface{} { 343 return p 344} 345 346func (p *testPropertiesStruct) String() string { 347 return p.name 348} 349 350var _ propertiesContainer = (*testPropertiesStruct)(nil) 351 352func TestCommonValueOptimization(t *testing.T) { 353 common := &testPropertiesStruct{name: "common"} 354 structs := []propertiesContainer{ 355 &testPropertiesStruct{ 356 name: "struct-0", 357 private: "common", 358 Public_Kept: "common", 359 S_Common: "common", 360 S_Different: "upper", 361 A_Common: []string{"first", "second"}, 362 A_Different: []string{"alpha", "beta"}, 363 F_Common: proptools.BoolPtr(false), 364 F_Different: proptools.BoolPtr(false), 365 EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ 366 S_Embedded_Common: "embedded_common", 367 S_Embedded_Different: "embedded_upper", 368 }, 369 }, 370 &testPropertiesStruct{ 371 name: "struct-1", 372 private: "common", 373 Public_Kept: "common", 374 S_Common: "common", 375 S_Different: "lower", 376 A_Common: []string{"first", "second"}, 377 A_Different: []string{"alpha", "delta"}, 378 F_Common: proptools.BoolPtr(false), 379 F_Different: proptools.BoolPtr(true), 380 EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ 381 S_Embedded_Common: "embedded_common", 382 S_Embedded_Different: "embedded_lower", 383 }, 384 }, 385 } 386 387 extractor := newCommonValueExtractor(common) 388 389 err := extractor.extractCommonProperties(common, structs) 390 android.AssertDeepEquals(t, "unexpected error", nil, err) 391 392 android.AssertDeepEquals(t, "common properties not correct", 393 &testPropertiesStruct{ 394 name: "common", 395 private: "", 396 Public_Kept: "", 397 S_Common: "common", 398 S_Different: "", 399 A_Common: []string{"first", "second"}, 400 A_Different: []string(nil), 401 F_Common: proptools.BoolPtr(false), 402 F_Different: nil, 403 EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ 404 S_Embedded_Common: "embedded_common", 405 S_Embedded_Different: "", 406 }, 407 }, 408 common) 409 410 android.AssertDeepEquals(t, "updated properties[0] not correct", 411 &testPropertiesStruct{ 412 name: "struct-0", 413 private: "common", 414 Public_Kept: "common", 415 S_Common: "", 416 S_Different: "upper", 417 A_Common: nil, 418 A_Different: []string{"alpha", "beta"}, 419 F_Common: nil, 420 F_Different: proptools.BoolPtr(false), 421 EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ 422 S_Embedded_Common: "", 423 S_Embedded_Different: "embedded_upper", 424 }, 425 }, 426 structs[0]) 427 428 android.AssertDeepEquals(t, "updated properties[1] not correct", 429 &testPropertiesStruct{ 430 name: "struct-1", 431 private: "common", 432 Public_Kept: "common", 433 S_Common: "", 434 S_Different: "lower", 435 A_Common: nil, 436 A_Different: []string{"alpha", "delta"}, 437 F_Common: nil, 438 F_Different: proptools.BoolPtr(true), 439 EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ 440 S_Embedded_Common: "", 441 S_Embedded_Different: "embedded_lower", 442 }, 443 }, 444 structs[1]) 445} 446 447func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) { 448 common := &testPropertiesStruct{name: "common"} 449 structs := []propertiesContainer{ 450 &testPropertiesStruct{ 451 name: "struct-0", 452 S_Common: "should-be-but-is-not-common0", 453 }, 454 &testPropertiesStruct{ 455 name: "struct-1", 456 S_Common: "should-be-but-is-not-common1", 457 }, 458 } 459 460 extractor := newCommonValueExtractor(common) 461 462 err := extractor.extractCommonProperties(common, structs) 463 android.AssertErrorMessageEquals(t, "unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties: 464 "struct-0" has value "should-be-but-is-not-common0" 465 "struct-1" has value "should-be-but-is-not-common1"`, err) 466} 467 468// Ensure that sdk snapshot related environment variables work correctly. 469func TestSnapshot_EnvConfiguration(t *testing.T) { 470 bp := ` 471 sdk { 472 name: "mysdk", 473 java_header_libs: ["myjavalib"], 474 } 475 476 java_library { 477 name: "myjavalib", 478 srcs: ["Test.java"], 479 system_modules: "none", 480 sdk_version: "none", 481 compile_dex: true, 482 host_supported: true, 483 } 484 ` 485 preparer := android.GroupFixturePreparers( 486 prepareForSdkTestWithJava, 487 android.FixtureWithRootAndroidBp(bp), 488 ) 489 490 checkZipFile := func(t *testing.T, result *android.TestResult, expected string) { 491 zipRule := result.ModuleForTests("mysdk", "common_os").Rule("SnapshotZipFiles") 492 android.AssertStringEquals(t, "snapshot zip file", expected, zipRule.Output.String()) 493 } 494 495 t.Run("no env variables", func(t *testing.T) { 496 result := preparer.RunTest(t) 497 498 checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip") 499 500 CheckSnapshot(t, result, "mysdk", "", 501 checkAndroidBpContents(` 502// This is auto-generated. DO NOT EDIT. 503 504java_import { 505 name: "mysdk_myjavalib@current", 506 sdk_member_name: "myjavalib", 507 visibility: ["//visibility:public"], 508 apex_available: ["//apex_available:platform"], 509 jars: ["java/myjavalib.jar"], 510} 511 512java_import { 513 name: "myjavalib", 514 prefer: false, 515 visibility: ["//visibility:public"], 516 apex_available: ["//apex_available:platform"], 517 jars: ["java/myjavalib.jar"], 518} 519 520sdk_snapshot { 521 name: "mysdk@current", 522 visibility: ["//visibility:public"], 523 java_header_libs: ["mysdk_myjavalib@current"], 524} 525 `), 526 ) 527 }) 528 529 t.Run("SOONG_SDK_SNAPSHOT_PREFER=true", func(t *testing.T) { 530 result := android.GroupFixturePreparers( 531 preparer, 532 android.FixtureMergeEnv(map[string]string{ 533 "SOONG_SDK_SNAPSHOT_PREFER": "true", 534 }), 535 ).RunTest(t) 536 537 checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip") 538 539 CheckSnapshot(t, result, "mysdk", "", 540 checkAndroidBpContents(` 541// This is auto-generated. DO NOT EDIT. 542 543java_import { 544 name: "mysdk_myjavalib@current", 545 sdk_member_name: "myjavalib", 546 visibility: ["//visibility:public"], 547 apex_available: ["//apex_available:platform"], 548 jars: ["java/myjavalib.jar"], 549} 550 551java_import { 552 name: "myjavalib", 553 prefer: true, 554 visibility: ["//visibility:public"], 555 apex_available: ["//apex_available:platform"], 556 jars: ["java/myjavalib.jar"], 557} 558 559sdk_snapshot { 560 name: "mysdk@current", 561 visibility: ["//visibility:public"], 562 java_header_libs: ["mysdk_myjavalib@current"], 563} 564 `), 565 ) 566 }) 567 568 t.Run("SOONG_SDK_SNAPSHOT_VERSION=unversioned", func(t *testing.T) { 569 result := android.GroupFixturePreparers( 570 preparer, 571 android.FixtureMergeEnv(map[string]string{ 572 "SOONG_SDK_SNAPSHOT_VERSION": "unversioned", 573 }), 574 ).RunTest(t) 575 576 checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk.zip") 577 578 CheckSnapshot(t, result, "mysdk", "", 579 checkAndroidBpContents(` 580// This is auto-generated. DO NOT EDIT. 581 582java_import { 583 name: "myjavalib", 584 prefer: false, 585 visibility: ["//visibility:public"], 586 apex_available: ["//apex_available:platform"], 587 jars: ["java/myjavalib.jar"], 588} 589 `), 590 ) 591 }) 592 593 t.Run("SOONG_SDK_SNAPSHOT_VERSION=current", func(t *testing.T) { 594 result := android.GroupFixturePreparers( 595 preparer, 596 android.FixtureMergeEnv(map[string]string{ 597 "SOONG_SDK_SNAPSHOT_VERSION": "current", 598 }), 599 ).RunTest(t) 600 601 checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip") 602 603 CheckSnapshot(t, result, "mysdk", "", 604 checkAndroidBpContents(` 605// This is auto-generated. DO NOT EDIT. 606 607java_import { 608 name: "mysdk_myjavalib@current", 609 sdk_member_name: "myjavalib", 610 visibility: ["//visibility:public"], 611 apex_available: ["//apex_available:platform"], 612 jars: ["java/myjavalib.jar"], 613} 614 615java_import { 616 name: "myjavalib", 617 prefer: false, 618 visibility: ["//visibility:public"], 619 apex_available: ["//apex_available:platform"], 620 jars: ["java/myjavalib.jar"], 621} 622 623sdk_snapshot { 624 name: "mysdk@current", 625 visibility: ["//visibility:public"], 626 java_header_libs: ["mysdk_myjavalib@current"], 627} 628 `), 629 ) 630 }) 631 632 t.Run("SOONG_SDK_SNAPSHOT_VERSION=2", func(t *testing.T) { 633 result := android.GroupFixturePreparers( 634 preparer, 635 android.FixtureMergeEnv(map[string]string{ 636 "SOONG_SDK_SNAPSHOT_VERSION": "2", 637 }), 638 ).RunTest(t) 639 640 checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-2.zip") 641 642 CheckSnapshot(t, result, "mysdk", "", 643 checkAndroidBpContents(` 644// This is auto-generated. DO NOT EDIT. 645 646java_import { 647 name: "mysdk_myjavalib@2", 648 sdk_member_name: "myjavalib", 649 visibility: ["//visibility:public"], 650 apex_available: ["//apex_available:platform"], 651 jars: ["java/myjavalib.jar"], 652} 653 654sdk_snapshot { 655 name: "mysdk@2", 656 visibility: ["//visibility:public"], 657 java_header_libs: ["mysdk_myjavalib@2"], 658} 659 `), 660 // A versioned snapshot cannot be used on its own so add the source back in. 661 snapshotTestPreparer(checkSnapshotWithoutSource, android.FixtureWithRootAndroidBp(bp)), 662 ) 663 }) 664} 665