123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834 |
- package android
- import (
- "testing"
- "github.com/google/blueprint"
- )
- var licensesTests = []struct {
- name string
- fs MockFS
- expectedErrors []string
- effectiveLicenses map[string][]string
- effectiveInheritedLicenses map[string][]string
- effectivePackage map[string]string
- effectiveNotices map[string][]string
- effectiveKinds map[string][]string
- effectiveConditions map[string][]string
- }{
- {
- name: "invalid module type without licenses property",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- mock_bad_module {
- name: "libexample",
- }`),
- },
- expectedErrors: []string{`module type "mock_bad_module" must have an applicable licenses property`},
- },
- {
- name: "license must exist",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- mock_library {
- name: "libexample",
- licenses: ["notice"],
- }`),
- },
- expectedErrors: []string{`"libexample" depends on undefined module "notice"`},
- },
- {
- name: "all good",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- license_kind {
- name: "notice",
- conditions: ["shownotice"],
- }
- license {
- name: "top_Apache2",
- license_kinds: ["notice"],
- package_name: "topDog",
- license_text: ["LICENSE", "NOTICE"],
- }
- mock_library {
- name: "libexample1",
- licenses: ["top_Apache2"],
- }`),
- "top/nested/Android.bp": []byte(`
- mock_library {
- name: "libnested",
- licenses: ["top_Apache2"],
- }`),
- "other/Android.bp": []byte(`
- mock_library {
- name: "libother",
- licenses: ["top_Apache2"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample1": []string{"top_Apache2"},
- "libnested": []string{"top_Apache2"},
- "libother": []string{"top_Apache2"},
- },
- effectiveKinds: map[string][]string{
- "libexample1": []string{"notice"},
- "libnested": []string{"notice"},
- "libother": []string{"notice"},
- },
- effectivePackage: map[string]string{
- "libexample1": "topDog",
- "libnested": "topDog",
- "libother": "topDog",
- },
- effectiveConditions: map[string][]string{
- "libexample1": []string{"shownotice"},
- "libnested": []string{"shownotice"},
- "libother": []string{"shownotice"},
- },
- effectiveNotices: map[string][]string{
- "libexample1": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
- "libnested": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
- "libother": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
- },
- },
- // Defaults propagation tests
- {
- // Check that licenses is the union of the defaults modules.
- name: "defaults union, basic",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- license_kind {
- name: "top_notice",
- conditions: ["notice"],
- }
- license {
- name: "top_other",
- license_kinds: ["top_notice"],
- }
- mock_defaults {
- name: "libexample_defaults",
- licenses: ["top_other"],
- }
- mock_library {
- name: "libexample",
- licenses: ["nested_other"],
- defaults: ["libexample_defaults"],
- }
- mock_library {
- name: "libsamepackage",
- deps: ["libexample"],
- }`),
- "top/nested/Android.bp": []byte(`
- license_kind {
- name: "nested_notice",
- conditions: ["notice"],
- }
- license {
- name: "nested_other",
- license_kinds: ["nested_notice"],
- }
- mock_library {
- name: "libnested",
- deps: ["libexample"],
- }`),
- "other/Android.bp": []byte(`
- mock_library {
- name: "libother",
- deps: ["libexample"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
- "libsamepackage": []string{"nested_other", "top_other"},
- "libnested": []string{"nested_other", "top_other"},
- "libother": []string{"nested_other", "top_other"},
- },
- effectiveKinds: map[string][]string{
- "libexample": []string{"nested_notice", "top_notice"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- },
- effectiveConditions: map[string][]string{
- "libexample": []string{"notice"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- },
- },
- {
- name: "defaults union, multiple defaults",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- license {
- name: "top",
- }
- mock_defaults {
- name: "libexample_defaults_1",
- licenses: ["other"],
- }
- mock_defaults {
- name: "libexample_defaults_2",
- licenses: ["top_nested"],
- }
- mock_library {
- name: "libexample",
- defaults: ["libexample_defaults_1", "libexample_defaults_2"],
- }
- mock_library {
- name: "libsamepackage",
- deps: ["libexample"],
- }`),
- "top/nested/Android.bp": []byte(`
- license {
- name: "top_nested",
- license_text: ["LICENSE.txt"],
- }
- mock_library {
- name: "libnested",
- deps: ["libexample"],
- }`),
- "other/Android.bp": []byte(`
- license {
- name: "other",
- }
- mock_library {
- name: "libother",
- deps: ["libexample"],
- }`),
- "outsider/Android.bp": []byte(`
- mock_library {
- name: "liboutsider",
- deps: ["libexample"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
- "libsamepackage": []string{"other", "top_nested"},
- "libnested": []string{"other", "top_nested"},
- "libother": []string{"other", "top_nested"},
- "liboutsider": []string{"other", "top_nested"},
- },
- effectiveKinds: map[string][]string{
- "libexample": []string{},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
- },
- effectiveNotices: map[string][]string{
- "libexample": []string{"top/nested/LICENSE.txt"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
- },
- },
- // Defaults module's defaults_licenses tests
- {
- name: "defaults_licenses invalid",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- mock_defaults {
- name: "top_defaults",
- licenses: ["notice"],
- }`),
- },
- expectedErrors: []string{`"top_defaults" depends on undefined module "notice"`},
- },
- {
- name: "defaults_licenses overrides package default",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- package {
- default_applicable_licenses: ["by_exception_only"],
- }
- license {
- name: "by_exception_only",
- }
- license {
- name: "notice",
- }
- mock_defaults {
- name: "top_defaults",
- licenses: ["notice"],
- }
- mock_library {
- name: "libexample",
- }
- mock_library {
- name: "libdefaults",
- defaults: ["top_defaults"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
- "libdefaults": []string{"notice"},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
- "libdefaults": []string{"notice"},
- },
- },
- // Package default_applicable_licenses tests
- {
- name: "package default_applicable_licenses must exist",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- package {
- default_applicable_licenses: ["notice"],
- }`),
- },
- expectedErrors: []string{`"//top" depends on undefined module "notice"`},
- },
- {
- // This test relies on the default licenses being legacy_public.
- name: "package default_applicable_licenses property used when no licenses specified",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- package {
- default_applicable_licenses: ["top_notice"],
- }
- license {
- name: "top_notice",
- }
- mock_library {
- name: "libexample",
- }`),
- "outsider/Android.bp": []byte(`
- mock_library {
- name: "liboutsider",
- deps: ["libexample"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "liboutsider": []string{"top_notice"},
- },
- },
- {
- name: "package default_applicable_licenses not inherited to subpackages",
- fs: map[string][]byte{
- "top/Android.bp": []byte(`
- package {
- default_applicable_licenses: ["top_notice"],
- }
- license {
- name: "top_notice",
- }
- mock_library {
- name: "libexample",
- }`),
- "top/nested/Android.bp": []byte(`
- package {
- default_applicable_licenses: ["outsider"],
- }
- mock_library {
- name: "libnested",
- }`),
- "top/other/Android.bp": []byte(`
- mock_library {
- name: "libother",
- }`),
- "outsider/Android.bp": []byte(`
- license {
- name: "outsider",
- }
- mock_library {
- name: "liboutsider",
- deps: ["libexample", "libother", "libnested"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
- "liboutsider": []string{"top_notice", "outsider"},
- },
- },
- {
- name: "verify that prebuilt dependencies are included",
- fs: map[string][]byte{
- "prebuilts/Android.bp": []byte(`
- license {
- name: "prebuilt"
- }
- prebuilt {
- name: "module",
- licenses: ["prebuilt"],
- }`),
- "top/sources/source_file": nil,
- "top/sources/Android.bp": []byte(`
- license {
- name: "top_sources"
- }
- source {
- name: "module",
- licenses: ["top_sources"],
- }`),
- "top/other/source_file": nil,
- "top/other/Android.bp": []byte(`
- source {
- name: "other",
- deps: [":module"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "other": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "other": []string{"prebuilt", "top_sources"},
- },
- },
- {
- name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)",
- fs: map[string][]byte{
- "prebuilts/Android.bp": []byte(`
- license {
- name: "prebuilt"
- }
- prebuilt {
- name: "module",
- licenses: ["prebuilt"],
- prefer: true,
- }`),
- "top/sources/source_file": nil,
- "top/sources/Android.bp": []byte(`
- license {
- name: "top_sources"
- }
- source {
- name: "module",
- licenses: ["top_sources"],
- }`),
- "top/other/source_file": nil,
- "top/other/Android.bp": []byte(`
- source {
- name: "other",
- deps: [":module"],
- }`),
- },
- effectiveLicenses: map[string][]string{
- "other": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "module": []string{"prebuilt", "top_sources"},
- "other": []string{"prebuilt", "top_sources"},
- },
- },
- }
- func TestLicenses(t *testing.T) {
- for _, test := range licensesTests {
- t.Run(test.name, func(t *testing.T) {
- // Customize the common license text fixture factory.
- result := GroupFixturePreparers(
- prepareForLicenseTest,
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
- ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
- ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
- }),
- test.fs.AddToFixture(),
- ).
- ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
- RunTest(t)
- if test.effectiveLicenses != nil {
- checkEffectiveLicenses(t, result, test.effectiveLicenses)
- }
- if test.effectivePackage != nil {
- checkEffectivePackage(t, result, test.effectivePackage)
- }
- if test.effectiveNotices != nil {
- checkEffectiveNotices(t, result, test.effectiveNotices)
- }
- if test.effectiveKinds != nil {
- checkEffectiveKinds(t, result, test.effectiveKinds)
- }
- if test.effectiveConditions != nil {
- checkEffectiveConditions(t, result, test.effectiveConditions)
- }
- if test.effectiveInheritedLicenses != nil {
- checkEffectiveInheritedLicenses(t, result, test.effectiveInheritedLicenses)
- }
- })
- }
- }
- func checkEffectiveLicenses(t *testing.T, result *TestResult, effectiveLicenses map[string][]string) {
- actualLicenses := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- actualLicenses[m.Name()] = base.commonProperties.Effective_licenses
- })
- for moduleName, expectedLicenses := range effectiveLicenses {
- licenses, ok := actualLicenses[moduleName]
- if !ok {
- licenses = []string{}
- }
- if !compareUnorderedStringArrays(expectedLicenses, licenses) {
- t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
- }
- }
- }
- func checkEffectiveInheritedLicenses(t *testing.T, result *TestResult, effectiveInheritedLicenses map[string][]string) {
- actualLicenses := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- inherited := make(map[string]bool)
- for _, l := range base.commonProperties.Effective_licenses {
- inherited[l] = true
- }
- result.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
- if _, ok := c.(*licenseModule); ok {
- return
- }
- if _, ok := c.(*licenseKindModule); ok {
- return
- }
- if _, ok := c.(*packageModule); ok {
- return
- }
- cmodule, ok := c.(Module)
- if !ok {
- t.Errorf("%q not a module", c.Name())
- return
- }
- cbase := cmodule.base()
- if cbase == nil {
- return
- }
- for _, l := range cbase.commonProperties.Effective_licenses {
- inherited[l] = true
- }
- })
- actualLicenses[m.Name()] = []string{}
- for l := range inherited {
- actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l)
- }
- })
- for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses {
- licenses, ok := actualLicenses[moduleName]
- if !ok {
- licenses = []string{}
- }
- if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) {
- t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
- }
- }
- }
- func checkEffectivePackage(t *testing.T, result *TestResult, effectivePackage map[string]string) {
- actualPackage := make(map[string]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- if base.commonProperties.Effective_package_name == nil {
- actualPackage[m.Name()] = ""
- } else {
- actualPackage[m.Name()] = *base.commonProperties.Effective_package_name
- }
- })
- for moduleName, expectedPackage := range effectivePackage {
- packageName, ok := actualPackage[moduleName]
- if !ok {
- packageName = ""
- }
- if expectedPackage != packageName {
- t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName)
- }
- }
- }
- func checkEffectiveNotices(t *testing.T, result *TestResult, effectiveNotices map[string][]string) {
- actualNotices := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- actualNotices[m.Name()] = base.commonProperties.Effective_license_text.Strings()
- })
- for moduleName, expectedNotices := range effectiveNotices {
- notices, ok := actualNotices[moduleName]
- if !ok {
- notices = []string{}
- }
- if !compareUnorderedStringArrays(expectedNotices, notices) {
- t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices)
- }
- }
- }
- func checkEffectiveKinds(t *testing.T, result *TestResult, effectiveKinds map[string][]string) {
- actualKinds := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- actualKinds[m.Name()] = base.commonProperties.Effective_license_kinds
- })
- for moduleName, expectedKinds := range effectiveKinds {
- kinds, ok := actualKinds[moduleName]
- if !ok {
- kinds = []string{}
- }
- if !compareUnorderedStringArrays(expectedKinds, kinds) {
- t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds)
- }
- }
- }
- func checkEffectiveConditions(t *testing.T, result *TestResult, effectiveConditions map[string][]string) {
- actualConditions := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- actualConditions[m.Name()] = base.commonProperties.Effective_license_conditions
- })
- for moduleName, expectedConditions := range effectiveConditions {
- conditions, ok := actualConditions[moduleName]
- if !ok {
- conditions = []string{}
- }
- if !compareUnorderedStringArrays(expectedConditions, conditions) {
- t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions)
- }
- }
- }
- func compareUnorderedStringArrays(expected, actual []string) bool {
- if len(expected) != len(actual) {
- return false
- }
- s := make(map[string]int)
- for _, v := range expected {
- s[v] += 1
- }
- for _, v := range actual {
- c, ok := s[v]
- if !ok {
- return false
- }
- if c < 1 {
- return false
- }
- s[v] -= 1
- }
- return true
- }
- type mockLicensesBadProperties struct {
- Visibility []string
- }
- type mockLicensesBadModule struct {
- ModuleBase
- DefaultableModuleBase
- properties mockLicensesBadProperties
- }
- func newMockLicensesBadModule() Module {
- m := &mockLicensesBadModule{}
- base := m.base()
- m.AddProperties(&base.nameProperties, &m.properties)
- // The default_visibility property needs to be checked and parsed by the visibility module during
- // its checking and parsing phases so make it the primary visibility property.
- setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility)
- initAndroidModuleBase(m)
- InitDefaultableModule(m)
- return m
- }
- func (m *mockLicensesBadModule) GenerateAndroidBuildActions(ModuleContext) {
- }
- type mockLicensesLibraryProperties struct {
- Deps []string
- }
- type mockLicensesLibraryModule struct {
- ModuleBase
- DefaultableModuleBase
- properties mockLicensesLibraryProperties
- }
- func newMockLicensesLibraryModule() Module {
- m := &mockLicensesLibraryModule{}
- m.AddProperties(&m.properties)
- InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
- InitDefaultableModule(m)
- return m
- }
- type dependencyLicensesTag struct {
- blueprint.BaseDependencyTag
- name string
- }
- func (j *mockLicensesLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
- ctx.AddVariationDependencies(nil, dependencyLicensesTag{name: "mockdeps"}, j.properties.Deps...)
- }
- func (p *mockLicensesLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
- }
- type mockLicensesDefaults struct {
- ModuleBase
- DefaultsModuleBase
- }
- func defaultsLicensesFactory() Module {
- m := &mockLicensesDefaults{}
- InitDefaultsModule(m)
- return m
- }
|