1package android 2 3import ( 4 "reflect" 5 "testing" 6 7 "github.com/google/blueprint" 8) 9 10var visibilityTests = []struct { 11 name string 12 fs MockFS 13 expectedErrors []string 14 effectiveVisibility map[qualifiedModuleName][]string 15}{ 16 { 17 name: "invalid visibility: empty list", 18 fs: MockFS{ 19 "top/Blueprints": []byte(` 20 mock_library { 21 name: "libexample", 22 visibility: [], 23 }`), 24 }, 25 expectedErrors: []string{`visibility: must contain at least one visibility rule`}, 26 }, 27 { 28 name: "invalid visibility: empty rule", 29 fs: MockFS{ 30 "top/Blueprints": []byte(` 31 mock_library { 32 name: "libexample", 33 visibility: [""], 34 }`), 35 }, 36 expectedErrors: []string{`visibility: invalid visibility pattern ""`}, 37 }, 38 { 39 name: "invalid visibility: unqualified", 40 fs: MockFS{ 41 "top/Blueprints": []byte(` 42 mock_library { 43 name: "libexample", 44 visibility: ["target"], 45 }`), 46 }, 47 expectedErrors: []string{`visibility: invalid visibility pattern "target"`}, 48 }, 49 { 50 name: "invalid visibility: empty namespace", 51 fs: MockFS{ 52 "top/Blueprints": []byte(` 53 mock_library { 54 name: "libexample", 55 visibility: ["//"], 56 }`), 57 }, 58 expectedErrors: []string{`visibility: invalid visibility pattern "//"`}, 59 }, 60 { 61 name: "invalid visibility: empty module", 62 fs: MockFS{ 63 "top/Blueprints": []byte(` 64 mock_library { 65 name: "libexample", 66 visibility: [":"], 67 }`), 68 }, 69 expectedErrors: []string{`visibility: invalid visibility pattern ":"`}, 70 }, 71 { 72 name: "invalid visibility: empty namespace and module", 73 fs: MockFS{ 74 "top/Blueprints": []byte(` 75 mock_library { 76 name: "libexample", 77 visibility: ["//:"], 78 }`), 79 }, 80 expectedErrors: []string{`visibility: invalid visibility pattern "//:"`}, 81 }, 82 { 83 name: "//visibility:unknown", 84 fs: MockFS{ 85 "top/Blueprints": []byte(` 86 mock_library { 87 name: "libexample", 88 visibility: ["//visibility:unknown"], 89 }`), 90 }, 91 expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`}, 92 }, 93 { 94 name: "//visibility:xxx mixed", 95 fs: MockFS{ 96 "top/Blueprints": []byte(` 97 mock_library { 98 name: "libexample", 99 visibility: ["//visibility:public", "//namespace"], 100 } 101 102 mock_library { 103 name: "libother", 104 visibility: ["//visibility:private", "//namespace"], 105 }`), 106 }, 107 expectedErrors: []string{ 108 `module "libother": visibility: cannot mix "//visibility:private"` + 109 ` with any other visibility rules`, 110 `module "libexample": visibility: cannot mix "//visibility:public"` + 111 ` with any other visibility rules`, 112 }, 113 }, 114 { 115 name: "//visibility:legacy_public", 116 fs: MockFS{ 117 "top/Blueprints": []byte(` 118 mock_library { 119 name: "libexample", 120 visibility: ["//visibility:legacy_public"], 121 }`), 122 }, 123 expectedErrors: []string{ 124 `module "libexample": visibility: //visibility:legacy_public must` + 125 ` not be used`, 126 }, 127 }, 128 { 129 // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g. 130 // the current directory, a nested directory and a directory in a separate tree. 131 name: "//visibility:public", 132 fs: MockFS{ 133 "top/Blueprints": []byte(` 134 mock_library { 135 name: "libexample", 136 visibility: ["//visibility:public"], 137 } 138 139 mock_library { 140 name: "libsamepackage", 141 deps: ["libexample"], 142 }`), 143 "top/nested/Blueprints": []byte(` 144 mock_library { 145 name: "libnested", 146 deps: ["libexample"], 147 }`), 148 "other/Blueprints": []byte(` 149 mock_library { 150 name: "libother", 151 deps: ["libexample"], 152 }`), 153 }, 154 }, 155 { 156 // Verify that //visibility:private allows the module to be referenced from the current 157 // directory only. 158 name: "//visibility:private", 159 fs: MockFS{ 160 "top/Blueprints": []byte(` 161 mock_library { 162 name: "libexample", 163 visibility: ["//visibility:private"], 164 } 165 166 mock_library { 167 name: "libsamepackage", 168 deps: ["libexample"], 169 }`), 170 "top/nested/Blueprints": []byte(` 171 mock_library { 172 name: "libnested", 173 deps: ["libexample"], 174 }`), 175 "other/Blueprints": []byte(` 176 mock_library { 177 name: "libother", 178 deps: ["libexample"], 179 }`), 180 }, 181 expectedErrors: []string{ 182 `module "libnested" variant "android_common": depends on //top:libexample which is not` + 183 ` visible to this module`, 184 `module "libother" variant "android_common": depends on //top:libexample which is not` + 185 ` visible to this module`, 186 }, 187 }, 188 { 189 // Verify that :__pkg__ allows the module to be referenced from the current directory only. 190 name: ":__pkg__", 191 fs: MockFS{ 192 "top/Blueprints": []byte(` 193 mock_library { 194 name: "libexample", 195 visibility: [":__pkg__"], 196 } 197 198 mock_library { 199 name: "libsamepackage", 200 deps: ["libexample"], 201 }`), 202 "top/nested/Blueprints": []byte(` 203 mock_library { 204 name: "libnested", 205 deps: ["libexample"], 206 }`), 207 "other/Blueprints": []byte(` 208 mock_library { 209 name: "libother", 210 deps: ["libexample"], 211 }`), 212 }, 213 expectedErrors: []string{ 214 `module "libnested" variant "android_common": depends on //top:libexample which is not` + 215 ` visible to this module`, 216 `module "libother" variant "android_common": depends on //top:libexample which is not` + 217 ` visible to this module`, 218 }, 219 }, 220 { 221 // Verify that //top/nested allows the module to be referenced from the current directory and 222 // the top/nested directory only, not a subdirectory of top/nested and not peak directory. 223 name: "//top/nested", 224 fs: MockFS{ 225 "top/Blueprints": []byte(` 226 mock_library { 227 name: "libexample", 228 visibility: ["//top/nested"], 229 } 230 231 mock_library { 232 name: "libsamepackage", 233 deps: ["libexample"], 234 }`), 235 "top/nested/Blueprints": []byte(` 236 mock_library { 237 name: "libnested", 238 deps: ["libexample"], 239 }`), 240 "top/nested/again/Blueprints": []byte(` 241 mock_library { 242 name: "libnestedagain", 243 deps: ["libexample"], 244 }`), 245 "peak/Blueprints": []byte(` 246 mock_library { 247 name: "libother", 248 deps: ["libexample"], 249 }`), 250 }, 251 expectedErrors: []string{ 252 `module "libother" variant "android_common": depends on //top:libexample which is not` + 253 ` visible to this module`, 254 `module "libnestedagain" variant "android_common": depends on //top:libexample which is not` + 255 ` visible to this module`, 256 }, 257 }, 258 { 259 // Verify that :__subpackages__ allows the module to be referenced from the current directory 260 // and sub directories but nowhere else. 261 name: ":__subpackages__", 262 fs: MockFS{ 263 "top/Blueprints": []byte(` 264 mock_library { 265 name: "libexample", 266 visibility: [":__subpackages__"], 267 } 268 269 mock_library { 270 name: "libsamepackage", 271 deps: ["libexample"], 272 }`), 273 "top/nested/Blueprints": []byte(` 274 mock_library { 275 name: "libnested", 276 deps: ["libexample"], 277 }`), 278 "peak/other/Blueprints": []byte(` 279 mock_library { 280 name: "libother", 281 deps: ["libexample"], 282 }`), 283 }, 284 expectedErrors: []string{ 285 `module "libother" variant "android_common": depends on //top:libexample which is not` + 286 ` visible to this module`, 287 }, 288 }, 289 { 290 // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current 291 // directory and sub directories but nowhere else. 292 name: "//top/nested:__subpackages__", 293 fs: MockFS{ 294 "top/Blueprints": []byte(` 295 mock_library { 296 name: "libexample", 297 visibility: ["//top/nested:__subpackages__", "//other"], 298 } 299 300 mock_library { 301 name: "libsamepackage", 302 deps: ["libexample"], 303 }`), 304 "top/nested/Blueprints": []byte(` 305 mock_library { 306 name: "libnested", 307 deps: ["libexample"], 308 }`), 309 "top/other/Blueprints": []byte(` 310 mock_library { 311 name: "libother", 312 deps: ["libexample"], 313 }`), 314 }, 315 expectedErrors: []string{ 316 `module "libother" variant "android_common": depends on //top:libexample which is not` + 317 ` visible to this module`, 318 }, 319 }, 320 { 321 // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from 322 // the current directory, top/nested and peak and all its subpackages. 323 name: `["//top/nested", "//peak:__subpackages__"]`, 324 fs: MockFS{ 325 "top/Blueprints": []byte(` 326 mock_library { 327 name: "libexample", 328 visibility: ["//top/nested", "//peak:__subpackages__"], 329 } 330 331 mock_library { 332 name: "libsamepackage", 333 deps: ["libexample"], 334 }`), 335 "top/nested/Blueprints": []byte(` 336 mock_library { 337 name: "libnested", 338 deps: ["libexample"], 339 }`), 340 "peak/other/Blueprints": []byte(` 341 mock_library { 342 name: "libother", 343 deps: ["libexample"], 344 }`), 345 }, 346 }, 347 { 348 // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__ 349 name: `//vendor`, 350 fs: MockFS{ 351 "top/Blueprints": []byte(` 352 mock_library { 353 name: "libexample", 354 visibility: ["//vendor:__subpackages__"], 355 } 356 357 mock_library { 358 name: "libsamepackage", 359 visibility: ["//vendor/apps/AcmeSettings"], 360 }`), 361 "vendor/Blueprints": []byte(` 362 mock_library { 363 name: "libvendorexample", 364 deps: ["libexample"], 365 visibility: ["//vendor/nested"], 366 }`), 367 "vendor/nested/Blueprints": []byte(` 368 mock_library { 369 name: "libvendornested", 370 deps: ["libexample", "libvendorexample"], 371 }`), 372 }, 373 expectedErrors: []string{ 374 `module "libsamepackage": visibility: "//vendor/apps/AcmeSettings"` + 375 ` is not allowed. Packages outside //vendor cannot make themselves visible to specific` + 376 ` targets within //vendor, they can only use //vendor:__subpackages__.`, 377 }, 378 }, 379 380 // Defaults propagation tests 381 { 382 // Check that visibility is the union of the defaults modules. 383 name: "defaults union, basic", 384 fs: MockFS{ 385 "top/Blueprints": []byte(` 386 mock_defaults { 387 name: "libexample_defaults", 388 visibility: ["//other"], 389 } 390 mock_library { 391 name: "libexample", 392 visibility: ["//top/nested"], 393 defaults: ["libexample_defaults"], 394 } 395 mock_library { 396 name: "libsamepackage", 397 deps: ["libexample"], 398 }`), 399 "top/nested/Blueprints": []byte(` 400 mock_library { 401 name: "libnested", 402 deps: ["libexample"], 403 }`), 404 "other/Blueprints": []byte(` 405 mock_library { 406 name: "libother", 407 deps: ["libexample"], 408 }`), 409 "outsider/Blueprints": []byte(` 410 mock_library { 411 name: "liboutsider", 412 deps: ["libexample"], 413 }`), 414 }, 415 expectedErrors: []string{ 416 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 417 ` visible to this module`, 418 }, 419 }, 420 { 421 name: "defaults union, multiple defaults", 422 fs: MockFS{ 423 "top/Blueprints": []byte(` 424 mock_defaults { 425 name: "libexample_defaults_1", 426 visibility: ["//other"], 427 } 428 mock_defaults { 429 name: "libexample_defaults_2", 430 visibility: ["//top/nested"], 431 } 432 mock_library { 433 name: "libexample", 434 defaults: ["libexample_defaults_1", "libexample_defaults_2"], 435 } 436 mock_library { 437 name: "libsamepackage", 438 deps: ["libexample"], 439 }`), 440 "top/nested/Blueprints": []byte(` 441 mock_library { 442 name: "libnested", 443 deps: ["libexample"], 444 }`), 445 "other/Blueprints": []byte(` 446 mock_library { 447 name: "libother", 448 deps: ["libexample"], 449 }`), 450 "outsider/Blueprints": []byte(` 451 mock_library { 452 name: "liboutsider", 453 deps: ["libexample"], 454 }`), 455 }, 456 expectedErrors: []string{ 457 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 458 ` visible to this module`, 459 }, 460 }, 461 { 462 name: "//visibility:public mixed with other in defaults", 463 fs: MockFS{ 464 "top/Blueprints": []byte(` 465 mock_defaults { 466 name: "libexample_defaults", 467 visibility: ["//visibility:public", "//namespace"], 468 } 469 mock_library { 470 name: "libexample", 471 defaults: ["libexample_defaults"], 472 }`), 473 }, 474 expectedErrors: []string{ 475 `module "libexample_defaults": visibility: cannot mix "//visibility:public"` + 476 ` with any other visibility rules`, 477 }, 478 }, 479 { 480 name: "//visibility:public overriding defaults", 481 fs: MockFS{ 482 "top/Blueprints": []byte(` 483 mock_defaults { 484 name: "libexample_defaults", 485 visibility: ["//namespace"], 486 } 487 mock_library { 488 name: "libexample", 489 visibility: ["//visibility:public"], 490 defaults: ["libexample_defaults"], 491 }`), 492 "outsider/Blueprints": []byte(` 493 mock_library { 494 name: "liboutsider", 495 deps: ["libexample"], 496 }`), 497 }, 498 effectiveVisibility: map[qualifiedModuleName][]string{ 499 qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"}, 500 }, 501 }, 502 { 503 name: "//visibility:public mixed with other from different defaults 1", 504 fs: MockFS{ 505 "top/Blueprints": []byte(` 506 mock_defaults { 507 name: "libexample_defaults_1", 508 visibility: ["//namespace"], 509 } 510 mock_defaults { 511 name: "libexample_defaults_2", 512 visibility: ["//visibility:public"], 513 } 514 mock_library { 515 name: "libexample", 516 defaults: ["libexample_defaults_1", "libexample_defaults_2"], 517 }`), 518 "outsider/Blueprints": []byte(` 519 mock_library { 520 name: "liboutsider", 521 deps: ["libexample"], 522 }`), 523 }, 524 }, 525 { 526 name: "//visibility:public mixed with other from different defaults 2", 527 fs: MockFS{ 528 "top/Blueprints": []byte(` 529 mock_defaults { 530 name: "libexample_defaults_1", 531 visibility: ["//visibility:public"], 532 } 533 mock_defaults { 534 name: "libexample_defaults_2", 535 visibility: ["//namespace"], 536 } 537 mock_library { 538 name: "libexample", 539 defaults: ["libexample_defaults_1", "libexample_defaults_2"], 540 }`), 541 "outsider/Blueprints": []byte(` 542 mock_library { 543 name: "liboutsider", 544 deps: ["libexample"], 545 }`), 546 }, 547 }, 548 { 549 name: "//visibility:private in defaults", 550 fs: MockFS{ 551 "top/Blueprints": []byte(` 552 mock_defaults { 553 name: "libexample_defaults", 554 visibility: ["//visibility:private"], 555 } 556 mock_library { 557 name: "libexample", 558 defaults: ["libexample_defaults"], 559 } 560 mock_library { 561 name: "libsamepackage", 562 deps: ["libexample"], 563 }`), 564 "top/nested/Blueprints": []byte(` 565 mock_library { 566 name: "libnested", 567 deps: ["libexample"], 568 }`), 569 "other/Blueprints": []byte(` 570 mock_library { 571 name: "libother", 572 deps: ["libexample"], 573 }`), 574 }, 575 expectedErrors: []string{ 576 `module "libnested" variant "android_common": depends on //top:libexample which is not` + 577 ` visible to this module`, 578 `module "libother" variant "android_common": depends on //top:libexample which is not` + 579 ` visible to this module`, 580 }, 581 }, 582 { 583 name: "//visibility:private mixed with other in defaults", 584 fs: MockFS{ 585 "top/Blueprints": []byte(` 586 mock_defaults { 587 name: "libexample_defaults", 588 visibility: ["//visibility:private", "//namespace"], 589 } 590 mock_library { 591 name: "libexample", 592 defaults: ["libexample_defaults"], 593 }`), 594 }, 595 expectedErrors: []string{ 596 `module "libexample_defaults": visibility: cannot mix "//visibility:private"` + 597 ` with any other visibility rules`, 598 }, 599 }, 600 { 601 name: "//visibility:private overriding defaults", 602 fs: MockFS{ 603 "top/Blueprints": []byte(` 604 mock_defaults { 605 name: "libexample_defaults", 606 visibility: ["//namespace"], 607 } 608 mock_library { 609 name: "libexample", 610 visibility: ["//visibility:private"], 611 defaults: ["libexample_defaults"], 612 }`), 613 }, 614 expectedErrors: []string{ 615 `module "libexample": visibility: cannot mix "//visibility:private"` + 616 ` with any other visibility rules`, 617 }, 618 }, 619 { 620 name: "//visibility:private in defaults overridden", 621 fs: MockFS{ 622 "top/Blueprints": []byte(` 623 mock_defaults { 624 name: "libexample_defaults", 625 visibility: ["//visibility:private"], 626 } 627 mock_library { 628 name: "libexample", 629 visibility: ["//namespace"], 630 defaults: ["libexample_defaults"], 631 }`), 632 }, 633 expectedErrors: []string{ 634 `module "libexample": visibility: cannot mix "//visibility:private"` + 635 ` with any other visibility rules`, 636 }, 637 }, 638 { 639 name: "//visibility:private override //visibility:public", 640 fs: MockFS{ 641 "top/Blueprints": []byte(` 642 mock_defaults { 643 name: "libexample_defaults", 644 visibility: ["//visibility:public"], 645 } 646 mock_library { 647 name: "libexample", 648 visibility: ["//visibility:private"], 649 defaults: ["libexample_defaults"], 650 }`), 651 }, 652 expectedErrors: []string{ 653 `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`, 654 }, 655 }, 656 { 657 name: "//visibility:public override //visibility:private", 658 fs: MockFS{ 659 "top/Blueprints": []byte(` 660 mock_defaults { 661 name: "libexample_defaults", 662 visibility: ["//visibility:private"], 663 } 664 mock_library { 665 name: "libexample", 666 visibility: ["//visibility:public"], 667 defaults: ["libexample_defaults"], 668 }`), 669 }, 670 expectedErrors: []string{ 671 `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`, 672 }, 673 }, 674 { 675 name: "//visibility:override must be first in the list", 676 fs: MockFS{ 677 "top/Blueprints": []byte(` 678 mock_library { 679 name: "libexample", 680 visibility: ["//other", "//visibility:override", "//namespace"], 681 }`), 682 }, 683 expectedErrors: []string{ 684 `module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`, 685 }, 686 }, 687 { 688 name: "//visibility:override discards //visibility:private", 689 fs: MockFS{ 690 "top/Blueprints": []byte(` 691 mock_defaults { 692 name: "libexample_defaults", 693 visibility: ["//visibility:private"], 694 } 695 mock_library { 696 name: "libexample", 697 // Make this visibility to //other but not //visibility:private 698 visibility: ["//visibility:override", "//other"], 699 defaults: ["libexample_defaults"], 700 }`), 701 "other/Blueprints": []byte(` 702 mock_library { 703 name: "libother", 704 deps: ["libexample"], 705 }`), 706 }, 707 }, 708 { 709 name: "//visibility:override discards //visibility:public", 710 fs: MockFS{ 711 "top/Blueprints": []byte(` 712 mock_defaults { 713 name: "libexample_defaults", 714 visibility: ["//visibility:public"], 715 } 716 mock_library { 717 name: "libexample", 718 // Make this visibility to //other but not //visibility:public 719 visibility: ["//visibility:override", "//other"], 720 defaults: ["libexample_defaults"], 721 }`), 722 "other/Blueprints": []byte(` 723 mock_library { 724 name: "libother", 725 deps: ["libexample"], 726 }`), 727 "namespace/Blueprints": []byte(` 728 mock_library { 729 name: "libnamespace", 730 deps: ["libexample"], 731 }`), 732 }, 733 expectedErrors: []string{ 734 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`, 735 }, 736 }, 737 { 738 name: "//visibility:override discards defaults supplied rules", 739 fs: MockFS{ 740 "top/Blueprints": []byte(` 741 mock_defaults { 742 name: "libexample_defaults", 743 visibility: ["//namespace"], 744 } 745 mock_library { 746 name: "libexample", 747 // Make this visibility to //other but not //namespace 748 visibility: ["//visibility:override", "//other"], 749 defaults: ["libexample_defaults"], 750 }`), 751 "other/Blueprints": []byte(` 752 mock_library { 753 name: "libother", 754 deps: ["libexample"], 755 }`), 756 "namespace/Blueprints": []byte(` 757 mock_library { 758 name: "libnamespace", 759 deps: ["libexample"], 760 }`), 761 }, 762 expectedErrors: []string{ 763 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`, 764 }, 765 }, 766 { 767 name: "//visibility:override can override //visibility:public with //visibility:private", 768 fs: MockFS{ 769 "top/Blueprints": []byte(` 770 mock_defaults { 771 name: "libexample_defaults", 772 visibility: ["//visibility:public"], 773 } 774 mock_library { 775 name: "libexample", 776 visibility: ["//visibility:override", "//visibility:private"], 777 defaults: ["libexample_defaults"], 778 }`), 779 "namespace/Blueprints": []byte(` 780 mock_library { 781 name: "libnamespace", 782 deps: ["libexample"], 783 }`), 784 }, 785 expectedErrors: []string{ 786 `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`, 787 }, 788 }, 789 { 790 name: "//visibility:override can override //visibility:private with //visibility:public", 791 fs: MockFS{ 792 "top/Blueprints": []byte(` 793 mock_defaults { 794 name: "libexample_defaults", 795 visibility: ["//visibility:private"], 796 } 797 mock_library { 798 name: "libexample", 799 visibility: ["//visibility:override", "//visibility:public"], 800 defaults: ["libexample_defaults"], 801 }`), 802 "namespace/Blueprints": []byte(` 803 mock_library { 804 name: "libnamespace", 805 deps: ["libexample"], 806 }`), 807 }, 808 }, 809 { 810 name: "//visibility:private mixed with itself", 811 fs: MockFS{ 812 "top/Blueprints": []byte(` 813 mock_defaults { 814 name: "libexample_defaults_1", 815 visibility: ["//visibility:private"], 816 } 817 mock_defaults { 818 name: "libexample_defaults_2", 819 visibility: ["//visibility:private"], 820 } 821 mock_library { 822 name: "libexample", 823 visibility: ["//visibility:private"], 824 defaults: ["libexample_defaults_1", "libexample_defaults_2"], 825 }`), 826 "outsider/Blueprints": []byte(` 827 mock_library { 828 name: "liboutsider", 829 deps: ["libexample"], 830 }`), 831 }, 832 expectedErrors: []string{ 833 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 834 ` visible to this module`, 835 }, 836 }, 837 838 // Defaults module's defaults_visibility tests 839 { 840 name: "defaults_visibility invalid", 841 fs: MockFS{ 842 "top/Blueprints": []byte(` 843 mock_defaults { 844 name: "top_defaults", 845 defaults_visibility: ["//visibility:invalid"], 846 }`), 847 }, 848 expectedErrors: []string{ 849 `defaults_visibility: unrecognized visibility rule "//visibility:invalid"`, 850 }, 851 }, 852 { 853 name: "defaults_visibility overrides package default", 854 fs: MockFS{ 855 "top/Blueprints": []byte(` 856 package { 857 default_visibility: ["//visibility:private"], 858 } 859 mock_defaults { 860 name: "top_defaults", 861 defaults_visibility: ["//visibility:public"], 862 }`), 863 "outsider/Blueprints": []byte(` 864 mock_library { 865 name: "liboutsider", 866 defaults: ["top_defaults"], 867 }`), 868 }, 869 }, 870 871 // Package default_visibility tests 872 { 873 name: "package default_visibility property is checked", 874 fs: MockFS{ 875 "top/Blueprints": []byte(` 876 package { 877 default_visibility: ["//visibility:invalid"], 878 }`), 879 }, 880 expectedErrors: []string{`default_visibility: unrecognized visibility rule "//visibility:invalid"`}, 881 }, 882 { 883 // This test relies on the default visibility being legacy_public. 884 name: "package default_visibility property used when no visibility specified", 885 fs: MockFS{ 886 "top/Blueprints": []byte(` 887 package { 888 default_visibility: ["//visibility:private"], 889 } 890 891 mock_library { 892 name: "libexample", 893 }`), 894 "outsider/Blueprints": []byte(` 895 mock_library { 896 name: "liboutsider", 897 deps: ["libexample"], 898 }`), 899 }, 900 expectedErrors: []string{ 901 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 902 ` visible to this module`, 903 }, 904 }, 905 { 906 name: "package default_visibility public does not override visibility private", 907 fs: MockFS{ 908 "top/Blueprints": []byte(` 909 package { 910 default_visibility: ["//visibility:public"], 911 } 912 913 mock_library { 914 name: "libexample", 915 visibility: ["//visibility:private"], 916 }`), 917 "outsider/Blueprints": []byte(` 918 mock_library { 919 name: "liboutsider", 920 deps: ["libexample"], 921 }`), 922 }, 923 expectedErrors: []string{ 924 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 925 ` visible to this module`, 926 }, 927 }, 928 { 929 name: "package default_visibility private does not override visibility public", 930 fs: MockFS{ 931 "top/Blueprints": []byte(` 932 package { 933 default_visibility: ["//visibility:private"], 934 } 935 936 mock_library { 937 name: "libexample", 938 visibility: ["//visibility:public"], 939 }`), 940 "outsider/Blueprints": []byte(` 941 mock_library { 942 name: "liboutsider", 943 deps: ["libexample"], 944 }`), 945 }, 946 }, 947 { 948 name: "package default_visibility :__subpackages__", 949 fs: MockFS{ 950 "top/Blueprints": []byte(` 951 package { 952 default_visibility: [":__subpackages__"], 953 } 954 955 mock_library { 956 name: "libexample", 957 }`), 958 "top/nested/Blueprints": []byte(` 959 mock_library { 960 name: "libnested", 961 deps: ["libexample"], 962 }`), 963 "outsider/Blueprints": []byte(` 964 mock_library { 965 name: "liboutsider", 966 deps: ["libexample"], 967 }`), 968 }, 969 expectedErrors: []string{ 970 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 971 ` visible to this module`, 972 }, 973 }, 974 { 975 name: "package default_visibility inherited to subpackages", 976 fs: MockFS{ 977 "top/Blueprints": []byte(` 978 package { 979 default_visibility: ["//outsider"], 980 } 981 982 mock_library { 983 name: "libexample", 984 visibility: [":__subpackages__"], 985 }`), 986 "top/nested/Blueprints": []byte(` 987 mock_library { 988 name: "libnested", 989 deps: ["libexample"], 990 }`), 991 "outsider/Blueprints": []byte(` 992 mock_library { 993 name: "liboutsider", 994 deps: ["libexample", "libnested"], 995 }`), 996 }, 997 expectedErrors: []string{ 998 `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + 999 ` visible to this module`, 1000 }, 1001 }, 1002 { 1003 name: "package default_visibility inherited to subpackages", 1004 fs: MockFS{ 1005 "top/Blueprints": []byte(` 1006 package { 1007 default_visibility: ["//visibility:private"], 1008 }`), 1009 "top/nested/Blueprints": []byte(` 1010 package { 1011 default_visibility: ["//outsider"], 1012 } 1013 1014 mock_library { 1015 name: "libnested", 1016 }`), 1017 "top/other/Blueprints": []byte(` 1018 mock_library { 1019 name: "libother", 1020 }`), 1021 "outsider/Blueprints": []byte(` 1022 mock_library { 1023 name: "liboutsider", 1024 deps: ["libother", "libnested"], 1025 }`), 1026 }, 1027 expectedErrors: []string{ 1028 `module "liboutsider" variant "android_common": depends on //top/other:libother which is` + 1029 ` not visible to this module`, 1030 }, 1031 }, 1032 { 1033 name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)", 1034 fs: MockFS{ 1035 "prebuilts/Blueprints": []byte(` 1036 prebuilt { 1037 name: "module", 1038 visibility: ["//top/other"], 1039 }`), 1040 "top/sources/source_file": nil, 1041 "top/sources/Blueprints": []byte(` 1042 source { 1043 name: "module", 1044 visibility: ["//top/other"], 1045 }`), 1046 "top/other/source_file": nil, 1047 "top/other/Blueprints": []byte(` 1048 source { 1049 name: "other", 1050 deps: [":module"], 1051 }`), 1052 }, 1053 }, 1054 { 1055 name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)", 1056 fs: MockFS{ 1057 "prebuilts/Blueprints": []byte(` 1058 prebuilt { 1059 name: "module", 1060 visibility: ["//top/other"], 1061 prefer: true, 1062 }`), 1063 "top/sources/source_file": nil, 1064 "top/sources/Blueprints": []byte(` 1065 source { 1066 name: "module", 1067 visibility: ["//top/other"], 1068 }`), 1069 "top/other/source_file": nil, 1070 "top/other/Blueprints": []byte(` 1071 source { 1072 name: "other", 1073 deps: [":module"], 1074 }`), 1075 }, 1076 }, 1077 { 1078 name: "ensure visibility properties are checked for correctness", 1079 fs: MockFS{ 1080 "top/Blueprints": []byte(` 1081 mock_parent { 1082 name: "parent", 1083 visibility: ["//top/nested"], 1084 child: { 1085 name: "libchild", 1086 visibility: ["top/other"], 1087 }, 1088 }`), 1089 }, 1090 expectedErrors: []string{ 1091 `module "parent": child.visibility: invalid visibility pattern "top/other"`, 1092 }, 1093 }, 1094 { 1095 name: "invalid visibility added to child detected during gather phase", 1096 fs: MockFS{ 1097 "top/Blueprints": []byte(` 1098 mock_parent { 1099 name: "parent", 1100 visibility: ["//top/nested"], 1101 child: { 1102 name: "libchild", 1103 invalid_visibility: ["top/other"], 1104 }, 1105 }`), 1106 }, 1107 expectedErrors: []string{ 1108 // That this error is reported against the child not the parent shows it was 1109 // not being detected in the parent which is correct as invalid_visibility is 1110 // purposely not added to the list of visibility properties to check, and was 1111 // in fact detected in the child in the gather phase. Contrast this error message 1112 // with the preceding one. 1113 `module "libchild" \(created by module "parent"\): visibility: invalid visibility pattern "top/other"`, 1114 }, 1115 }, 1116 { 1117 name: "automatic visibility inheritance enabled", 1118 fs: MockFS{ 1119 "top/Blueprints": []byte(` 1120 mock_parent { 1121 name: "parent", 1122 visibility: ["//top/nested"], 1123 child: { 1124 name: "libchild", 1125 visibility: ["//top/other"], 1126 }, 1127 }`), 1128 "top/nested/Blueprints": []byte(` 1129 mock_library { 1130 name: "libnested", 1131 deps: ["libchild"], 1132 }`), 1133 "top/other/Blueprints": []byte(` 1134 mock_library { 1135 name: "libother", 1136 deps: ["libchild"], 1137 }`), 1138 }, 1139 }, 1140} 1141 1142func TestVisibility(t *testing.T) { 1143 for _, test := range visibilityTests { 1144 t.Run(test.name, func(t *testing.T) { 1145 result := GroupFixturePreparers( 1146 // General preparers in alphabetical order as test infrastructure will enforce correct 1147 // registration order. 1148 PrepareForTestWithArchMutator, 1149 PrepareForTestWithDefaults, 1150 PrepareForTestWithOverrides, 1151 PrepareForTestWithPackageModule, 1152 PrepareForTestWithPrebuilts, 1153 PrepareForTestWithVisibility, 1154 1155 // Additional test specific preparers. 1156 FixtureRegisterWithContext(func(ctx RegistrationContext) { 1157 ctx.RegisterModuleType("mock_library", newMockLibraryModule) 1158 ctx.RegisterModuleType("mock_parent", newMockParentFactory) 1159 ctx.RegisterModuleType("mock_defaults", defaultsFactory) 1160 }), 1161 prepareForTestWithFakePrebuiltModules, 1162 // Add additional files to the mock filesystem 1163 test.fs.AddToFixture(), 1164 ). 1165 ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). 1166 RunTest(t) 1167 1168 if test.effectiveVisibility != nil { 1169 checkEffectiveVisibility(t, result, test.effectiveVisibility) 1170 } 1171 }) 1172 } 1173} 1174 1175func checkEffectiveVisibility(t *testing.T, result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) { 1176 for moduleName, expectedRules := range effectiveVisibility { 1177 rule := effectiveVisibilityRules(result.Config, moduleName) 1178 stringRules := rule.Strings() 1179 AssertDeepEquals(t, "effective rules mismatch", expectedRules, stringRules) 1180 } 1181} 1182 1183type mockLibraryProperties struct { 1184 Deps []string 1185} 1186 1187type mockLibraryModule struct { 1188 ModuleBase 1189 DefaultableModuleBase 1190 properties mockLibraryProperties 1191} 1192 1193func newMockLibraryModule() Module { 1194 m := &mockLibraryModule{} 1195 m.AddProperties(&m.properties) 1196 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) 1197 InitDefaultableModule(m) 1198 return m 1199} 1200 1201type dependencyTag struct { 1202 blueprint.BaseDependencyTag 1203 name string 1204} 1205 1206func (j *mockLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { 1207 ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...) 1208} 1209 1210func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) { 1211} 1212 1213type mockDefaults struct { 1214 ModuleBase 1215 DefaultsModuleBase 1216} 1217 1218func defaultsFactory() Module { 1219 m := &mockDefaults{} 1220 InitDefaultsModule(m) 1221 return m 1222} 1223 1224type mockParentProperties struct { 1225 Child struct { 1226 Name *string 1227 1228 // Visibility to pass to the child module. 1229 Visibility []string 1230 1231 // Purposely not validated visibility to pass to the child. 1232 Invalid_visibility []string 1233 } 1234} 1235 1236type mockParent struct { 1237 ModuleBase 1238 DefaultableModuleBase 1239 properties mockParentProperties 1240} 1241 1242func (p *mockParent) GenerateAndroidBuildActions(ModuleContext) { 1243} 1244 1245func newMockParentFactory() Module { 1246 m := &mockParent{} 1247 m.AddProperties(&m.properties) 1248 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) 1249 InitDefaultableModule(m) 1250 AddVisibilityProperty(m, "child.visibility", &m.properties.Child.Visibility) 1251 1252 m.SetDefaultableHook(func(ctx DefaultableHookContext) { 1253 visibility := m.properties.Child.Visibility 1254 visibility = append(visibility, m.properties.Child.Invalid_visibility...) 1255 ctx.CreateModule(newMockLibraryModule, &struct { 1256 Name *string 1257 Visibility []string 1258 }{m.properties.Child.Name, visibility}) 1259 }) 1260 return m 1261} 1262 1263func testVisibilityRuleSet(t *testing.T, rules, extra, expected []string) { 1264 t.Helper() 1265 set := &visibilityRuleSet{rules} 1266 err := set.Widen(extra) 1267 if err != nil { 1268 t.Error(err) 1269 return 1270 } 1271 actual := set.Strings() 1272 if !reflect.DeepEqual(actual, expected) { 1273 t.Errorf("mismatching rules after extend: expected %#v, actual %#v", expected, actual) 1274 } 1275} 1276 1277func TestVisibilityRuleSet(t *testing.T) { 1278 t.Run("extend empty", func(t *testing.T) { 1279 testVisibilityRuleSet(t, nil, []string{"//foo"}, []string{"//foo"}) 1280 }) 1281 t.Run("extend", func(t *testing.T) { 1282 testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar"}, []string{"//bar", "//foo"}) 1283 }) 1284 t.Run("extend duplicate", func(t *testing.T) { 1285 testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar", "//foo"}, []string{"//bar", "//foo"}) 1286 }) 1287 t.Run("extend public", func(t *testing.T) { 1288 testVisibilityRuleSet(t, []string{"//visibility:public"}, []string{"//foo"}, []string{"//visibility:public"}) 1289 }) 1290 t.Run("extend private", func(t *testing.T) { 1291 testVisibilityRuleSet(t, []string{"//visibility:private"}, []string{"//foo"}, []string{"//foo"}) 1292 }) 1293 t.Run("extend with public", func(t *testing.T) { 1294 testVisibilityRuleSet(t, []string{"//foo"}, []string{"//visibility:public"}, []string{"//visibility:public"}) 1295 }) 1296 t.Run("extend with private", func(t *testing.T) { 1297 t.Helper() 1298 set := &visibilityRuleSet{[]string{"//foo"}} 1299 err := set.Widen([]string{"//visibility:private"}) 1300 expectedError := `"//visibility:private" does not widen the visibility` 1301 if err == nil { 1302 t.Errorf("missing error") 1303 } else if err.Error() != expectedError { 1304 t.Errorf("expected error %q found error %q", expectedError, err) 1305 } 1306 }) 1307} 1308