|  | package android | 
|  |  | 
|  | import ( | 
|  | "testing" | 
|  |  | 
|  | "github.com/google/blueprint" | 
|  | ) | 
|  |  | 
|  | var visibilityTests = []struct { | 
|  | name           string | 
|  | fs             map[string][]byte | 
|  | expectedErrors []string | 
|  | }{ | 
|  | { | 
|  | name: "invalid visibility: empty list", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: must contain at least one visibility rule`}, | 
|  | }, | 
|  | { | 
|  | name: "invalid visibility: empty rule", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [""], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: invalid visibility pattern ""`}, | 
|  | }, | 
|  | { | 
|  | name: "invalid visibility: unqualified", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["target"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: invalid visibility pattern "target"`}, | 
|  | }, | 
|  | { | 
|  | name: "invalid visibility: empty namespace", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: invalid visibility pattern "//"`}, | 
|  | }, | 
|  | { | 
|  | name: "invalid visibility: empty module", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [":"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: invalid visibility pattern ":"`}, | 
|  | }, | 
|  | { | 
|  | name: "invalid visibility: empty namespace and module", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//:"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`visibility: invalid visibility pattern "//:"`}, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:unknown", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:unknown"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`}, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:xxx mixed", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:public", "//namespace"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libother", | 
|  | visibility: ["//visibility:private", "//namespace"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libother": visibility: cannot mix "//visibility:private"` + | 
|  | ` with any other visibility rules`, | 
|  | `module "libexample": visibility: cannot mix "//visibility:public"` + | 
|  | ` with any other visibility rules`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:legacy_public", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:legacy_public"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libexample": visibility: //visibility:legacy_public must` + | 
|  | ` not be used`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g. | 
|  | // the current directory, a nested directory and a directory in a separate tree. | 
|  | name: "//visibility:public", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:public"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that //visibility:private allows the module to be referenced from the current | 
|  | // directory only. | 
|  | name: "//visibility:private", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:private"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libnested" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that :__pkg__ allows the module to be referenced from the current directory only. | 
|  | name: ":__pkg__", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [":__pkg__"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libnested" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that //top/nested allows the module to be referenced from the current directory and | 
|  | // the top/nested directory only, not a subdirectory of top/nested and not peak directory. | 
|  | name: "//top/nested", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//top/nested"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/again/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnestedagain", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "peak/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | `module "libnestedagain" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that :__subpackages__ allows the module to be referenced from the current directory | 
|  | // and sub directories but nowhere else. | 
|  | name: ":__subpackages__", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [":__subpackages__"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "peak/other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current | 
|  | // directory and sub directories but nowhere else. | 
|  | name: "//top/nested:__subpackages__", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//top/nested:__subpackages__", "//other"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from | 
|  | // the current directory, top/nested and peak and all its subpackages. | 
|  | name: `["//top/nested", "//peak:__subpackages__"]`, | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//top/nested", "//peak:__subpackages__"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "peak/other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__ | 
|  | name: `//vendor`, | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//vendor:__subpackages__"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | visibility: ["//vendor/apps/AcmeSettings"], | 
|  | }`), | 
|  | "vendor/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libvendorexample", | 
|  | deps: ["libexample"], | 
|  | visibility: ["//vendor/nested"], | 
|  | }`), | 
|  | "vendor/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libvendornested", | 
|  | deps: ["libexample", "libvendorexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libsamepackage": visibility: "//vendor/apps/AcmeSettings"` + | 
|  | ` is not allowed. Packages outside //vendor cannot make themselves visible to specific` + | 
|  | ` targets within //vendor, they can only use //vendor:__subpackages__.`, | 
|  | }, | 
|  | }, | 
|  |  | 
|  | // Defaults propagation tests | 
|  | { | 
|  | // Check that visibility is the union of the defaults modules. | 
|  | name: "defaults union, basic", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//other"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//top/nested"], | 
|  | defaults: ["libexample_defaults"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "defaults union, multiple defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_1", | 
|  | visibility: ["//other"], | 
|  | } | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_2", | 
|  | visibility: ["//top/nested"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults_1", "libexample_defaults_2"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:public mixed with other in defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//visibility:public", "//namespace"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libexample_defaults": visibility: cannot mix "//visibility:public"` + | 
|  | ` with any other visibility rules`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:public overriding defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//namespace"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:public"], | 
|  | defaults: ["libexample_defaults"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:public mixed with other from different defaults 1", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_1", | 
|  | visibility: ["//namespace"], | 
|  | } | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_2", | 
|  | visibility: ["//visibility:public"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults_1", "libexample_defaults_2"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:public mixed with other from different defaults 2", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_1", | 
|  | visibility: ["//visibility:public"], | 
|  | } | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_2", | 
|  | visibility: ["//namespace"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults_1", "libexample_defaults_2"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:private in defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//visibility:private"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libsamepackage", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libnested" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | `module "libother" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:private mixed with other in defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//visibility:private", "//namespace"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | defaults: ["libexample_defaults"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libexample_defaults": visibility: cannot mix "//visibility:private"` + | 
|  | ` with any other visibility rules`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:private overriding defaults", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//namespace"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:private"], | 
|  | defaults: ["libexample_defaults"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libexample": visibility: cannot mix "//visibility:private"` + | 
|  | ` with any other visibility rules`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:private in defaults overridden", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults", | 
|  | visibility: ["//visibility:private"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//namespace"], | 
|  | defaults: ["libexample_defaults"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "libexample": visibility: cannot mix "//visibility:private"` + | 
|  | ` with any other visibility rules`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "//visibility:private mixed with itself", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_1", | 
|  | visibility: ["//visibility:private"], | 
|  | } | 
|  | mock_defaults { | 
|  | name: "libexample_defaults_2", | 
|  | visibility: ["//visibility:private"], | 
|  | } | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:private"], | 
|  | defaults: ["libexample_defaults_1", "libexample_defaults_2"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  |  | 
|  | // Defaults module's defaults_visibility tests | 
|  | { | 
|  | name: "defaults_visibility invalid", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | mock_defaults { | 
|  | name: "top_defaults", | 
|  | defaults_visibility: ["//visibility:invalid"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `defaults_visibility: unrecognized visibility rule "//visibility:invalid"`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "defaults_visibility overrides package default", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:private"], | 
|  | } | 
|  | mock_defaults { | 
|  | name: "top_defaults", | 
|  | defaults_visibility: ["//visibility:public"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | defaults: ["top_defaults"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  |  | 
|  | // Package default_visibility tests | 
|  | { | 
|  | name: "package default_visibility property is checked", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:invalid"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{`default_visibility: unrecognized visibility rule "//visibility:invalid"`}, | 
|  | }, | 
|  | { | 
|  | // This test relies on the default visibility being legacy_public. | 
|  | name: "package default_visibility property used when no visibility specified", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:private"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "package default_visibility public does not override visibility private", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:public"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:private"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "package default_visibility private does not override visibility public", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:private"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: ["//visibility:public"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "package default_visibility :__subpackages__", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: [":__subpackages__"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "package default_visibility inherited to subpackages", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//outsider"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libexample", | 
|  | visibility: [":__subpackages__"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | deps: ["libexample"], | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libexample", "libnested"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top:libexample which is not` + | 
|  | ` visible to this module`, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "package default_visibility inherited to subpackages", | 
|  | fs: map[string][]byte{ | 
|  | "top/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//visibility:private"], | 
|  | }`), | 
|  | "top/nested/Blueprints": []byte(` | 
|  | package { | 
|  | default_visibility: ["//outsider"], | 
|  | } | 
|  |  | 
|  | mock_library { | 
|  | name: "libnested", | 
|  | }`), | 
|  | "top/other/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "libother", | 
|  | }`), | 
|  | "outsider/Blueprints": []byte(` | 
|  | mock_library { | 
|  | name: "liboutsider", | 
|  | deps: ["libother", "libnested"], | 
|  | }`), | 
|  | }, | 
|  | expectedErrors: []string{ | 
|  | `module "liboutsider" variant "android_common": depends on //top/other:libother which is` + | 
|  | ` not visible to this module`, | 
|  | }, | 
|  | }, | 
|  | } | 
|  |  | 
|  | func TestVisibility(t *testing.T) { | 
|  | for _, test := range visibilityTests { | 
|  | t.Run(test.name, func(t *testing.T) { | 
|  | _, errs := testVisibility(buildDir, test.fs) | 
|  |  | 
|  | CheckErrorsAgainstExpectations(t, errs, test.expectedErrors) | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) { | 
|  |  | 
|  | // Create a new config per test as visibility information is stored in the config. | 
|  | config := TestArchConfig(buildDir, nil) | 
|  |  | 
|  | ctx := NewTestArchContext() | 
|  | ctx.RegisterModuleType("package", ModuleFactoryAdaptor(PackageFactory)) | 
|  | ctx.RegisterModuleType("mock_library", ModuleFactoryAdaptor(newMockLibraryModule)) | 
|  | ctx.RegisterModuleType("mock_defaults", ModuleFactoryAdaptor(defaultsFactory)) | 
|  | ctx.PreArchMutators(registerPackageRenamer) | 
|  | ctx.PreArchMutators(registerVisibilityRuleChecker) | 
|  | ctx.PreArchMutators(RegisterDefaultsPreArchMutators) | 
|  | ctx.PreArchMutators(registerVisibilityRuleGatherer) | 
|  | ctx.PostDepsMutators(registerVisibilityRuleEnforcer) | 
|  | ctx.Register() | 
|  |  | 
|  | ctx.MockFileSystem(fs) | 
|  |  | 
|  | _, errs := ctx.ParseBlueprintsFiles(".") | 
|  | if len(errs) > 0 { | 
|  | return ctx, errs | 
|  | } | 
|  |  | 
|  | _, errs = ctx.PrepareBuildActions(config) | 
|  | return ctx, errs | 
|  | } | 
|  |  | 
|  | type mockLibraryProperties struct { | 
|  | Deps []string | 
|  | } | 
|  |  | 
|  | type mockLibraryModule struct { | 
|  | ModuleBase | 
|  | DefaultableModuleBase | 
|  | properties mockLibraryProperties | 
|  | } | 
|  |  | 
|  | func newMockLibraryModule() Module { | 
|  | m := &mockLibraryModule{} | 
|  | m.AddProperties(&m.properties) | 
|  | InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) | 
|  | InitDefaultableModule(m) | 
|  | return m | 
|  | } | 
|  |  | 
|  | type dependencyTag struct { | 
|  | blueprint.BaseDependencyTag | 
|  | name string | 
|  | } | 
|  |  | 
|  | func (j *mockLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { | 
|  | ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...) | 
|  | } | 
|  |  | 
|  | func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) { | 
|  | } | 
|  |  | 
|  | type mockDefaults struct { | 
|  | ModuleBase | 
|  | DefaultsModuleBase | 
|  | } | 
|  |  | 
|  | func defaultsFactory() Module { | 
|  | m := &mockDefaults{} | 
|  | InitDefaultsModule(m) | 
|  | return m | 
|  | } |