| 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 |
| } |