Loading android/fixture.go +126 −18 Original line number Diff line number Diff line Loading @@ -182,7 +182,13 @@ type FixtureFactory interface { // Create a Fixture. Fixture(t *testing.T, preparers ...FixturePreparer) Fixture // Run the test, expecting no errors, returning a TestResult instance. // Set the error handler that will be used to check any errors reported by the test. // // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any // errors are reported. SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory // Run the test, checking any errors reported and returning a TestResult instance. // // Shorthand for Fixture(t, preparers...).RunTest() RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult Loading @@ -202,6 +208,9 @@ func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) F return &fixtureFactory{ buildDirSupplier: buildDirSupplier, preparers: dedupAndFlattenPreparers(nil, preparers), // Set the default error handler. errorHandler: FixtureExpectsNoErrors, } } Loading Loading @@ -352,9 +361,84 @@ func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer { return &simpleFixturePreparer{function: preparer} } // FixtureErrorHandler determines how to respond to errors reported by the code under test. // // Some possible responses: // * Fail the test if any errors are reported, see FixtureExpectsNoErrors. // * Fail the test if at least one error that matches a pattern is not reported see // FixtureExpectsAtLeastOneErrorMatchingPattern // * Fail the test if any unexpected errors are reported. // // Although at the moment all the error handlers are implemented as simply a wrapper around a // function this is defined as an interface to allow future enhancements, e.g. provide different // ways other than patterns to match an error and to combine handlers together. type FixtureErrorHandler interface { // CheckErrors checks the errors reported. // // The supplied result can be used to access the state of the code under test just as the main // body of the test would but if any errors other than ones expected are reported the state may // be indeterminate. CheckErrors(result *TestResult, errs []error) } type simpleErrorHandler struct { function func(result *TestResult, errs []error) } func (h simpleErrorHandler) CheckErrors(result *TestResult, errs []error) { h.function(result, errs) } // The default fixture error handler. // // Will fail the test immediately if any errors are reported. var FixtureExpectsNoErrors = FixtureCustomErrorHandler( func(result *TestResult, errs []error) { FailIfErrored(result.T, errs) }, ) // FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail // if at least one error that matches the regular expression is not found. // // The test will be failed if: // * No errors are reported. // * One or more errors are reported but none match the pattern. // // The test will not fail if: // * Multiple errors are reported that do not match the pattern as long as one does match. func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler { return FixtureCustomErrorHandler(func(result *TestResult, errs []error) { FailIfNoMatchingErrors(result.T, pattern, errs) }) } // FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail // if there are any unexpected errors. // // The test will be failed if: // * The number of errors reported does not exactly match the patterns. // * One or more of the reported errors do not match a pattern. // * No patterns are provided and one or more errors are reported. // // The test will not fail if: // * One or more of the patterns does not match an error. func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler { return FixtureCustomErrorHandler(func(result *TestResult, errs []error) { CheckErrorsAgainstExpectations(result.T, errs, patterns) }) } // FixtureCustomErrorHandler creates a custom error handler func FixtureCustomErrorHandler(function func(result *TestResult, errs []error)) FixtureErrorHandler { return simpleErrorHandler{ function: function, } } // Fixture defines the test environment. type Fixture interface { // Run the test, expecting no errors, returning a TestResult instance. // Run the test, checking any errors reported and returning a TestResult instance. RunTest() *TestResult } Loading Loading @@ -454,14 +538,17 @@ var _ FixtureFactory = (*fixtureFactory)(nil) type fixtureFactory struct { buildDirSupplier *string preparers []*simpleFixturePreparer errorHandler FixtureErrorHandler } func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory { all := append(f.preparers, dedupAndFlattenPreparers(f.preparers, preparers)...) return &fixtureFactory{ buildDirSupplier: f.buildDirSupplier, preparers: all, } // Copy the existing factory. extendedFactory := &fixtureFactory{} *extendedFactory = *f // Use the extended list of preparers. extendedFactory.preparers = all return extendedFactory } func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture { Loading @@ -473,6 +560,7 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix config: config, ctx: ctx, mockFS: make(MockFS), errorHandler: f.errorHandler, } for _, preparer := range f.preparers { Loading @@ -486,6 +574,11 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix return fixture } func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory { f.errorHandler = errorHandler return f } func (f *fixtureFactory) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult { t.Helper() fixture := f.Fixture(t, preparers...) Loading @@ -498,11 +591,23 @@ func (f *fixtureFactory) RunTestWithBp(t *testing.T, bp string) *TestResult { } type fixture struct { // The factory used to create this fixture. factory *fixtureFactory // The gotest state of the go test within which this was created. t *testing.T // The configuration prepared for this fixture. config Config // The test context prepared for this fixture. ctx *TestContext // The mock filesystem prepared for this fixture. mockFS MockFS // The error handler used to check the errors, if any, that are reported. errorHandler FixtureErrorHandler } func (f *fixture) RunTest() *TestResult { Loading @@ -525,9 +630,9 @@ func (f *fixture) RunTest() *TestResult { ctx.Register() _, errs := ctx.ParseBlueprintsFiles("ignored") FailIfErrored(f.t, errs) if len(errs) == 0 { _, errs = ctx.PrepareBuildActions(f.config) FailIfErrored(f.t, errs) } result := &TestResult{ TestHelper: TestHelper{T: f.t}, Loading @@ -535,6 +640,9 @@ func (f *fixture) RunTest() *TestResult { fixture: f, Config: f.config, } f.errorHandler.CheckErrors(result, errs) return result } Loading android/package.go +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ func init() { RegisterPackageBuildComponents(InitRegistrationContext) } var PrepareForTestWithPackageModule = FixtureRegisterWithContext(RegisterPackageBuildComponents) // Register the package module type. func RegisterPackageBuildComponents(ctx RegistrationContext) { ctx.RegisterModuleType("package", PackageFactory) Loading android/prebuilt_test.go +2 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,8 @@ func registerTestPrebuiltBuildComponents(ctx RegistrationContext) { ctx.PostDepsMutators(RegisterOverridePostDepsMutators) } var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules) func registerTestPrebuiltModules(ctx RegistrationContext) { ctx.RegisterModuleType("prebuilt", newPrebuiltModule) ctx.RegisterModuleType("source", newSourceModule) Loading android/visibility.go +12 −0 Original line number Diff line number Diff line Loading @@ -202,6 +202,18 @@ type ExcludeFromVisibilityEnforcementTag interface { ExcludeFromVisibilityEnforcement() } var PrepareForTestWithVisibilityRuleChecker = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PreArchMutators(RegisterVisibilityRuleChecker) }) var PrepareForTestWithVisibilityRuleGatherer = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PreArchMutators(RegisterVisibilityRuleGatherer) }) var PrepareForTestWithVisibilityRuleEnforcer = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) }) // The rule checker needs to be registered before defaults expansion to correctly check that // //visibility:xxx isn't combined with other packages in the same list in any one module. func RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) { Loading android/visibility_test.go +76 −88 Original line number Diff line number Diff line Loading @@ -9,13 +9,13 @@ import ( var visibilityTests = []struct { name string fs map[string][]byte fs MockFS expectedErrors []string effectiveVisibility map[qualifiedModuleName][]string }{ { name: "invalid visibility: empty list", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -26,7 +26,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty rule", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -37,7 +37,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: unqualified", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -48,7 +48,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty namespace", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -59,7 +59,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty module", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -70,7 +70,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty namespace and module", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -81,7 +81,7 @@ var visibilityTests = []struct { }, { name: "//visibility:unknown", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -92,7 +92,7 @@ var visibilityTests = []struct { }, { name: "//visibility:xxx mixed", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -113,7 +113,7 @@ var visibilityTests = []struct { }, { name: "//visibility:legacy_public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -129,7 +129,7 @@ var visibilityTests = []struct { // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g. // the current directory, a nested directory and a directory in a separate tree. name: "//visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -156,7 +156,7 @@ var visibilityTests = []struct { // Verify that //visibility:private allows the module to be referenced from the current // directory only. name: "//visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -188,7 +188,7 @@ var visibilityTests = []struct { { // Verify that :__pkg__ allows the module to be referenced from the current directory only. name: ":__pkg__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -221,7 +221,7 @@ var visibilityTests = []struct { // Verify that //top/nested allows the module to be referenced from the current directory and // the top/nested directory only, not a subdirectory of top/nested and not peak directory. name: "//top/nested", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -259,7 +259,7 @@ var visibilityTests = []struct { // Verify that :__subpackages__ allows the module to be referenced from the current directory // and sub directories but nowhere else. name: ":__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -290,7 +290,7 @@ var visibilityTests = []struct { // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current // directory and sub directories but nowhere else. name: "//top/nested:__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -321,7 +321,7 @@ var visibilityTests = []struct { // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from // the current directory, top/nested and peak and all its subpackages. name: `["//top/nested", "//peak:__subpackages__"]`, fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -347,7 +347,7 @@ var visibilityTests = []struct { { // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__ name: `//vendor`, fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -381,7 +381,7 @@ var visibilityTests = []struct { { // Check that visibility is the union of the defaults modules. name: "defaults union, basic", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -419,7 +419,7 @@ var visibilityTests = []struct { }, { name: "defaults union, multiple defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading Loading @@ -460,7 +460,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -478,7 +478,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public overriding defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -501,7 +501,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other from different defaults 1", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading @@ -524,7 +524,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other from different defaults 2", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading @@ -547,7 +547,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -581,7 +581,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private mixed with other in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -599,7 +599,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private overriding defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -618,7 +618,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private in defaults overridden", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -637,7 +637,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private override //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -655,7 +655,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public override //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -673,7 +673,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override must be first in the list", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -686,7 +686,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -707,7 +707,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -736,7 +736,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards defaults supplied rules", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -765,7 +765,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override can override //visibility:public with //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -788,7 +788,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override can override //visibility:private with //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -808,7 +808,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private mixed with itself", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading Loading @@ -838,7 +838,7 @@ var visibilityTests = []struct { // Defaults module's defaults_visibility tests { name: "defaults_visibility invalid", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "top_defaults", Loading @@ -851,7 +851,7 @@ var visibilityTests = []struct { }, { name: "defaults_visibility overrides package default", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -871,7 +871,7 @@ var visibilityTests = []struct { // Package default_visibility tests { name: "package default_visibility property is checked", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:invalid"], Loading @@ -882,7 +882,7 @@ var visibilityTests = []struct { { // This test relies on the default visibility being legacy_public. name: "package default_visibility property used when no visibility specified", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -904,7 +904,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility public does not override visibility private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:public"], Loading @@ -927,7 +927,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility private does not override visibility public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -946,7 +946,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility :__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: [":__subpackages__"], Loading @@ -973,7 +973,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility inherited to subpackages", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//outsider"], Loading Loading @@ -1001,7 +1001,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility inherited to subpackages", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading Loading @@ -1031,7 +1031,7 @@ var visibilityTests = []struct { }, { name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)", fs: map[string][]byte{ fs: MockFS{ "prebuilts/Blueprints": []byte(` prebuilt { name: "module", Loading @@ -1053,7 +1053,7 @@ var visibilityTests = []struct { }, { name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)", fs: map[string][]byte{ fs: MockFS{ "prebuilts/Blueprints": []byte(` prebuilt { name: "module", Loading @@ -1076,7 +1076,7 @@ var visibilityTests = []struct { }, { name: "ensure visibility properties are checked for correctness", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1093,7 +1093,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility added to child detected during gather phase", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1115,7 +1115,7 @@ var visibilityTests = []struct { }, { name: "automatic visibility inheritance enabled", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1142,53 +1142,41 @@ var visibilityTests = []struct { func TestVisibility(t *testing.T) { for _, test := range visibilityTests { t.Run(test.name, func(t *testing.T) { ctx, errs := testVisibility(buildDir, test.fs) CheckErrorsAgainstExpectations(t, errs, test.expectedErrors) result := emptyTestFixtureFactory.Extend( FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("mock_library", newMockLibraryModule) ctx.RegisterModuleType("mock_parent", newMockParentFactory) ctx.RegisterModuleType("mock_defaults", defaultsFactory) }), prepareForTestWithFakePrebuiltModules, PrepareForTestWithPackageModule, // Order of the following method calls is significant as they register mutators. PrepareForTestWithArchMutator, PrepareForTestWithPrebuilts, PrepareForTestWithOverrides, PrepareForTestWithVisibilityRuleChecker, PrepareForTestWithDefaults, PrepareForTestWithVisibilityRuleGatherer, PrepareForTestWithVisibilityRuleEnforcer, // Add additional files to the mock filesystem test.fs.AddToFixture(), ). SetErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). RunTest(t) if test.effectiveVisibility != nil { checkEffectiveVisibility(t, ctx, test.effectiveVisibility) checkEffectiveVisibility(result, test.effectiveVisibility) } }) } } func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) { func checkEffectiveVisibility(result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) { for moduleName, expectedRules := range effectiveVisibility { rule := effectiveVisibilityRules(ctx.config, moduleName) rule := effectiveVisibilityRules(result.Config, moduleName) stringRules := rule.Strings() if !reflect.DeepEqual(expectedRules, stringRules) { t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules) } } } func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) { // Create a new config per test as visibility information is stored in the config. config := TestArchConfig(buildDir, nil, "", fs) ctx := NewTestArchContext(config) ctx.RegisterModuleType("mock_library", newMockLibraryModule) ctx.RegisterModuleType("mock_parent", newMockParentFactory) ctx.RegisterModuleType("mock_defaults", defaultsFactory) // Order of the following method calls is significant. RegisterPackageBuildComponents(ctx) registerTestPrebuiltBuildComponents(ctx) ctx.PreArchMutators(RegisterVisibilityRuleChecker) ctx.PreArchMutators(RegisterDefaultsPreArchMutators) ctx.PreArchMutators(RegisterVisibilityRuleGatherer) ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) ctx.Register() _, errs := ctx.ParseBlueprintsFiles(".") if len(errs) > 0 { return ctx, errs result.AssertDeepEquals("effective rules mismatch", expectedRules, stringRules) } _, errs = ctx.PrepareBuildActions(config) return ctx, errs } type mockLibraryProperties struct { Loading Loading
android/fixture.go +126 −18 Original line number Diff line number Diff line Loading @@ -182,7 +182,13 @@ type FixtureFactory interface { // Create a Fixture. Fixture(t *testing.T, preparers ...FixturePreparer) Fixture // Run the test, expecting no errors, returning a TestResult instance. // Set the error handler that will be used to check any errors reported by the test. // // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any // errors are reported. SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory // Run the test, checking any errors reported and returning a TestResult instance. // // Shorthand for Fixture(t, preparers...).RunTest() RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult Loading @@ -202,6 +208,9 @@ func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) F return &fixtureFactory{ buildDirSupplier: buildDirSupplier, preparers: dedupAndFlattenPreparers(nil, preparers), // Set the default error handler. errorHandler: FixtureExpectsNoErrors, } } Loading Loading @@ -352,9 +361,84 @@ func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer { return &simpleFixturePreparer{function: preparer} } // FixtureErrorHandler determines how to respond to errors reported by the code under test. // // Some possible responses: // * Fail the test if any errors are reported, see FixtureExpectsNoErrors. // * Fail the test if at least one error that matches a pattern is not reported see // FixtureExpectsAtLeastOneErrorMatchingPattern // * Fail the test if any unexpected errors are reported. // // Although at the moment all the error handlers are implemented as simply a wrapper around a // function this is defined as an interface to allow future enhancements, e.g. provide different // ways other than patterns to match an error and to combine handlers together. type FixtureErrorHandler interface { // CheckErrors checks the errors reported. // // The supplied result can be used to access the state of the code under test just as the main // body of the test would but if any errors other than ones expected are reported the state may // be indeterminate. CheckErrors(result *TestResult, errs []error) } type simpleErrorHandler struct { function func(result *TestResult, errs []error) } func (h simpleErrorHandler) CheckErrors(result *TestResult, errs []error) { h.function(result, errs) } // The default fixture error handler. // // Will fail the test immediately if any errors are reported. var FixtureExpectsNoErrors = FixtureCustomErrorHandler( func(result *TestResult, errs []error) { FailIfErrored(result.T, errs) }, ) // FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail // if at least one error that matches the regular expression is not found. // // The test will be failed if: // * No errors are reported. // * One or more errors are reported but none match the pattern. // // The test will not fail if: // * Multiple errors are reported that do not match the pattern as long as one does match. func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler { return FixtureCustomErrorHandler(func(result *TestResult, errs []error) { FailIfNoMatchingErrors(result.T, pattern, errs) }) } // FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail // if there are any unexpected errors. // // The test will be failed if: // * The number of errors reported does not exactly match the patterns. // * One or more of the reported errors do not match a pattern. // * No patterns are provided and one or more errors are reported. // // The test will not fail if: // * One or more of the patterns does not match an error. func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler { return FixtureCustomErrorHandler(func(result *TestResult, errs []error) { CheckErrorsAgainstExpectations(result.T, errs, patterns) }) } // FixtureCustomErrorHandler creates a custom error handler func FixtureCustomErrorHandler(function func(result *TestResult, errs []error)) FixtureErrorHandler { return simpleErrorHandler{ function: function, } } // Fixture defines the test environment. type Fixture interface { // Run the test, expecting no errors, returning a TestResult instance. // Run the test, checking any errors reported and returning a TestResult instance. RunTest() *TestResult } Loading Loading @@ -454,14 +538,17 @@ var _ FixtureFactory = (*fixtureFactory)(nil) type fixtureFactory struct { buildDirSupplier *string preparers []*simpleFixturePreparer errorHandler FixtureErrorHandler } func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory { all := append(f.preparers, dedupAndFlattenPreparers(f.preparers, preparers)...) return &fixtureFactory{ buildDirSupplier: f.buildDirSupplier, preparers: all, } // Copy the existing factory. extendedFactory := &fixtureFactory{} *extendedFactory = *f // Use the extended list of preparers. extendedFactory.preparers = all return extendedFactory } func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture { Loading @@ -473,6 +560,7 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix config: config, ctx: ctx, mockFS: make(MockFS), errorHandler: f.errorHandler, } for _, preparer := range f.preparers { Loading @@ -486,6 +574,11 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix return fixture } func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory { f.errorHandler = errorHandler return f } func (f *fixtureFactory) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult { t.Helper() fixture := f.Fixture(t, preparers...) Loading @@ -498,11 +591,23 @@ func (f *fixtureFactory) RunTestWithBp(t *testing.T, bp string) *TestResult { } type fixture struct { // The factory used to create this fixture. factory *fixtureFactory // The gotest state of the go test within which this was created. t *testing.T // The configuration prepared for this fixture. config Config // The test context prepared for this fixture. ctx *TestContext // The mock filesystem prepared for this fixture. mockFS MockFS // The error handler used to check the errors, if any, that are reported. errorHandler FixtureErrorHandler } func (f *fixture) RunTest() *TestResult { Loading @@ -525,9 +630,9 @@ func (f *fixture) RunTest() *TestResult { ctx.Register() _, errs := ctx.ParseBlueprintsFiles("ignored") FailIfErrored(f.t, errs) if len(errs) == 0 { _, errs = ctx.PrepareBuildActions(f.config) FailIfErrored(f.t, errs) } result := &TestResult{ TestHelper: TestHelper{T: f.t}, Loading @@ -535,6 +640,9 @@ func (f *fixture) RunTest() *TestResult { fixture: f, Config: f.config, } f.errorHandler.CheckErrors(result, errs) return result } Loading
android/package.go +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ func init() { RegisterPackageBuildComponents(InitRegistrationContext) } var PrepareForTestWithPackageModule = FixtureRegisterWithContext(RegisterPackageBuildComponents) // Register the package module type. func RegisterPackageBuildComponents(ctx RegistrationContext) { ctx.RegisterModuleType("package", PackageFactory) Loading
android/prebuilt_test.go +2 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,8 @@ func registerTestPrebuiltBuildComponents(ctx RegistrationContext) { ctx.PostDepsMutators(RegisterOverridePostDepsMutators) } var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules) func registerTestPrebuiltModules(ctx RegistrationContext) { ctx.RegisterModuleType("prebuilt", newPrebuiltModule) ctx.RegisterModuleType("source", newSourceModule) Loading
android/visibility.go +12 −0 Original line number Diff line number Diff line Loading @@ -202,6 +202,18 @@ type ExcludeFromVisibilityEnforcementTag interface { ExcludeFromVisibilityEnforcement() } var PrepareForTestWithVisibilityRuleChecker = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PreArchMutators(RegisterVisibilityRuleChecker) }) var PrepareForTestWithVisibilityRuleGatherer = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PreArchMutators(RegisterVisibilityRuleGatherer) }) var PrepareForTestWithVisibilityRuleEnforcer = FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) }) // The rule checker needs to be registered before defaults expansion to correctly check that // //visibility:xxx isn't combined with other packages in the same list in any one module. func RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) { Loading
android/visibility_test.go +76 −88 Original line number Diff line number Diff line Loading @@ -9,13 +9,13 @@ import ( var visibilityTests = []struct { name string fs map[string][]byte fs MockFS expectedErrors []string effectiveVisibility map[qualifiedModuleName][]string }{ { name: "invalid visibility: empty list", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -26,7 +26,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty rule", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -37,7 +37,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: unqualified", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -48,7 +48,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty namespace", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -59,7 +59,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty module", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -70,7 +70,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: empty namespace and module", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -81,7 +81,7 @@ var visibilityTests = []struct { }, { name: "//visibility:unknown", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -92,7 +92,7 @@ var visibilityTests = []struct { }, { name: "//visibility:xxx mixed", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -113,7 +113,7 @@ var visibilityTests = []struct { }, { name: "//visibility:legacy_public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -129,7 +129,7 @@ var visibilityTests = []struct { // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g. // the current directory, a nested directory and a directory in a separate tree. name: "//visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -156,7 +156,7 @@ var visibilityTests = []struct { // Verify that //visibility:private allows the module to be referenced from the current // directory only. name: "//visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -188,7 +188,7 @@ var visibilityTests = []struct { { // Verify that :__pkg__ allows the module to be referenced from the current directory only. name: ":__pkg__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -221,7 +221,7 @@ var visibilityTests = []struct { // Verify that //top/nested allows the module to be referenced from the current directory and // the top/nested directory only, not a subdirectory of top/nested and not peak directory. name: "//top/nested", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -259,7 +259,7 @@ var visibilityTests = []struct { // Verify that :__subpackages__ allows the module to be referenced from the current directory // and sub directories but nowhere else. name: ":__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -290,7 +290,7 @@ var visibilityTests = []struct { // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current // directory and sub directories but nowhere else. name: "//top/nested:__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -321,7 +321,7 @@ var visibilityTests = []struct { // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from // the current directory, top/nested and peak and all its subpackages. name: `["//top/nested", "//peak:__subpackages__"]`, fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -347,7 +347,7 @@ var visibilityTests = []struct { { // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__ name: `//vendor`, fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading Loading @@ -381,7 +381,7 @@ var visibilityTests = []struct { { // Check that visibility is the union of the defaults modules. name: "defaults union, basic", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -419,7 +419,7 @@ var visibilityTests = []struct { }, { name: "defaults union, multiple defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading Loading @@ -460,7 +460,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -478,7 +478,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public overriding defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -501,7 +501,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other from different defaults 1", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading @@ -524,7 +524,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public mixed with other from different defaults 2", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading @@ -547,7 +547,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -581,7 +581,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private mixed with other in defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -599,7 +599,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private overriding defaults", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -618,7 +618,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private in defaults overridden", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -637,7 +637,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private override //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -655,7 +655,7 @@ var visibilityTests = []struct { }, { name: "//visibility:public override //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -673,7 +673,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override must be first in the list", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", Loading @@ -686,7 +686,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -707,7 +707,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -736,7 +736,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override discards defaults supplied rules", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading Loading @@ -765,7 +765,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override can override //visibility:public with //visibility:private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -788,7 +788,7 @@ var visibilityTests = []struct { }, { name: "//visibility:override can override //visibility:private with //visibility:public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults", Loading @@ -808,7 +808,7 @@ var visibilityTests = []struct { }, { name: "//visibility:private mixed with itself", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "libexample_defaults_1", Loading Loading @@ -838,7 +838,7 @@ var visibilityTests = []struct { // Defaults module's defaults_visibility tests { name: "defaults_visibility invalid", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_defaults { name: "top_defaults", Loading @@ -851,7 +851,7 @@ var visibilityTests = []struct { }, { name: "defaults_visibility overrides package default", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -871,7 +871,7 @@ var visibilityTests = []struct { // Package default_visibility tests { name: "package default_visibility property is checked", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:invalid"], Loading @@ -882,7 +882,7 @@ var visibilityTests = []struct { { // This test relies on the default visibility being legacy_public. name: "package default_visibility property used when no visibility specified", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -904,7 +904,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility public does not override visibility private", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:public"], Loading @@ -927,7 +927,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility private does not override visibility public", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading @@ -946,7 +946,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility :__subpackages__", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: [":__subpackages__"], Loading @@ -973,7 +973,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility inherited to subpackages", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//outsider"], Loading Loading @@ -1001,7 +1001,7 @@ var visibilityTests = []struct { }, { name: "package default_visibility inherited to subpackages", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], Loading Loading @@ -1031,7 +1031,7 @@ var visibilityTests = []struct { }, { name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)", fs: map[string][]byte{ fs: MockFS{ "prebuilts/Blueprints": []byte(` prebuilt { name: "module", Loading @@ -1053,7 +1053,7 @@ var visibilityTests = []struct { }, { name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)", fs: map[string][]byte{ fs: MockFS{ "prebuilts/Blueprints": []byte(` prebuilt { name: "module", Loading @@ -1076,7 +1076,7 @@ var visibilityTests = []struct { }, { name: "ensure visibility properties are checked for correctness", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1093,7 +1093,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility added to child detected during gather phase", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1115,7 +1115,7 @@ var visibilityTests = []struct { }, { name: "automatic visibility inheritance enabled", fs: map[string][]byte{ fs: MockFS{ "top/Blueprints": []byte(` mock_parent { name: "parent", Loading @@ -1142,53 +1142,41 @@ var visibilityTests = []struct { func TestVisibility(t *testing.T) { for _, test := range visibilityTests { t.Run(test.name, func(t *testing.T) { ctx, errs := testVisibility(buildDir, test.fs) CheckErrorsAgainstExpectations(t, errs, test.expectedErrors) result := emptyTestFixtureFactory.Extend( FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("mock_library", newMockLibraryModule) ctx.RegisterModuleType("mock_parent", newMockParentFactory) ctx.RegisterModuleType("mock_defaults", defaultsFactory) }), prepareForTestWithFakePrebuiltModules, PrepareForTestWithPackageModule, // Order of the following method calls is significant as they register mutators. PrepareForTestWithArchMutator, PrepareForTestWithPrebuilts, PrepareForTestWithOverrides, PrepareForTestWithVisibilityRuleChecker, PrepareForTestWithDefaults, PrepareForTestWithVisibilityRuleGatherer, PrepareForTestWithVisibilityRuleEnforcer, // Add additional files to the mock filesystem test.fs.AddToFixture(), ). SetErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). RunTest(t) if test.effectiveVisibility != nil { checkEffectiveVisibility(t, ctx, test.effectiveVisibility) checkEffectiveVisibility(result, test.effectiveVisibility) } }) } } func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) { func checkEffectiveVisibility(result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) { for moduleName, expectedRules := range effectiveVisibility { rule := effectiveVisibilityRules(ctx.config, moduleName) rule := effectiveVisibilityRules(result.Config, moduleName) stringRules := rule.Strings() if !reflect.DeepEqual(expectedRules, stringRules) { t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules) } } } func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) { // Create a new config per test as visibility information is stored in the config. config := TestArchConfig(buildDir, nil, "", fs) ctx := NewTestArchContext(config) ctx.RegisterModuleType("mock_library", newMockLibraryModule) ctx.RegisterModuleType("mock_parent", newMockParentFactory) ctx.RegisterModuleType("mock_defaults", defaultsFactory) // Order of the following method calls is significant. RegisterPackageBuildComponents(ctx) registerTestPrebuiltBuildComponents(ctx) ctx.PreArchMutators(RegisterVisibilityRuleChecker) ctx.PreArchMutators(RegisterDefaultsPreArchMutators) ctx.PreArchMutators(RegisterVisibilityRuleGatherer) ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) ctx.Register() _, errs := ctx.ParseBlueprintsFiles(".") if len(errs) > 0 { return ctx, errs result.AssertDeepEquals("effective rules mismatch", expectedRules, stringRules) } _, errs = ctx.PrepareBuildActions(config) return ctx, errs } type mockLibraryProperties struct { Loading