1// Copyright 2024 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 apex 16 17import ( 18 "testing" 19 20 "android/soong/aconfig/codegen" 21 "android/soong/android" 22 "android/soong/cc" 23 "android/soong/genrule" 24 "android/soong/java" 25 "android/soong/rust" 26 27 "github.com/google/blueprint/proptools" 28) 29 30var withAconfigValidationError = android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 31 variables.AconfigContainerValidation = "error" 32 variables.BuildId = proptools.StringPtr("TEST.BUILD_ID") 33}) 34 35func TestValidationAcrossContainersExportedPass(t *testing.T) { 36 testCases := []struct { 37 name string 38 bp string 39 }{ 40 { 41 name: "Java lib passes for exported containers cross", 42 bp: apex_default_bp + ` 43 apex { 44 name: "myapex", 45 manifest: ":myapex.manifest", 46 androidManifest: ":myapex.androidmanifest", 47 key: "myapex.key", 48 java_libs: [ 49 "my_java_library_foo", 50 ], 51 updatable: false, 52 } 53 java_library { 54 name: "my_java_library_foo", 55 srcs: ["foo/bar/MyClass.java"], 56 sdk_version: "none", 57 system_modules: "none", 58 static_libs: ["my_java_aconfig_library_foo"], 59 apex_available: [ 60 "myapex", 61 ], 62 } 63 aconfig_declarations { 64 name: "my_aconfig_declarations_foo", 65 package: "com.example.package", 66 container: "otherapex", 67 srcs: ["foo.aconfig"], 68 exportable: true, 69 } 70 java_aconfig_library { 71 name: "my_java_aconfig_library_foo", 72 aconfig_declarations: "my_aconfig_declarations_foo", 73 mode: "exported", 74 apex_available: [ 75 "myapex", 76 ], 77 }`, 78 }, 79 { 80 name: "Android app passes for exported containers cross", 81 bp: apex_default_bp + ` 82 apex { 83 name: "myapex", 84 manifest: ":myapex.manifest", 85 androidManifest: ":myapex.androidmanifest", 86 key: "myapex.key", 87 apps: [ 88 "my_android_app_foo", 89 ], 90 updatable: false, 91 } 92 android_app { 93 name: "my_android_app_foo", 94 srcs: ["foo/MyClass.java"], 95 sdk_version: "none", 96 system_modules: "none", 97 stl: "none", 98 static_libs: ["my_java_library_bar"], 99 apex_available: [ "myapex" ], 100 } 101 java_library { 102 name: "my_java_library_bar", 103 srcs: ["foo/bar/MyClass.java"], 104 sdk_version: "none", 105 system_modules: "none", 106 static_libs: ["my_java_aconfig_library_bar"], 107 apex_available: [ 108 "myapex", 109 ], 110 } 111 aconfig_declarations { 112 name: "my_aconfig_declarations_bar", 113 package: "com.example.package", 114 container: "otherapex", 115 srcs: ["bar.aconfig"], 116 exportable: true, 117 } 118 java_aconfig_library { 119 name: "my_java_aconfig_library_bar", 120 aconfig_declarations: "my_aconfig_declarations_bar", 121 mode: "exported", 122 apex_available: [ 123 "myapex", 124 ], 125 }`, 126 }, 127 { 128 name: "Cc lib passes for exported containers cross", 129 bp: apex_default_bp + ` 130 apex { 131 name: "myapex", 132 manifest: ":myapex.manifest", 133 androidManifest: ":myapex.androidmanifest", 134 key: "myapex.key", 135 native_shared_libs: [ 136 "my_cc_library_bar", 137 ], 138 binaries: [ 139 "my_cc_binary_baz", 140 ], 141 updatable: false, 142 } 143 cc_library { 144 name: "my_cc_library_bar", 145 srcs: ["foo/bar/MyClass.cc"], 146 static_libs: [ 147 "my_cc_aconfig_library_bar", 148 "my_cc_aconfig_library_baz", 149 ], 150 apex_available: [ 151 "myapex", 152 ], 153 } 154 cc_binary { 155 name: "my_cc_binary_baz", 156 srcs: ["foo/bar/MyClass.cc"], 157 static_libs: ["my_cc_aconfig_library_baz"], 158 apex_available: [ 159 "myapex", 160 ], 161 } 162 cc_library { 163 name: "server_configurable_flags", 164 srcs: ["server_configurable_flags.cc"], 165 } 166 cc_library { 167 name: "libbase", 168 srcs: ["libbase.cc"], 169 apex_available: [ 170 "myapex", 171 ], 172 } 173 cc_library { 174 name: "libaconfig_storage_read_api_cc", 175 srcs: ["libaconfig_storage_read_api_cc.cc"], 176 } 177 aconfig_declarations { 178 name: "my_aconfig_declarations_bar", 179 package: "com.example.package", 180 container: "otherapex", 181 srcs: ["bar.aconfig"], 182 exportable: true, 183 } 184 cc_aconfig_library { 185 name: "my_cc_aconfig_library_bar", 186 aconfig_declarations: "my_aconfig_declarations_bar", 187 apex_available: [ 188 "myapex", 189 ], 190 mode: "exported", 191 } 192 aconfig_declarations { 193 name: "my_aconfig_declarations_baz", 194 package: "com.example.package", 195 container: "otherapex", 196 srcs: ["baz.aconfig"], 197 exportable: true, 198 } 199 cc_aconfig_library { 200 name: "my_cc_aconfig_library_baz", 201 aconfig_declarations: "my_aconfig_declarations_baz", 202 apex_available: [ 203 "myapex", 204 ], 205 mode: "exported", 206 }`, 207 }, 208 { 209 name: "Rust lib passes for exported containers cross", 210 bp: apex_default_bp + ` 211 apex { 212 name: "myapex", 213 manifest: ":myapex.manifest", 214 androidManifest: ":myapex.androidmanifest", 215 key: "myapex.key", 216 native_shared_libs: ["libmy_rust_library"], 217 binaries: ["my_rust_binary"], 218 updatable: false, 219 } 220 rust_library { 221 name: "libflags_rust", // test mock 222 crate_name: "flags_rust", 223 srcs: ["lib.rs"], 224 apex_available: ["myapex"], 225 } 226 rust_library { 227 name: "liblazy_static", // test mock 228 crate_name: "lazy_static", 229 srcs: ["src/lib.rs"], 230 apex_available: ["myapex"], 231 } 232 rust_library { 233 name: "libaconfig_storage_read_api", // test mock 234 crate_name: "aconfig_storage_read_api", 235 srcs: ["src/lib.rs"], 236 apex_available: ["myapex"], 237 } 238 rust_library { 239 name: "liblogger", // test mock 240 crate_name: "logger", 241 srcs: ["src/lib.rs"], 242 apex_available: ["myapex"], 243 } 244 rust_library { 245 name: "liblog_rust", // test mock 246 crate_name: "log_rust", 247 srcs: ["src/lib.rs"], 248 apex_available: ["myapex"], 249 } 250 rust_ffi_shared { 251 name: "libmy_rust_library", 252 srcs: ["src/lib.rs"], 253 rustlibs: ["libmy_rust_aconfig_library_foo"], 254 crate_name: "my_rust_library", 255 apex_available: ["myapex"], 256 } 257 rust_binary { 258 name: "my_rust_binary", 259 srcs: ["foo/bar/MyClass.rs"], 260 rustlibs: ["libmy_rust_aconfig_library_bar"], 261 apex_available: ["myapex"], 262 } 263 aconfig_declarations { 264 name: "my_aconfig_declarations_foo", 265 package: "com.example.package", 266 container: "otherapex", 267 srcs: ["foo.aconfig"], 268 } 269 aconfig_declarations { 270 name: "my_aconfig_declarations_bar", 271 package: "com.example.package", 272 container: "otherapex", 273 srcs: ["bar.aconfig"], 274 } 275 rust_aconfig_library { 276 name: "libmy_rust_aconfig_library_foo", 277 aconfig_declarations: "my_aconfig_declarations_foo", 278 crate_name: "my_rust_aconfig_library_foo", 279 apex_available: ["myapex"], 280 mode: "exported", 281 } 282 rust_aconfig_library { 283 name: "libmy_rust_aconfig_library_bar", 284 aconfig_declarations: "my_aconfig_declarations_bar", 285 crate_name: "my_rust_aconfig_library_bar", 286 apex_available: ["myapex"], 287 mode: "exported", 288 }`, 289 }, 290 } 291 for _, test := range testCases { 292 t.Run(test.name, func(t *testing.T) { 293 android.GroupFixturePreparers( 294 java.PrepareForTestWithJavaDefaultModules, 295 cc.PrepareForTestWithCcBuildComponents, 296 rust.PrepareForTestWithRustDefaultModules, 297 codegen.PrepareForTestWithAconfigBuildComponents, 298 PrepareForTestWithApexBuildComponents, 299 prepareForTestWithMyapex, 300 withAconfigValidationError, 301 ). 302 RunTestWithBp(t, test.bp) 303 }) 304 } 305} 306 307func TestValidationAcrossContainersNotExportedFail(t *testing.T) { 308 testCases := []struct { 309 name string 310 expectedError string 311 bp string 312 }{ 313 { 314 name: "Java lib fails for non-exported containers cross", 315 bp: apex_default_bp + ` 316 apex { 317 name: "myapex", 318 manifest: ":myapex.manifest", 319 androidManifest: ":myapex.androidmanifest", 320 key: "myapex.key", 321 java_libs: [ 322 "my_java_library_foo", 323 ], 324 updatable: false, 325 } 326 java_library { 327 name: "my_java_library_foo", 328 srcs: ["foo/bar/MyClass.java"], 329 sdk_version: "none", 330 system_modules: "none", 331 static_libs: ["my_java_aconfig_library_foo"], 332 apex_available: [ 333 "myapex", 334 ], 335 } 336 aconfig_declarations { 337 name: "my_aconfig_declarations_foo", 338 package: "com.example.package", 339 container: "otherapex", 340 srcs: ["foo.aconfig"], 341 } 342 java_aconfig_library { 343 name: "my_java_aconfig_library_foo", 344 aconfig_declarations: "my_aconfig_declarations_foo", 345 apex_available: [ 346 "myapex", 347 ], 348 }`, 349 expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`, 350 }, 351 { 352 name: "Android app fails for non-exported containers cross", 353 bp: apex_default_bp + ` 354 apex { 355 name: "myapex", 356 manifest: ":myapex.manifest", 357 androidManifest: ":myapex.androidmanifest", 358 key: "myapex.key", 359 apps: [ 360 "my_android_app_foo", 361 ], 362 updatable: false, 363 } 364 android_app { 365 name: "my_android_app_foo", 366 srcs: ["foo/MyClass.java"], 367 sdk_version: "none", 368 system_modules: "none", 369 stl: "none", 370 static_libs: ["my_java_library_foo"], 371 apex_available: [ "myapex" ], 372 } 373 java_library { 374 name: "my_java_library_foo", 375 srcs: ["foo/bar/MyClass.java"], 376 sdk_version: "none", 377 system_modules: "none", 378 static_libs: ["my_java_aconfig_library_foo"], 379 apex_available: [ 380 "myapex", 381 ], 382 } 383 aconfig_declarations { 384 name: "my_aconfig_declarations_foo", 385 package: "com.example.package", 386 container: "otherapex", 387 srcs: ["bar.aconfig"], 388 } 389 java_aconfig_library { 390 name: "my_java_aconfig_library_foo", 391 aconfig_declarations: "my_aconfig_declarations_foo", 392 apex_available: [ 393 "myapex", 394 ], 395 }`, 396 expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`, 397 }, 398 { 399 name: "Cc lib fails for non-exported containers cross", 400 bp: apex_default_bp + ` 401 apex { 402 name: "myapex", 403 manifest: ":myapex.manifest", 404 androidManifest: ":myapex.androidmanifest", 405 key: "myapex.key", 406 native_shared_libs: [ 407 "my_cc_library_foo", 408 ], 409 updatable: false, 410 } 411 cc_library { 412 name: "my_cc_library_foo", 413 srcs: ["foo/bar/MyClass.cc"], 414 shared_libs: [ 415 "my_cc_aconfig_library_foo", 416 ], 417 apex_available: [ 418 "myapex", 419 ], 420 } 421 cc_library { 422 name: "server_configurable_flags", 423 srcs: ["server_configurable_flags.cc"], 424 } 425 cc_library { 426 name: "libbase", 427 srcs: ["libbase.cc"], 428 apex_available: [ 429 "myapex", 430 ], 431 } 432 cc_library { 433 name: "libaconfig_storage_read_api_cc", 434 srcs: ["libaconfig_storage_read_api_cc.cc"], 435 } 436 aconfig_declarations { 437 name: "my_aconfig_declarations_foo", 438 package: "com.example.package", 439 container: "otherapex", 440 srcs: ["foo.aconfig"], 441 } 442 cc_aconfig_library { 443 name: "my_cc_aconfig_library_foo", 444 aconfig_declarations: "my_aconfig_declarations_foo", 445 apex_available: [ 446 "myapex", 447 ], 448 }`, 449 expectedError: `.*my_cc_library_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`, 450 }, 451 { 452 name: "Cc binary fails for non-exported containers cross", 453 bp: apex_default_bp + ` 454 apex { 455 name: "myapex", 456 manifest: ":myapex.manifest", 457 androidManifest: ":myapex.androidmanifest", 458 key: "myapex.key", 459 binaries: [ 460 "my_cc_binary_foo", 461 ], 462 updatable: false, 463 } 464 cc_library { 465 name: "my_cc_library_foo", 466 srcs: ["foo/bar/MyClass.cc"], 467 static_libs: [ 468 "my_cc_aconfig_library_foo", 469 ], 470 apex_available: [ 471 "myapex", 472 ], 473 } 474 cc_binary { 475 name: "my_cc_binary_foo", 476 srcs: ["foo/bar/MyClass.cc"], 477 static_libs: ["my_cc_library_foo"], 478 apex_available: [ 479 "myapex", 480 ], 481 } 482 cc_library { 483 name: "server_configurable_flags", 484 srcs: ["server_configurable_flags.cc"], 485 } 486 cc_library { 487 name: "libbase", 488 srcs: ["libbase.cc"], 489 apex_available: [ 490 "myapex", 491 ], 492 } 493 cc_library { 494 name: "libaconfig_storage_read_api_cc", 495 srcs: ["libaconfig_storage_read_api_cc.cc"], 496 } 497 aconfig_declarations { 498 name: "my_aconfig_declarations_foo", 499 package: "com.example.package", 500 container: "otherapex", 501 srcs: ["foo.aconfig"], 502 } 503 cc_aconfig_library { 504 name: "my_cc_aconfig_library_foo", 505 aconfig_declarations: "my_aconfig_declarations_foo", 506 apex_available: [ 507 "myapex", 508 ], 509 }`, 510 expectedError: `.*my_cc_binary_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`, 511 }, 512 { 513 name: "Rust lib fails for non-exported containers cross", 514 bp: apex_default_bp + ` 515 apex { 516 name: "myapex", 517 manifest: ":myapex.manifest", 518 androidManifest: ":myapex.androidmanifest", 519 key: "myapex.key", 520 native_shared_libs: ["libmy_rust_library"], 521 updatable: false, 522 } 523 rust_library { 524 name: "libflags_rust", // test mock 525 crate_name: "flags_rust", 526 srcs: ["lib.rs"], 527 apex_available: ["myapex"], 528 } 529 rust_library { 530 name: "liblazy_static", // test mock 531 crate_name: "lazy_static", 532 srcs: ["src/lib.rs"], 533 apex_available: ["myapex"], 534 } 535 rust_library { 536 name: "libaconfig_storage_read_api", // test mock 537 crate_name: "aconfig_storage_read_api", 538 srcs: ["src/lib.rs"], 539 apex_available: ["myapex"], 540 } 541 rust_library { 542 name: "liblogger", // test mock 543 crate_name: "logger", 544 srcs: ["src/lib.rs"], 545 apex_available: ["myapex"], 546 } 547 rust_library { 548 name: "liblog_rust", // test mock 549 crate_name: "log_rust", 550 srcs: ["src/lib.rs"], 551 apex_available: ["myapex"], 552 } 553 rust_ffi_shared { 554 name: "libmy_rust_library", 555 srcs: ["src/lib.rs"], 556 rustlibs: ["libmy_rust_aconfig_library_foo"], 557 crate_name: "my_rust_library", 558 apex_available: ["myapex"], 559 } 560 aconfig_declarations { 561 name: "my_aconfig_declarations_foo", 562 package: "com.example.package", 563 container: "otherapex", 564 srcs: ["foo.aconfig"], 565 } 566 rust_aconfig_library { 567 name: "libmy_rust_aconfig_library_foo", 568 aconfig_declarations: "my_aconfig_declarations_foo", 569 crate_name: "my_rust_aconfig_library_foo", 570 apex_available: ["myapex"], 571 }`, 572 expectedError: `.*libmy_rust_aconfig_library_foo/myapex depends on libmy_rust_aconfig_library_foo/otherapex/production across containers`, 573 }, 574 { 575 name: "Rust binary fails for non-exported containers cross", 576 bp: apex_default_bp + ` 577 apex { 578 name: "myapex", 579 manifest: ":myapex.manifest", 580 androidManifest: ":myapex.androidmanifest", 581 key: "myapex.key", 582 binaries: ["my_rust_binary"], 583 updatable: false, 584 } 585 rust_library { 586 name: "libflags_rust", // test mock 587 crate_name: "flags_rust", 588 srcs: ["lib.rs"], 589 apex_available: ["myapex"], 590 } 591 rust_library { 592 name: "liblazy_static", // test mock 593 crate_name: "lazy_static", 594 srcs: ["src/lib.rs"], 595 apex_available: ["myapex"], 596 } 597 rust_library { 598 name: "libaconfig_storage_read_api", // test mock 599 crate_name: "aconfig_storage_read_api", 600 srcs: ["src/lib.rs"], 601 apex_available: ["myapex"], 602 } 603 rust_library { 604 name: "liblogger", // test mock 605 crate_name: "logger", 606 srcs: ["src/lib.rs"], 607 apex_available: ["myapex"], 608 } 609 rust_library { 610 name: "liblog_rust", // test mock 611 crate_name: "log_rust", 612 srcs: ["src/lib.rs"], 613 apex_available: ["myapex"], 614 } 615 rust_binary { 616 name: "my_rust_binary", 617 srcs: ["foo/bar/MyClass.rs"], 618 rustlibs: ["libmy_rust_aconfig_library_bar"], 619 apex_available: ["myapex"], 620 } 621 aconfig_declarations { 622 name: "my_aconfig_declarations_bar", 623 package: "com.example.package", 624 container: "otherapex", 625 srcs: ["bar.aconfig"], 626 } 627 rust_aconfig_library { 628 name: "libmy_rust_aconfig_library_bar", 629 aconfig_declarations: "my_aconfig_declarations_bar", 630 crate_name: "my_rust_aconfig_library_bar", 631 apex_available: ["myapex"], 632 }`, 633 expectedError: `.*libmy_rust_aconfig_library_bar/myapex depends on libmy_rust_aconfig_library_bar/otherapex/production across containers`, 634 }, 635 { 636 name: "Aconfig validation propagate along sourceOrOutputDependencyTag", 637 bp: apex_default_bp + ` 638 apex { 639 name: "myapex", 640 manifest: ":myapex.manifest", 641 androidManifest: ":myapex.androidmanifest", 642 key: "myapex.key", 643 apps: [ 644 "my_android_app_foo", 645 ], 646 updatable: false, 647 } 648 android_app { 649 name: "my_android_app_foo", 650 srcs: ["foo/MyClass.java"], 651 sdk_version: "none", 652 system_modules: "none", 653 stl: "none", 654 static_libs: ["my_java_library_foo"], 655 apex_available: [ "myapex" ], 656 } 657 java_library { 658 name: "my_java_library_foo", 659 srcs: [":my_genrule_foo"], 660 sdk_version: "none", 661 system_modules: "none", 662 apex_available: [ 663 "myapex", 664 ], 665 } 666 aconfig_declarations_group { 667 name: "my_aconfig_declarations_group_foo", 668 java_aconfig_libraries: [ 669 "my_java_aconfig_library_foo", 670 ], 671 } 672 filegroup { 673 name: "my_filegroup_foo_srcjars", 674 srcs: [ 675 ":my_aconfig_declarations_group_foo{.srcjars}", 676 ], 677 } 678 genrule { 679 name: "my_genrule_foo", 680 srcs: [":my_filegroup_foo_srcjars"], 681 cmd: "cp $(in) $(out)", 682 out: ["my_genrule_foo.srcjar"], 683 } 684 aconfig_declarations { 685 name: "my_aconfig_declarations_foo", 686 package: "com.example.package", 687 container: "otherapex", 688 srcs: ["bar.aconfig"], 689 } 690 java_aconfig_library { 691 name: "my_java_aconfig_library_foo", 692 aconfig_declarations: "my_aconfig_declarations_foo", 693 apex_available: [ 694 "myapex", 695 ], 696 }`, 697 expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`, 698 }, 699 } 700 for _, test := range testCases { 701 t.Run(test.name, func(t *testing.T) { 702 errorHandler := android.FixtureExpectsNoErrors 703 if test.expectedError != "" { 704 errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError) 705 } 706 android.GroupFixturePreparers( 707 java.PrepareForTestWithJavaDefaultModules, 708 cc.PrepareForTestWithCcBuildComponents, 709 rust.PrepareForTestWithRustDefaultModules, 710 codegen.PrepareForTestWithAconfigBuildComponents, 711 genrule.PrepareForIntegrationTestWithGenrule, 712 PrepareForTestWithApexBuildComponents, 713 prepareForTestWithMyapex, 714 withAconfigValidationError, 715 ). 716 ExtendWithErrorHandler(errorHandler). 717 RunTestWithBp(t, test.bp) 718 }) 719 } 720} 721 722func TestValidationNotPropagateAcrossShared(t *testing.T) { 723 testCases := []struct { 724 name string 725 bp string 726 }{ 727 { 728 name: "Java shared lib not propagate aconfig validation", 729 bp: apex_default_bp + ` 730 apex { 731 name: "myapex", 732 manifest: ":myapex.manifest", 733 androidManifest: ":myapex.androidmanifest", 734 key: "myapex.key", 735 java_libs: [ 736 "my_java_library_bar", 737 ], 738 updatable: false, 739 } 740 java_library { 741 name: "my_java_library_bar", 742 srcs: ["foo/bar/MyClass.java"], 743 sdk_version: "none", 744 system_modules: "none", 745 libs: ["my_java_library_foo"], 746 apex_available: [ 747 "myapex", 748 ], 749 } 750 java_library { 751 name: "my_java_library_foo", 752 srcs: ["foo/bar/MyClass.java"], 753 sdk_version: "none", 754 system_modules: "none", 755 static_libs: ["my_java_aconfig_library_foo"], 756 apex_available: [ 757 "myapex", 758 ], 759 } 760 aconfig_declarations { 761 name: "my_aconfig_declarations_foo", 762 package: "com.example.package", 763 container: "otherapex", 764 srcs: ["foo.aconfig"], 765 } 766 java_aconfig_library { 767 name: "my_java_aconfig_library_foo", 768 aconfig_declarations: "my_aconfig_declarations_foo", 769 apex_available: [ 770 "myapex", 771 ], 772 }`, 773 }, 774 } 775 for _, test := range testCases { 776 t.Run(test.name, func(t *testing.T) { 777 android.GroupFixturePreparers( 778 java.PrepareForTestWithJavaDefaultModules, 779 cc.PrepareForTestWithCcBuildComponents, 780 rust.PrepareForTestWithRustDefaultModules, 781 codegen.PrepareForTestWithAconfigBuildComponents, 782 PrepareForTestWithApexBuildComponents, 783 prepareForTestWithMyapex, 784 withAconfigValidationError, 785 ). 786 RunTestWithBp(t, test.bp) 787 }) 788 } 789} 790