1package android 2 3import ( 4 "testing" 5 6 "github.com/google/blueprint" 7) 8 9var licensesTests = []struct { 10 name string 11 fs MockFS 12 expectedErrors []string 13 effectiveLicenses map[string][]string 14 effectiveInheritedLicenses map[string][]string 15 effectivePackage map[string]string 16 effectiveNotices map[string][]string 17 effectiveKinds map[string][]string 18 effectiveConditions map[string][]string 19}{ 20 { 21 name: "invalid module type without licenses property", 22 fs: map[string][]byte{ 23 "top/Blueprints": []byte(` 24 mock_bad_module { 25 name: "libexample", 26 }`), 27 }, 28 expectedErrors: []string{`module type "mock_bad_module" must have an applicable licenses property`}, 29 }, 30 { 31 name: "license must exist", 32 fs: map[string][]byte{ 33 "top/Blueprints": []byte(` 34 mock_library { 35 name: "libexample", 36 licenses: ["notice"], 37 }`), 38 }, 39 expectedErrors: []string{`"libexample" depends on undefined module "notice"`}, 40 }, 41 { 42 name: "all good", 43 fs: map[string][]byte{ 44 "top/Blueprints": []byte(` 45 license_kind { 46 name: "notice", 47 conditions: ["shownotice"], 48 } 49 50 license { 51 name: "top_Apache2", 52 license_kinds: ["notice"], 53 package_name: "topDog", 54 license_text: ["LICENSE", "NOTICE"], 55 } 56 57 mock_library { 58 name: "libexample1", 59 licenses: ["top_Apache2"], 60 }`), 61 "top/nested/Blueprints": []byte(` 62 mock_library { 63 name: "libnested", 64 licenses: ["top_Apache2"], 65 }`), 66 "other/Blueprints": []byte(` 67 mock_library { 68 name: "libother", 69 licenses: ["top_Apache2"], 70 }`), 71 }, 72 effectiveLicenses: map[string][]string{ 73 "libexample1": []string{"top_Apache2"}, 74 "libnested": []string{"top_Apache2"}, 75 "libother": []string{"top_Apache2"}, 76 }, 77 effectiveKinds: map[string][]string{ 78 "libexample1": []string{"notice"}, 79 "libnested": []string{"notice"}, 80 "libother": []string{"notice"}, 81 }, 82 effectivePackage: map[string]string{ 83 "libexample1": "topDog", 84 "libnested": "topDog", 85 "libother": "topDog", 86 }, 87 effectiveConditions: map[string][]string{ 88 "libexample1": []string{"shownotice"}, 89 "libnested": []string{"shownotice"}, 90 "libother": []string{"shownotice"}, 91 }, 92 effectiveNotices: map[string][]string{ 93 "libexample1": []string{"top/LICENSE", "top/NOTICE"}, 94 "libnested": []string{"top/LICENSE", "top/NOTICE"}, 95 "libother": []string{"top/LICENSE", "top/NOTICE"}, 96 }, 97 }, 98 99 // Defaults propagation tests 100 { 101 // Check that licenses is the union of the defaults modules. 102 name: "defaults union, basic", 103 fs: map[string][]byte{ 104 "top/Blueprints": []byte(` 105 license_kind { 106 name: "top_notice", 107 conditions: ["notice"], 108 } 109 110 license { 111 name: "top_other", 112 license_kinds: ["top_notice"], 113 } 114 115 mock_defaults { 116 name: "libexample_defaults", 117 licenses: ["top_other"], 118 } 119 mock_library { 120 name: "libexample", 121 licenses: ["nested_other"], 122 defaults: ["libexample_defaults"], 123 } 124 mock_library { 125 name: "libsamepackage", 126 deps: ["libexample"], 127 }`), 128 "top/nested/Blueprints": []byte(` 129 license_kind { 130 name: "nested_notice", 131 conditions: ["notice"], 132 } 133 134 license { 135 name: "nested_other", 136 license_kinds: ["nested_notice"], 137 } 138 139 mock_library { 140 name: "libnested", 141 deps: ["libexample"], 142 }`), 143 "other/Blueprints": []byte(` 144 mock_library { 145 name: "libother", 146 deps: ["libexample"], 147 }`), 148 }, 149 effectiveLicenses: map[string][]string{ 150 "libexample": []string{"nested_other", "top_other"}, 151 "libsamepackage": []string{}, 152 "libnested": []string{}, 153 "libother": []string{}, 154 }, 155 effectiveInheritedLicenses: map[string][]string{ 156 "libexample": []string{"nested_other", "top_other"}, 157 "libsamepackage": []string{"nested_other", "top_other"}, 158 "libnested": []string{"nested_other", "top_other"}, 159 "libother": []string{"nested_other", "top_other"}, 160 }, 161 effectiveKinds: map[string][]string{ 162 "libexample": []string{"nested_notice", "top_notice"}, 163 "libsamepackage": []string{}, 164 "libnested": []string{}, 165 "libother": []string{}, 166 }, 167 effectiveConditions: map[string][]string{ 168 "libexample": []string{"notice"}, 169 "libsamepackage": []string{}, 170 "libnested": []string{}, 171 "libother": []string{}, 172 }, 173 }, 174 { 175 name: "defaults union, multiple defaults", 176 fs: map[string][]byte{ 177 "top/Blueprints": []byte(` 178 license { 179 name: "top", 180 } 181 mock_defaults { 182 name: "libexample_defaults_1", 183 licenses: ["other"], 184 } 185 mock_defaults { 186 name: "libexample_defaults_2", 187 licenses: ["top_nested"], 188 } 189 mock_library { 190 name: "libexample", 191 defaults: ["libexample_defaults_1", "libexample_defaults_2"], 192 } 193 mock_library { 194 name: "libsamepackage", 195 deps: ["libexample"], 196 }`), 197 "top/nested/Blueprints": []byte(` 198 license { 199 name: "top_nested", 200 license_text: ["LICENSE.txt"], 201 } 202 mock_library { 203 name: "libnested", 204 deps: ["libexample"], 205 }`), 206 "other/Blueprints": []byte(` 207 license { 208 name: "other", 209 } 210 mock_library { 211 name: "libother", 212 deps: ["libexample"], 213 }`), 214 "outsider/Blueprints": []byte(` 215 mock_library { 216 name: "liboutsider", 217 deps: ["libexample"], 218 }`), 219 }, 220 effectiveLicenses: map[string][]string{ 221 "libexample": []string{"other", "top_nested"}, 222 "libsamepackage": []string{}, 223 "libnested": []string{}, 224 "libother": []string{}, 225 "liboutsider": []string{}, 226 }, 227 effectiveInheritedLicenses: map[string][]string{ 228 "libexample": []string{"other", "top_nested"}, 229 "libsamepackage": []string{"other", "top_nested"}, 230 "libnested": []string{"other", "top_nested"}, 231 "libother": []string{"other", "top_nested"}, 232 "liboutsider": []string{"other", "top_nested"}, 233 }, 234 effectiveKinds: map[string][]string{ 235 "libexample": []string{}, 236 "libsamepackage": []string{}, 237 "libnested": []string{}, 238 "libother": []string{}, 239 "liboutsider": []string{}, 240 }, 241 effectiveNotices: map[string][]string{ 242 "libexample": []string{"top/nested/LICENSE.txt"}, 243 "libsamepackage": []string{}, 244 "libnested": []string{}, 245 "libother": []string{}, 246 "liboutsider": []string{}, 247 }, 248 }, 249 250 // Defaults module's defaults_licenses tests 251 { 252 name: "defaults_licenses invalid", 253 fs: map[string][]byte{ 254 "top/Blueprints": []byte(` 255 mock_defaults { 256 name: "top_defaults", 257 licenses: ["notice"], 258 }`), 259 }, 260 expectedErrors: []string{`"top_defaults" depends on undefined module "notice"`}, 261 }, 262 { 263 name: "defaults_licenses overrides package default", 264 fs: map[string][]byte{ 265 "top/Blueprints": []byte(` 266 package { 267 default_applicable_licenses: ["by_exception_only"], 268 } 269 license { 270 name: "by_exception_only", 271 } 272 license { 273 name: "notice", 274 } 275 mock_defaults { 276 name: "top_defaults", 277 licenses: ["notice"], 278 } 279 mock_library { 280 name: "libexample", 281 } 282 mock_library { 283 name: "libdefaults", 284 defaults: ["top_defaults"], 285 }`), 286 }, 287 effectiveLicenses: map[string][]string{ 288 "libexample": []string{"by_exception_only"}, 289 "libdefaults": []string{"notice"}, 290 }, 291 effectiveInheritedLicenses: map[string][]string{ 292 "libexample": []string{"by_exception_only"}, 293 "libdefaults": []string{"notice"}, 294 }, 295 }, 296 297 // Package default_applicable_licenses tests 298 { 299 name: "package default_applicable_licenses must exist", 300 fs: map[string][]byte{ 301 "top/Blueprints": []byte(` 302 package { 303 default_applicable_licenses: ["notice"], 304 }`), 305 }, 306 expectedErrors: []string{`"//top" depends on undefined module "notice"`}, 307 }, 308 { 309 // This test relies on the default licenses being legacy_public. 310 name: "package default_applicable_licenses property used when no licenses specified", 311 fs: map[string][]byte{ 312 "top/Blueprints": []byte(` 313 package { 314 default_applicable_licenses: ["top_notice"], 315 } 316 317 license { 318 name: "top_notice", 319 } 320 mock_library { 321 name: "libexample", 322 }`), 323 "outsider/Blueprints": []byte(` 324 mock_library { 325 name: "liboutsider", 326 deps: ["libexample"], 327 }`), 328 }, 329 effectiveLicenses: map[string][]string{ 330 "libexample": []string{"top_notice"}, 331 "liboutsider": []string{}, 332 }, 333 effectiveInheritedLicenses: map[string][]string{ 334 "libexample": []string{"top_notice"}, 335 "liboutsider": []string{"top_notice"}, 336 }, 337 }, 338 { 339 name: "package default_applicable_licenses not inherited to subpackages", 340 fs: map[string][]byte{ 341 "top/Blueprints": []byte(` 342 package { 343 default_applicable_licenses: ["top_notice"], 344 } 345 license { 346 name: "top_notice", 347 } 348 mock_library { 349 name: "libexample", 350 }`), 351 "top/nested/Blueprints": []byte(` 352 package { 353 default_applicable_licenses: ["outsider"], 354 } 355 356 mock_library { 357 name: "libnested", 358 }`), 359 "top/other/Blueprints": []byte(` 360 mock_library { 361 name: "libother", 362 }`), 363 "outsider/Blueprints": []byte(` 364 license { 365 name: "outsider", 366 } 367 mock_library { 368 name: "liboutsider", 369 deps: ["libexample", "libother", "libnested"], 370 }`), 371 }, 372 effectiveLicenses: map[string][]string{ 373 "libexample": []string{"top_notice"}, 374 "libnested": []string{"outsider"}, 375 "libother": []string{}, 376 "liboutsider": []string{}, 377 }, 378 effectiveInheritedLicenses: map[string][]string{ 379 "libexample": []string{"top_notice"}, 380 "libnested": []string{"outsider"}, 381 "libother": []string{}, 382 "liboutsider": []string{"top_notice", "outsider"}, 383 }, 384 }, 385 { 386 name: "verify that prebuilt dependencies are included", 387 fs: map[string][]byte{ 388 "prebuilts/Blueprints": []byte(` 389 license { 390 name: "prebuilt" 391 } 392 prebuilt { 393 name: "module", 394 licenses: ["prebuilt"], 395 }`), 396 "top/sources/source_file": nil, 397 "top/sources/Blueprints": []byte(` 398 license { 399 name: "top_sources" 400 } 401 source { 402 name: "module", 403 licenses: ["top_sources"], 404 }`), 405 "top/other/source_file": nil, 406 "top/other/Blueprints": []byte(` 407 source { 408 name: "other", 409 deps: [":module"], 410 }`), 411 }, 412 effectiveLicenses: map[string][]string{ 413 "other": []string{}, 414 }, 415 effectiveInheritedLicenses: map[string][]string{ 416 "other": []string{"prebuilt", "top_sources"}, 417 }, 418 }, 419 { 420 name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)", 421 fs: map[string][]byte{ 422 "prebuilts/Blueprints": []byte(` 423 license { 424 name: "prebuilt" 425 } 426 prebuilt { 427 name: "module", 428 licenses: ["prebuilt"], 429 prefer: true, 430 }`), 431 "top/sources/source_file": nil, 432 "top/sources/Blueprints": []byte(` 433 license { 434 name: "top_sources" 435 } 436 source { 437 name: "module", 438 licenses: ["top_sources"], 439 }`), 440 "top/other/source_file": nil, 441 "top/other/Blueprints": []byte(` 442 source { 443 name: "other", 444 deps: [":module"], 445 }`), 446 }, 447 effectiveLicenses: map[string][]string{ 448 "other": []string{}, 449 }, 450 effectiveInheritedLicenses: map[string][]string{ 451 "module": []string{"prebuilt", "top_sources"}, 452 "other": []string{"prebuilt", "top_sources"}, 453 }, 454 }, 455} 456 457func TestLicenses(t *testing.T) { 458 for _, test := range licensesTests { 459 t.Run(test.name, func(t *testing.T) { 460 // Customize the common license text fixture factory. 461 result := GroupFixturePreparers( 462 prepareForLicenseTest, 463 FixtureRegisterWithContext(func(ctx RegistrationContext) { 464 ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule) 465 ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule) 466 ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory) 467 }), 468 test.fs.AddToFixture(), 469 ). 470 ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). 471 RunTest(t) 472 473 if test.effectiveLicenses != nil { 474 checkEffectiveLicenses(t, result, test.effectiveLicenses) 475 } 476 477 if test.effectivePackage != nil { 478 checkEffectivePackage(t, result, test.effectivePackage) 479 } 480 481 if test.effectiveNotices != nil { 482 checkEffectiveNotices(t, result, test.effectiveNotices) 483 } 484 485 if test.effectiveKinds != nil { 486 checkEffectiveKinds(t, result, test.effectiveKinds) 487 } 488 489 if test.effectiveConditions != nil { 490 checkEffectiveConditions(t, result, test.effectiveConditions) 491 } 492 493 if test.effectiveInheritedLicenses != nil { 494 checkEffectiveInheritedLicenses(t, result, test.effectiveInheritedLicenses) 495 } 496 }) 497 } 498} 499 500func checkEffectiveLicenses(t *testing.T, result *TestResult, effectiveLicenses map[string][]string) { 501 actualLicenses := make(map[string][]string) 502 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 503 if _, ok := m.(*licenseModule); ok { 504 return 505 } 506 if _, ok := m.(*licenseKindModule); ok { 507 return 508 } 509 if _, ok := m.(*packageModule); ok { 510 return 511 } 512 module, ok := m.(Module) 513 if !ok { 514 t.Errorf("%q not a module", m.Name()) 515 return 516 } 517 base := module.base() 518 if base == nil { 519 return 520 } 521 actualLicenses[m.Name()] = base.commonProperties.Effective_licenses 522 }) 523 524 for moduleName, expectedLicenses := range effectiveLicenses { 525 licenses, ok := actualLicenses[moduleName] 526 if !ok { 527 licenses = []string{} 528 } 529 if !compareUnorderedStringArrays(expectedLicenses, licenses) { 530 t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses) 531 } 532 } 533} 534 535func checkEffectiveInheritedLicenses(t *testing.T, result *TestResult, effectiveInheritedLicenses map[string][]string) { 536 actualLicenses := make(map[string][]string) 537 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 538 if _, ok := m.(*licenseModule); ok { 539 return 540 } 541 if _, ok := m.(*licenseKindModule); ok { 542 return 543 } 544 if _, ok := m.(*packageModule); ok { 545 return 546 } 547 module, ok := m.(Module) 548 if !ok { 549 t.Errorf("%q not a module", m.Name()) 550 return 551 } 552 base := module.base() 553 if base == nil { 554 return 555 } 556 inherited := make(map[string]bool) 557 for _, l := range base.commonProperties.Effective_licenses { 558 inherited[l] = true 559 } 560 result.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) { 561 if _, ok := c.(*licenseModule); ok { 562 return 563 } 564 if _, ok := c.(*licenseKindModule); ok { 565 return 566 } 567 if _, ok := c.(*packageModule); ok { 568 return 569 } 570 cmodule, ok := c.(Module) 571 if !ok { 572 t.Errorf("%q not a module", c.Name()) 573 return 574 } 575 cbase := cmodule.base() 576 if cbase == nil { 577 return 578 } 579 for _, l := range cbase.commonProperties.Effective_licenses { 580 inherited[l] = true 581 } 582 }) 583 actualLicenses[m.Name()] = []string{} 584 for l := range inherited { 585 actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l) 586 } 587 }) 588 589 for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses { 590 licenses, ok := actualLicenses[moduleName] 591 if !ok { 592 licenses = []string{} 593 } 594 if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) { 595 t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses) 596 } 597 } 598} 599 600func checkEffectivePackage(t *testing.T, result *TestResult, effectivePackage map[string]string) { 601 actualPackage := make(map[string]string) 602 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 603 if _, ok := m.(*licenseModule); ok { 604 return 605 } 606 if _, ok := m.(*licenseKindModule); ok { 607 return 608 } 609 if _, ok := m.(*packageModule); ok { 610 return 611 } 612 module, ok := m.(Module) 613 if !ok { 614 t.Errorf("%q not a module", m.Name()) 615 return 616 } 617 base := module.base() 618 if base == nil { 619 return 620 } 621 622 if base.commonProperties.Effective_package_name == nil { 623 actualPackage[m.Name()] = "" 624 } else { 625 actualPackage[m.Name()] = *base.commonProperties.Effective_package_name 626 } 627 }) 628 629 for moduleName, expectedPackage := range effectivePackage { 630 packageName, ok := actualPackage[moduleName] 631 if !ok { 632 packageName = "" 633 } 634 if expectedPackage != packageName { 635 t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName) 636 } 637 } 638} 639 640func checkEffectiveNotices(t *testing.T, result *TestResult, effectiveNotices map[string][]string) { 641 actualNotices := make(map[string][]string) 642 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 643 if _, ok := m.(*licenseModule); ok { 644 return 645 } 646 if _, ok := m.(*licenseKindModule); ok { 647 return 648 } 649 if _, ok := m.(*packageModule); ok { 650 return 651 } 652 module, ok := m.(Module) 653 if !ok { 654 t.Errorf("%q not a module", m.Name()) 655 return 656 } 657 base := module.base() 658 if base == nil { 659 return 660 } 661 actualNotices[m.Name()] = base.commonProperties.Effective_license_text.Strings() 662 }) 663 664 for moduleName, expectedNotices := range effectiveNotices { 665 notices, ok := actualNotices[moduleName] 666 if !ok { 667 notices = []string{} 668 } 669 if !compareUnorderedStringArrays(expectedNotices, notices) { 670 t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices) 671 } 672 } 673} 674 675func checkEffectiveKinds(t *testing.T, result *TestResult, effectiveKinds map[string][]string) { 676 actualKinds := make(map[string][]string) 677 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 678 if _, ok := m.(*licenseModule); ok { 679 return 680 } 681 if _, ok := m.(*licenseKindModule); ok { 682 return 683 } 684 if _, ok := m.(*packageModule); ok { 685 return 686 } 687 module, ok := m.(Module) 688 if !ok { 689 t.Errorf("%q not a module", m.Name()) 690 return 691 } 692 base := module.base() 693 if base == nil { 694 return 695 } 696 actualKinds[m.Name()] = base.commonProperties.Effective_license_kinds 697 }) 698 699 for moduleName, expectedKinds := range effectiveKinds { 700 kinds, ok := actualKinds[moduleName] 701 if !ok { 702 kinds = []string{} 703 } 704 if !compareUnorderedStringArrays(expectedKinds, kinds) { 705 t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds) 706 } 707 } 708} 709 710func checkEffectiveConditions(t *testing.T, result *TestResult, effectiveConditions map[string][]string) { 711 actualConditions := make(map[string][]string) 712 result.Context.Context.VisitAllModules(func(m blueprint.Module) { 713 if _, ok := m.(*licenseModule); ok { 714 return 715 } 716 if _, ok := m.(*licenseKindModule); ok { 717 return 718 } 719 if _, ok := m.(*packageModule); ok { 720 return 721 } 722 module, ok := m.(Module) 723 if !ok { 724 t.Errorf("%q not a module", m.Name()) 725 return 726 } 727 base := module.base() 728 if base == nil { 729 return 730 } 731 actualConditions[m.Name()] = base.commonProperties.Effective_license_conditions 732 }) 733 734 for moduleName, expectedConditions := range effectiveConditions { 735 conditions, ok := actualConditions[moduleName] 736 if !ok { 737 conditions = []string{} 738 } 739 if !compareUnorderedStringArrays(expectedConditions, conditions) { 740 t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions) 741 } 742 } 743} 744 745func compareUnorderedStringArrays(expected, actual []string) bool { 746 if len(expected) != len(actual) { 747 return false 748 } 749 s := make(map[string]int) 750 for _, v := range expected { 751 s[v] += 1 752 } 753 for _, v := range actual { 754 c, ok := s[v] 755 if !ok { 756 return false 757 } 758 if c < 1 { 759 return false 760 } 761 s[v] -= 1 762 } 763 return true 764} 765 766type mockLicensesBadProperties struct { 767 Visibility []string 768} 769 770type mockLicensesBadModule struct { 771 ModuleBase 772 DefaultableModuleBase 773 properties mockLicensesBadProperties 774} 775 776func newMockLicensesBadModule() Module { 777 m := &mockLicensesBadModule{} 778 779 base := m.base() 780 m.AddProperties(&base.nameProperties, &m.properties) 781 782 base.generalProperties = m.GetProperties() 783 base.customizableProperties = m.GetProperties() 784 785 // The default_visibility property needs to be checked and parsed by the visibility module during 786 // its checking and parsing phases so make it the primary visibility property. 787 setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility) 788 789 initAndroidModuleBase(m) 790 InitDefaultableModule(m) 791 792 return m 793} 794 795func (m *mockLicensesBadModule) GenerateAndroidBuildActions(ModuleContext) { 796} 797 798type mockLicensesLibraryProperties struct { 799 Deps []string 800} 801 802type mockLicensesLibraryModule struct { 803 ModuleBase 804 DefaultableModuleBase 805 properties mockLicensesLibraryProperties 806} 807 808func newMockLicensesLibraryModule() Module { 809 m := &mockLicensesLibraryModule{} 810 m.AddProperties(&m.properties) 811 InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) 812 InitDefaultableModule(m) 813 return m 814} 815 816type dependencyLicensesTag struct { 817 blueprint.BaseDependencyTag 818 name string 819} 820 821func (j *mockLicensesLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { 822 ctx.AddVariationDependencies(nil, dependencyLicensesTag{name: "mockdeps"}, j.properties.Deps...) 823} 824 825func (p *mockLicensesLibraryModule) GenerateAndroidBuildActions(ModuleContext) { 826} 827 828type mockLicensesDefaults struct { 829 ModuleBase 830 DefaultsModuleBase 831} 832 833func defaultsLicensesFactory() Module { 834 m := &mockLicensesDefaults{} 835 InitDefaultsModule(m) 836 return m 837} 838