From cfd3374da03da06646fb209583178dbd718129dd Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Sat, 27 Feb 2021 11:59:02 +0000 Subject: [PATCH] Add error handling to test fixtures Adds support for customizing the error handling behavior of test fixtures and converts a test to use it. Bug: 181070625 Test: m nothing Change-Id: I736c41311819d57d8688fc3b0e021dbb50c491c1 --- android/fixture.go | 144 ++++++++++++++++++++++++++++---- android/package.go | 2 + android/prebuilt_test.go | 2 + android/visibility.go | 12 +++ android/visibility_test.go | 164 +++++++++++++++++-------------------- 5 files changed, 218 insertions(+), 106 deletions(-) diff --git a/android/fixture.go b/android/fixture.go index 0efe329cb..ae24b914f 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -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 @@ -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, } } @@ -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 } @@ -454,25 +538,29 @@ 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 { config := TestConfig(*f.buildDirSupplier, nil, "", nil) ctx := NewTestContext(config) fixture := &fixture{ - factory: f, - t: t, - config: config, - ctx: ctx, - mockFS: make(MockFS), + factory: f, + t: t, + config: config, + ctx: ctx, + mockFS: make(MockFS), + errorHandler: f.errorHandler, } for _, preparer := range f.preparers { @@ -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...) @@ -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 - t *testing.T - config Config - ctx *TestContext - mockFS MockFS + + // 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 { @@ -525,9 +630,9 @@ func (f *fixture) RunTest() *TestResult { ctx.Register() _, errs := ctx.ParseBlueprintsFiles("ignored") - FailIfErrored(f.t, errs) - _, errs = ctx.PrepareBuildActions(f.config) - FailIfErrored(f.t, errs) + if len(errs) == 0 { + _, errs = ctx.PrepareBuildActions(f.config) + } result := &TestResult{ TestHelper: TestHelper{T: f.t}, @@ -535,6 +640,9 @@ func (f *fixture) RunTest() *TestResult { fixture: f, Config: f.config, } + + f.errorHandler.CheckErrors(result, errs) + return result } diff --git a/android/package.go b/android/package.go index 7012fc7d8..878e4c4ed 100644 --- a/android/package.go +++ b/android/package.go @@ -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) diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 164b1bc59..32af5df4b 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -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) diff --git a/android/visibility.go b/android/visibility.go index 7eac47166..631e88ff9 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -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) { diff --git a/android/visibility_test.go b/android/visibility_test.go index 87a295e23..30cdcbf8f 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -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", @@ -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", @@ -37,7 +37,7 @@ var visibilityTests = []struct { }, { name: "invalid visibility: unqualified", - fs: map[string][]byte{ + fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", @@ -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", @@ -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", @@ -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", @@ -81,7 +81,7 @@ var visibilityTests = []struct { }, { name: "//visibility:unknown", - fs: map[string][]byte{ + fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", @@ -92,7 +92,7 @@ var visibilityTests = []struct { }, { name: "//visibility:xxx mixed", - fs: map[string][]byte{ + fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", @@ -113,7 +113,7 @@ var visibilityTests = []struct { }, { name: "//visibility:legacy_public", - fs: map[string][]byte{ + fs: MockFS{ "top/Blueprints": []byte(` mock_library { name: "libexample", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -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"], @@ -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"], @@ -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"], @@ -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"], @@ -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"], @@ -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__"], @@ -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"], @@ -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"], @@ -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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -1142,55 +1142,43 @@ 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) - } + result.AssertDeepEquals("effective rules mismatch", 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 - } - - _, errs = ctx.PrepareBuildActions(config) - return ctx, errs -} - type mockLibraryProperties struct { Deps []string }