Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/android/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 56 kB image not shown  

Quelle  visibility_test.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

package android

import (
 "reflect"
 "testing"

 "github.com/google/blueprint"
)

var visibilityTests = []struct {
 name                string
 fs                  MockFS
 expectedErrors      []string
 effectiveVisibility map[qualifiedModuleName][]string
}{
 {
  name: "invalid visibility: empty list",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [],
    }`),
  },
  expectedErrors: []string{`visibility: must contain at least one visibility rule`},
 },
 {
  name: "invalid visibility: empty rule",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [""],
    }`),
  },
  expectedErrors: []string{`visibility: invalid visibility pattern ""`},
 },
 {
  name: "invalid visibility: unqualified",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["target"],
    }`),
  },
  expectedErrors: []string{`visibility: invalid visibility pattern "target"`},
 },
 {
  name: "invalid visibility: empty namespace",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//"],
    }`),
  },
  expectedErrors: []string{`visibility: invalid visibility pattern "//"`},
 },
 {
  name: "invalid visibility: empty module",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [":"],
    }`),
  },
  expectedErrors: []string{`visibility: invalid visibility pattern ":"`},
 },
 {
  name: "invalid visibility: empty namespace and module",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//:"],
    }`),
  },
  expectedErrors: []string{`visibility: invalid visibility pattern "//:"`},
 },
 {
  name: "//visibility:unknown",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//visibility:unknown"],
    }`),
  },
  expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`},
 },
 {
  name: "//visibility:xxx mixed",
  fs: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }

    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }

    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  // Verify that //visibility:private allows the module to be referenced from the current
  // directory only.
  name: "//visibility:private",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "other/Android.bp": []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 //visibility:private allows the module to be referenced from the current
  // directory only.
  name: "//visibility:private (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "nested-notice" references "//top:libexample" which is not visible to this` +
    ` module\nYou may need to add "//top/nested" to its visibility`,
   `module "other-notice" references "//top:libexample" which is not visible to this module\n` +
    `You may need to add "//other" to its visibility`,
  },
 },
 {
  // Verify that :__pkg__ allows the module to be referenced from the current directory only.
  name: ":__pkg__",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [":__pkg__"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "other/Android.bp": []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__ (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [":__pkg__"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "nested-notice" references "//top:libexample" which is not visible to this module`,
   `module "other-notice" references "//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: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "top/nested/again/Android.bp": []byte(`
    mock_library {
     name: "libnestedagain",
     deps: ["libexample"],
    }`),
   "peak/Android.bp": []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 //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 (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "top/nested/again/Android.bp": []byte(`
    gen_notice {
     name: "nestedagain-notice",
     for: ["libexample"],
    }`),
   "peak/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "other-notice" references "//top:libexample" which is not visible to this module`,
   `module "nestedagain-notice" references "//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: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [":__subpackages__"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "peak/other/Android.bp": []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 :__subpackages__ allows the module to be referenced from the current directory
  // and sub directories but nowhere else.
  name: ":__subpackages__ (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: [":__subpackages__"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "peak/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "other-notice" references "//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: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested:__subpackages__", "//other"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "top/other/Android.bp": []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__ (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested:__subpackages__", "//other"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "top/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "other-notice" references "//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: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested", "//peak:__subpackages__"],
    }

    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "peak/other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
  },
 },
 {
  // 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__ (notices)"]`,
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//top/nested", "//peak:__subpackages__"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "peak/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__
  name: `//vendor`,
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//vendor:__subpackages__"],
    }

    mock_library {
     name: "libsamepackage",
     visibility: ["//vendor/apps/AcmeSettings"],
    }`),
   "vendor/Android.bp": []byte(`
    mock_library {
     name: "libvendorexample",
     deps: ["libexample"],
     visibility: ["//vendor/nested"],
    }`),
   "vendor/nested/Android.bp": []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: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
   "outsider/Android.bp": []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`,
  },
 },
 {
  // Check that visibility is the union of the defaults modules.
  name: "defaults union, basic (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//other"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//top/nested"],
     defaults: ["libexample_defaults"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "defaults union, multiple defaults",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
   "outsider/Android.bp": []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 (notices)",
  fs: MockFS{
   "top/Android.bp": []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"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "//visibility:public mixed with other in defaults",
  fs: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//namespace"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
     defaults: ["libexample_defaults"],
    }`),
   "outsider/Android.bp": []byte(`
    mock_library {
     name: "liboutsider",
     deps: ["libexample"],
    }`),
  },
  effectiveVisibility: map[qualifiedModuleName][]string{
   qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"},
  },
 },
 {
  name: "//visibility:public overriding defaults (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//namespace"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
     defaults: ["libexample_defaults"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  effectiveVisibility: map[qualifiedModuleName][]string{
   qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"},
  },
 },
 {
  name: "//visibility:public mixed with other from different defaults 1",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    mock_library {
     name: "liboutsider",
     deps: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:public mixed with other from different defaults 1",
  fs: MockFS{
   "top/Android.bp": []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"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:public mixed with other from different defaults 2",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    mock_library {
     name: "liboutsider",
     deps: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:public mixed with other from different defaults 2 (notices)",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:private in defaults",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     defaults: ["libexample_defaults"],
    }
    mock_library {
     name: "libsamepackage",
     deps: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "other/Android.bp": []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 in defaults (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     defaults: ["libexample_defaults"],
    }

    gen_notice {
     name: "libexample-notice",
     for: ["libexample"],
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "nested-notice" references "//top:libexample" which is not visible to this module`,
   `module "other-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "//visibility:private mixed with other in defaults",
  fs: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []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 override //visibility:public",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:public"],
    }
    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:public override //visibility:private",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
     defaults: ["libexample_defaults"],
    }`),
  },
  expectedErrors: []string{
   `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
  },
 },
 {
  name: "//visibility:override must be first in the list",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "libexample",
     visibility: ["//other", "//visibility:override", "//namespace"],
    }`),
  },
  expectedErrors: []string{
   `module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`,
  },
 },
 {
  name: "//visibility:override discards //visibility:private",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //visibility:private
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:override discards //visibility:private (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //visibility:private
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:override discards //visibility:public",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:public"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //visibility:public
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
   "namespace/Android.bp": []byte(`
    mock_library {
     name: "libnamespace",
     deps: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `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`,
  },
 },
 {
  name: "//visibility:override discards //visibility:public (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:public"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //visibility:public
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
   "namespace/Android.bp": []byte(`
    gen_notice {
     name: "namespace-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "namespace-notice" references "//top:libexample" which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
  },
 },
 {
  name: "//visibility:override discards defaults supplied rules",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//namespace"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //namespace
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libexample"],
    }`),
   "namespace/Android.bp": []byte(`
    mock_library {
     name: "libnamespace",
     deps: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `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`,
  },
 },
 {
  name: "//visibility:override discards defaults supplied rules (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//namespace"],
    }
    mock_library {
     name: "libexample",
     // Make this visibility to //other but not //namespace
     visibility: ["//visibility:override", "//other"],
     defaults: ["libexample_defaults"],
    }`),
   "other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libexample"],
    }`),
   "namespace/Android.bp": []byte(`
    gen_notice {
     name: "namespace-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "namespace-notice" references "//top:libexample" which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
  },
 },
 {
  name: "//visibility:override can override //visibility:public with //visibility:private",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:public"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:override", "//visibility:private"],
     defaults: ["libexample_defaults"],
    }`),
   "namespace/Android.bp": []byte(`
    mock_library {
     name: "libnamespace",
     deps: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
  },
 },
 {
  name: "//visibility:override can override //visibility:public with //visibility:private (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:public"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:override", "//visibility:private"],
     defaults: ["libexample_defaults"],
    }`),
   "namespace/Android.bp": []byte(`
    gen_notice {
     name: "namespace-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "namespace-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "//visibility:override can override //visibility:private with //visibility:public",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:override", "//visibility:public"],
     defaults: ["libexample_defaults"],
    }`),
   "namespace/Android.bp": []byte(`
    mock_library {
     name: "libnamespace",
     deps: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:override can override //visibility:private with //visibility:public (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_defaults {
     name: "libexample_defaults",
     visibility: ["//visibility:private"],
    }
    mock_library {
     name: "libexample",
     visibility: ["//visibility:override", "//visibility:public"],
     defaults: ["libexample_defaults"],
    }`),
   "namespace/Android.bp": []byte(`
    gen_notice {
     name: "namespace-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  name: "//visibility:private mixed with itself",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []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:private mixed with itself (notices)",
  fs: MockFS{
   "top/Android.bp": []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/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },

 // Defaults module's defaults_visibility tests
 {
  name: "defaults_visibility invalid",
  fs: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }
    mock_defaults {
     name: "top_defaults",
     defaults_visibility: ["//visibility:public"],
    }`),
   "outsider/Android.bp": []byte(`
    mock_library {
     name: "liboutsider",
     defaults: ["top_defaults"],
    }`),
  },
 },

 // Package default_visibility tests
 {
  name: "package default_visibility property is checked",
  fs: MockFS{
   "top/Android.bp": []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: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libexample",
    }`),
   "outsider/Android.bp": []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`,
  },
 },
 {
  // This test relies on the default visibility being legacy_public.
  name: "package default_visibility property used when no visibility specified (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libexample",
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "package default_visibility public does not override visibility private",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:public"],
    }

    mock_library {
     name: "libexample",
     visibility: ["//visibility:private"],
    }`),
   "outsider/Android.bp": []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 (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:public"],
    }

    mock_library {
     name: "libexample",
     visibility: ["//visibility:private"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "package default_visibility private does not override visibility public",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
    }`),
   "outsider/Android.bp": []byte(`
    mock_library {
     name: "liboutsider",
     deps: ["libexample"],
    }`),
  },
 },
 {
  name: "package default_visibility private does not override visibility public (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }

    mock_library {
     name: "libexample",
     visibility: ["//visibility:public"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
 },
 {
  name: "package default_visibility :__subpackages__",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: [":__subpackages__"],
    }

    mock_library {
     name: "libexample",
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "outsider/Android.bp": []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 :__subpackages__ (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: [":__subpackages__"],
    }

    mock_library {
     name: "libexample",
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "package default_visibility inherited to subpackages",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//outsider"],
    }

    mock_library {
     name: "libexample",
     visibility: [":__subpackages__"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }`),
   "outsider/Android.bp": []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 (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//outsider"],
    }

    mock_library {
     name: "libexample",
     visibility: [":__subpackages__"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libexample"],
    }

    gen_notice {
     name: "nested-notice",
     for: ["libexample"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libexample", "libnested"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top:libexample" which is not visible to this module`,
  },
 },
 {
  name: "package default_visibility inherited to subpackages",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }`),
   "top/nested/Android.bp": []byte(`
    package {
     default_visibility: ["//outsider"],
    }

    mock_library {
     name: "libnested",
    }`),
   "top/other/Android.bp": []byte(`
    mock_library {
     name: "libother",
    }`),
   "outsider/Android.bp": []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`,
  },
 },
 {
  name: "package default_visibility inherited to subpackages (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    package {
     default_visibility: ["//visibility:private"],
    }`),
   "top/nested/Android.bp": []byte(`
    package {
     default_visibility: ["//outsider"],
    }

    mock_library {
     name: "libnested",
    }`),
   "top/other/Android.bp": []byte(`
    mock_library {
     name: "libother",
    }

    gen_notice {
     name: "other-notice",
     for: ["libother"],
    }`),
   "outsider/Android.bp": []byte(`
    gen_notice {
     name: "outsider-notice",
     for: ["libother", "libnested"],
    }`),
  },
  expectedErrors: []string{
   `module "outsider-notice" references "//top/other:libother" which is not visible to this` +
    ` module\nYou may need to add "//outsider" to its visibility`,
  },
 },
 {
  name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)",
  fs: MockFS{
   "prebuilts/Android.bp": []byte(`
    prebuilt {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/sources/source_file": nil,
   "top/sources/Android.bp": []byte(`
    source {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/other/source_file": nil,
   "top/other/Android.bp": []byte(`
    source {
     name: "other",
     deps: [":module"],
    }`),
  },
 },
 {
  name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred) (notices)",
  fs: MockFS{
   "prebuilts/Android.bp": []byte(`
    prebuilt {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/sources/source_file": nil,
   "top/sources/Android.bp": []byte(`
    source {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/other/source_file": nil,
   "top/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["module"],
    }`),
  },
 },
 {
  name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)",
  fs: MockFS{
   "prebuilts/Android.bp": []byte(`
    prebuilt {
     name: "module",
     visibility: ["//top/other"],
     prefer: true,
    }`),
   "top/sources/source_file": nil,
   "top/sources/Android.bp": []byte(`
    source {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/other/source_file": nil,
   "top/other/Android.bp": []byte(`
    source {
     name: "other",
     deps: [":module"],
    }`),
  },
 },
 {
  name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred) (notices)",
  fs: MockFS{
   "prebuilts/Android.bp": []byte(`
    prebuilt {
     name: "module",
     visibility: ["//top/other"],
     prefer: true,
    }`),
   "top/sources/source_file": nil,
   "top/sources/Android.bp": []byte(`
    source {
     name: "module",
     visibility: ["//top/other"],
    }`),
   "top/other/source_file": nil,
   "top/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["module"],
    }`),
  },
 },
 {
  name: "ensure visibility properties are checked for correctness",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_parent {
     name: "parent",
     visibility: ["//top/nested"],
     child: {
      name: "libchild",
      visibility: ["top/other"],
     },
    }`),
  },
  expectedErrors: []string{
   `module "parent": child.visibility: invalid visibility pattern "top/other"`,
  },
 },
 {
  name: "invalid visibility added to child detected during gather phase",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_parent {
     name: "parent",
     visibility: ["//top/nested"],
     child: {
      name: "libchild",
      invalid_visibility: ["top/other"],
     },
    }`),
  },
  expectedErrors: []string{
   // That this error is reported against the child not the parent shows it was
   // not being detected in the parent which is correct as invalid_visibility is
   // purposely not added to the list of visibility properties to check, and was
   // in fact detected in the child in the gather phase. Contrast this error message
   // with the preceding one.
   `module "libchild" \(created by module "parent"\): visibility: invalid visibility pattern "top/other"`,
  },
 },
 {
  name: "automatic visibility inheritance enabled",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_parent {
     name: "parent",
     visibility: ["//top/nested"],
     child: {
      name: "libchild",
      visibility: ["//top/other"],
     },
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "libnested",
     deps: ["libchild"],
    }`),
   "top/other/Android.bp": []byte(`
    mock_library {
     name: "libother",
     deps: ["libchild"],
    }`),
  },
 },
 {
  name: "automatic visibility inheritance enabled (notices)",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_parent {
     name: "parent",
     visibility: ["//top/nested"],
     child: {
      name: "libchild",
      visibility: ["//top/other"],
     },
    }`),
   "top/nested/Android.bp": []byte(`
    gen_notice {
     name: "nested-notice",
     for: ["libchild"],
    }`),
   "top/other/Android.bp": []byte(`
    gen_notice {
     name: "other-notice",
     for: ["libchild"],
    }`),
  },
 },
 {
  name: "any_system_partition visibility works",
  fs: MockFS{
   "top/Android.bp": []byte(`
    android_filesystem {
     name: "foo",
     deps: ["bar"],
    }`),
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     visibility: ["//visibility:any_system_partition"],
    }`),
  },
 },
 {
  name: "any_system_partition visibility works with the other visibility",
  fs: MockFS{
   "top/Android.bp": []byte(`
    android_filesystem {
     name: "foo",
     deps: ["bar"],
    }`),
   "top2/Android.bp": []byte(``),
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     visibility: [
      "//top2",
      "//visibility:any_system_partition"
     ],
    }`),
  },
 },
 {
  name: "any_system_partition visibility doesn't work for non-partitions",
  fs: MockFS{
   "top/Android.bp": []byte(`
    mock_library {
     name: "foo",
     deps: ["bar"],
    }`),
   "top/nested/Android.bp": []byte(`
    mock_library {
     name: "bar",
     visibility: ["//visibility:any_system_partition"],
    }`),
  },
  expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
 },
 {
  name: "any_system_partition visibility doesn't work for vendor partitions",
  fs: MockFS{
   "top/Android.bp": []byte(`
    android_filesystem {
     name: "foo",
     partition_type: "vendor",
     deps: ["bar"],
    }`),
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     visibility: ["//visibility:any_system_partition"],
    }`),
  },
  expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
 },
 {
  name: "Vendor modules are visible to any vendor partition by default",
  fs: MockFS{
   "top/Android.bp": []byte(`
    android_filesystem {
     name: "foo",
     partition_type: "vendor",
     deps: ["bar"],
    }`),
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     vendor: true,
    }`),
  },
 },
 {
  name: "Not visible to vendor partitions when using any_system_partiton, even if vendor: true",
  fs: MockFS{
   "top/Android.bp": []byte(`
    android_filesystem {
     name: "foo",
     partition_type: "vendor",
     deps: ["bar"],
    }`),
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     vendor: true,
     visibility: ["//visibility:any_system_partition"],
    }`),
  },
  expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
 },
 {
  name: "unknown any_partition specs throw errors",
  fs: MockFS{
   "top/nested/Android.bp": []byte(`
    package(default_visibility=["//visibility:private"])
    mock_library {
     name: "bar",
     visibility: ["//visibility:any_unknown_partition"],
    }`),
  },
  expectedErrors: []string{`unrecognized visibility rule "//visibility:any_unknown_partition"`},
 },
}

func TestVisibility(t *testing.T) {
 for _, test := range visibilityTests {
  t.Run(test.name, func(t *testing.T) {
   result := GroupFixturePreparers(
    // General preparers in alphabetical order as test infrastructure will enforce correct
    // registration order.
    PrepareForTestWithArchMutator,
    PrepareForTestWithDefaults,
    PrepareForTestWithGenNotice,
    PrepareForTestWithOverrides,
    PrepareForTestWithPackageModule,
    PrepareForTestWithPrebuilts,
    PrepareForTestWithVisibility,
    PrepareForTestWithHostTools("textnotice"),

    // Additional test specific preparers.
    FixtureRegisterWithContext(func(ctx RegistrationContext) {
     ctx.RegisterModuleType("mock_library", newMockLibraryModule)
     ctx.RegisterModuleType("mock_parent", newMockParentFactory)
     ctx.RegisterModuleType("mock_defaults", defaultsFactory)
     ctx.RegisterModuleType("android_filesystem", newMockFilesystemModule)
    }),
    prepareForTestWithFakePrebuiltModules,
    // Add additional files to the mock filesystem
    test.fs.AddToFixture(),
   ).
    ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
    RunTest(t)

   if test.effectiveVisibility != nil {
    checkEffectiveVisibility(t, result, test.effectiveVisibility)
   }
  })
 }
}

func checkEffectiveVisibility(t *testing.T, result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) {
 for moduleName, expectedRules := range effectiveVisibility {
  rule := effectiveVisibilityRules(result.Config, moduleName)
  stringRules := rule.Strings()
  AssertDeepEquals(t, "effective rules mismatch", expectedRules, stringRules)
 }
}

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 mockFilesystemModuleProperties struct {
 Partition_type    *string
 Deps              []string
 Is_auto_generated *bool
}

type mockFilesystemModule struct {
 ModuleBase
 properties mockFilesystemModuleProperties
}

func (j *mockFilesystemModule) DepsMutator(ctx BottomUpMutatorContext) {
 ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
}

func (p *mockFilesystemModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 SetProvider(ctx, PartitionTypeInfoProvider, PartitionTypeInfo{
  PartitionType: p.PartitionType(),
 })
}

func (p *mockFilesystemModule) PartitionType() string {
 if p.properties.Partition_type == nil {
  return "system"
 }
 return *p.properties.Partition_type
}

func newMockFilesystemModule() Module {
 m := &mockFilesystemModule{}
 m.AddProperties(&m.properties)
 InitAndroidArchModule(m, DeviceSupported, MultilibCommon)
 return m
}

type mockDefaults struct {
 ModuleBase
 DefaultsModuleBase
}

func defaultsFactory() Module {
 m := &mockDefaults{}
 InitDefaultsModule(m)
 return m
}

type mockParentProperties struct {
 Child struct {
  Name *string

  // Visibility to pass to the child module.
  Visibility []string

  // Purposely not validated visibility to pass to the child.
  Invalid_visibility []string
 }
}

type mockParent struct {
 ModuleBase
 DefaultableModuleBase
 properties mockParentProperties
}

func (p *mockParent) GenerateAndroidBuildActions(ModuleContext) {
}

func newMockParentFactory() Module {
 m := &mockParent{}
 m.AddProperties(&m.properties)
 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
 InitDefaultableModule(m)
 AddVisibilityProperty(m, "child.visibility", &m.properties.Child.Visibility)

 m.SetDefaultableHook(func(ctx DefaultableHookContext) {
  visibility := m.properties.Child.Visibility
  visibility = append(visibility, m.properties.Child.Invalid_visibility...)
  ctx.CreateModule(newMockLibraryModule, &struct {
   Name       *string
   Visibility []string
  }{m.properties.Child.Name, visibility})
 })
 return m
}

func testVisibilityRuleSet(t *testing.T, rules, extra, expected []string) {
 t.Helper()
 set := &visibilityRuleSet{rules}
 err := set.Widen(extra)
 if err != nil {
  t.Error(err)
  return
 }
 actual := set.Strings()
 if !reflect.DeepEqual(actual, expected) {
  t.Errorf("mismatching rules after extend: expected %#v, actual %#v", expected, actual)
 }
}

func TestVisibilityRuleSet(t *testing.T) {
 t.Run("extend empty", func(t *testing.T) {
  testVisibilityRuleSet(t, nil, []string{"//foo"}, []string{"//foo"})
 })
 t.Run("extend", func(t *testing.T) {
  testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar"}, []string{"//bar", "//foo"})
 })
 t.Run("extend duplicate", func(t *testing.T) {
  testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar", "//foo"}, []string{"//bar", "//foo"})
 })
 t.Run("extend public", func(t *testing.T) {
  testVisibilityRuleSet(t, []string{"//visibility:public"}, []string{"//foo"}, []string{"//visibility:public"})
 })
 t.Run("extend private", func(t *testing.T) {
  testVisibilityRuleSet(t, []string{"//visibility:private"}, []string{"//foo"}, []string{"//foo"})
 })
 t.Run("extend with public", func(t *testing.T) {
  testVisibilityRuleSet(t, []string{"//foo"}, []string{"//visibility:public"}, []string{"//visibility:public"})
 })
 t.Run("extend with private", func(t *testing.T) {
  t.Helper()
  set := &visibilityRuleSet{[]string{"//foo"}}
  err := set.Widen([]string{"//visibility:private"})
  expectedError := `"//visibility:private" does not widen the visibility`
  if err == nil {
   t.Errorf("missing error")
  } else if err.Error() != expectedError {
   t.Errorf("expected error %q found error %q", expectedError, err)
  }
 })
}

[Dauer der Verarbeitung: 0.57 Sekunden, vorverarbeitet 2026-06-28]