diff --git a/android/fixture.go b/android/fixture.go index 6e4819c2c..624390d99 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -458,15 +458,22 @@ func (f fixturePreparers) visit(visitor simpleFixturePreparerVisitor) { // preparers - a list of additional unflattened, undeduped preparers that will be applied after the // base preparers. // -// Returns a deduped and flattened list of the preparers minus any that exist in the base preparers. +// Returns a deduped and flattened list of the preparers starting with the ones in base with any +// additional ones from the preparers list added afterwards. func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers fixturePreparers) []*simpleFixturePreparer { - var list []*simpleFixturePreparer + if len(preparers) == 0 { + return base + } + + list := make([]*simpleFixturePreparer, len(base)) visited := make(map[*simpleFixturePreparer]struct{}) // Mark the already flattened and deduped preparers, if any, as having been seen so that - // duplicates of these in the additional preparers will be discarded. - for _, s := range base { + // duplicates of these in the additional preparers will be discarded. Add them to the output + // list. + for i, s := range base { visited[s] = struct{}{} + list[i] = s } preparers.visit(func(preparer *simpleFixturePreparer) { @@ -644,11 +651,8 @@ type fixtureFactory struct { } func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory { - // Create a new slice to avoid accidentally sharing the preparers slice from this factory with - // the extending factories. - var all []*simpleFixturePreparer - all = append(all, f.preparers...) - all = append(all, dedupAndFlattenPreparers(f.preparers, preparers)...) + all := dedupAndFlattenPreparers(f.preparers, preparers) + // Copy the existing factory. extendedFactory := &fixtureFactory{} *extendedFactory = *f @@ -667,10 +671,15 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix // Retrieve the buildDir from the supplier. buildDir = *f.buildDirSupplier } + + // Construct an array of all preparers, those from this factory and the additional ones passed to + // this method. + all := dedupAndFlattenPreparers(f.preparers, preparers) + config := TestConfig(buildDir, nil, "", nil) ctx := NewTestContext(config) fixture := &fixture{ - factory: f, + preparers: all, t: t, config: config, ctx: ctx, @@ -678,11 +687,7 @@ func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fix errorHandler: f.errorHandler, } - for _, preparer := range f.preparers { - preparer.function(fixture) - } - - for _, preparer := range dedupAndFlattenPreparers(f.preparers, preparers) { + for _, preparer := range all { preparer.function(fixture) } @@ -730,8 +735,8 @@ func (f *fixtureFactory) RunTestWithConfig(t *testing.T, config Config) *TestRes } type fixture struct { - // The factory used to create this fixture. - factory *fixtureFactory + // The preparers used to create this fixture. + preparers []*simpleFixturePreparer // The gotest state of the go test within which this was created. t *testing.T @@ -839,6 +844,21 @@ func (r *TestResult) NormalizePathsForTesting(paths Paths) []string { return result } +// Preparer will return a FixturePreparer encapsulating all the preparers used to create the fixture +// that produced this result. +// +// e.g. assuming that this result was created by running: +// factory.Extend(preparer1, preparer2).RunTest(t, preparer3, preparer4) +// +// Then this method will be equivalent to running: +// GroupFixturePreparers(preparer1, preparer2, preparer3, preparer4) +// +// This is intended for use by tests whose output is Android.bp files to verify that those files +// are valid, e.g. tests of the snapshots produced by the sdk module type. +func (r *TestResult) Preparer() FixturePreparer { + return &compositeFixturePreparer{r.fixture.preparers} +} + // Module returns the module with the specific name and of the specified variant. func (r *TestResult) Module(name string, variant string) Module { return r.ModuleForTests(name, variant).Module()