xref: /aosp_15_r20/build/soong/android/fixture.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2021 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage android
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"runtime"
20*333d2b36SAndroid Build Coastguard Worker	"strings"
21*333d2b36SAndroid Build Coastguard Worker	"testing"
22*333d2b36SAndroid Build Coastguard Worker)
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker// Provides support for creating test fixtures on which tests can be run. Reduces duplication
25*333d2b36SAndroid Build Coastguard Worker// of test setup by allow tests to easily reuse setup code.
26*333d2b36SAndroid Build Coastguard Worker//
27*333d2b36SAndroid Build Coastguard Worker// Fixture
28*333d2b36SAndroid Build Coastguard Worker// =======
29*333d2b36SAndroid Build Coastguard Worker// These determine the environment within which a test can be run. Fixtures are mutable and are
30*333d2b36SAndroid Build Coastguard Worker// created and mutated by FixturePreparer instances. They are created by first creating a base
31*333d2b36SAndroid Build Coastguard Worker// Fixture (which is essentially empty) and then applying FixturePreparer instances to it to modify
32*333d2b36SAndroid Build Coastguard Worker// the environment.
33*333d2b36SAndroid Build Coastguard Worker//
34*333d2b36SAndroid Build Coastguard Worker// FixturePreparer
35*333d2b36SAndroid Build Coastguard Worker// ===============
36*333d2b36SAndroid Build Coastguard Worker// These are responsible for modifying a Fixture in preparation for it to run a test. Preparers are
37*333d2b36SAndroid Build Coastguard Worker// intended to be immutable and able to prepare multiple Fixture objects simultaneously without
38*333d2b36SAndroid Build Coastguard Worker// them sharing any data.
39*333d2b36SAndroid Build Coastguard Worker//
40*333d2b36SAndroid Build Coastguard Worker// They provide the basic capabilities for running tests too.
41*333d2b36SAndroid Build Coastguard Worker//
42*333d2b36SAndroid Build Coastguard Worker// FixturePreparers are only ever applied once per test fixture. Prior to application the list of
43*333d2b36SAndroid Build Coastguard Worker// FixturePreparers are flattened and deduped while preserving the order they first appear in the
44*333d2b36SAndroid Build Coastguard Worker// list. This makes it easy to reuse, group and combine FixturePreparers together.
45*333d2b36SAndroid Build Coastguard Worker//
46*333d2b36SAndroid Build Coastguard Worker// Each small self contained piece of test setup should be their own FixturePreparer. e.g.
47*333d2b36SAndroid Build Coastguard Worker// * A group of related modules.
48*333d2b36SAndroid Build Coastguard Worker// * A group of related mutators.
49*333d2b36SAndroid Build Coastguard Worker// * A combination of both.
50*333d2b36SAndroid Build Coastguard Worker// * Configuration.
51*333d2b36SAndroid Build Coastguard Worker//
52*333d2b36SAndroid Build Coastguard Worker// They should not overlap, e.g. the same module type should not be registered by different
53*333d2b36SAndroid Build Coastguard Worker// FixturePreparers as using them both would cause a build error. In that case the preparer should
54*333d2b36SAndroid Build Coastguard Worker// be split into separate parts and combined together using FixturePreparers(...).
55*333d2b36SAndroid Build Coastguard Worker//
56*333d2b36SAndroid Build Coastguard Worker// e.g. attempting to use AllPreparers in preparing a Fixture would break as it would attempt to
57*333d2b36SAndroid Build Coastguard Worker// register module bar twice:
58*333d2b36SAndroid Build Coastguard Worker//   var Preparer1 = FixtureRegisterWithContext(RegisterModuleFooAndBar)
59*333d2b36SAndroid Build Coastguard Worker//   var Preparer2 = FixtureRegisterWithContext(RegisterModuleBarAndBaz)
60*333d2b36SAndroid Build Coastguard Worker//   var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
61*333d2b36SAndroid Build Coastguard Worker//
62*333d2b36SAndroid Build Coastguard Worker// However, when restructured like this it would work fine:
63*333d2b36SAndroid Build Coastguard Worker//   var PreparerFoo = FixtureRegisterWithContext(RegisterModuleFoo)
64*333d2b36SAndroid Build Coastguard Worker//   var PreparerBar = FixtureRegisterWithContext(RegisterModuleBar)
65*333d2b36SAndroid Build Coastguard Worker//   var PreparerBaz = FixtureRegisterWithContext(RegisterModuleBaz)
66*333d2b36SAndroid Build Coastguard Worker//   var Preparer1 = GroupFixturePreparers(RegisterModuleFoo, RegisterModuleBar)
67*333d2b36SAndroid Build Coastguard Worker//   var Preparer2 = GroupFixturePreparers(RegisterModuleBar, RegisterModuleBaz)
68*333d2b36SAndroid Build Coastguard Worker//   var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
69*333d2b36SAndroid Build Coastguard Worker//
70*333d2b36SAndroid Build Coastguard Worker// As after deduping and flattening AllPreparers would result in the following preparers being
71*333d2b36SAndroid Build Coastguard Worker// applied:
72*333d2b36SAndroid Build Coastguard Worker// 1. PreparerFoo
73*333d2b36SAndroid Build Coastguard Worker// 2. PreparerBar
74*333d2b36SAndroid Build Coastguard Worker// 3. PreparerBaz
75*333d2b36SAndroid Build Coastguard Worker//
76*333d2b36SAndroid Build Coastguard Worker// Preparers can be used for both integration and unit tests.
77*333d2b36SAndroid Build Coastguard Worker//
78*333d2b36SAndroid Build Coastguard Worker// Integration tests typically use all the module types, mutators and singletons that are available
79*333d2b36SAndroid Build Coastguard Worker// for that package to try and replicate the behavior of the runtime build as closely as possible.
80*333d2b36SAndroid Build Coastguard Worker// However, that realism comes at a cost of increased fragility (as they can be broken by changes in
81*333d2b36SAndroid Build Coastguard Worker// many different parts of the build) and also increased runtime, especially if they use lots of
82*333d2b36SAndroid Build Coastguard Worker// singletons and mutators.
83*333d2b36SAndroid Build Coastguard Worker//
84*333d2b36SAndroid Build Coastguard Worker// Unit tests on the other hand try and minimize the amount of code being tested which makes them
85*333d2b36SAndroid Build Coastguard Worker// less susceptible to changes elsewhere in the build and quick to run but at a cost of potentially
86*333d2b36SAndroid Build Coastguard Worker// not testing realistic scenarios.
87*333d2b36SAndroid Build Coastguard Worker//
88*333d2b36SAndroid Build Coastguard Worker// Supporting unit tests effectively require that preparers are available at the lowest granularity
89*333d2b36SAndroid Build Coastguard Worker// possible. Supporting integration tests effectively require that the preparers are organized into
90*333d2b36SAndroid Build Coastguard Worker// groups that provide all the functionality available.
91*333d2b36SAndroid Build Coastguard Worker//
92*333d2b36SAndroid Build Coastguard Worker// At least in terms of tests that check the behavior of build components via processing
93*333d2b36SAndroid Build Coastguard Worker// `Android.bp` there is no clear separation between a unit test and an integration test. Instead
94*333d2b36SAndroid Build Coastguard Worker// they vary from one end that tests a single module (e.g. filegroup) to the other end that tests a
95*333d2b36SAndroid Build Coastguard Worker// whole system of modules, mutators and singletons (e.g. apex + hiddenapi).
96*333d2b36SAndroid Build Coastguard Worker//
97*333d2b36SAndroid Build Coastguard Worker// TestResult
98*333d2b36SAndroid Build Coastguard Worker// ==========
99*333d2b36SAndroid Build Coastguard Worker// These are created by running tests in a Fixture and provide access to the Config and TestContext
100*333d2b36SAndroid Build Coastguard Worker// in which the tests were run.
101*333d2b36SAndroid Build Coastguard Worker//
102*333d2b36SAndroid Build Coastguard Worker// Example
103*333d2b36SAndroid Build Coastguard Worker// =======
104*333d2b36SAndroid Build Coastguard Worker//
105*333d2b36SAndroid Build Coastguard Worker// An exported preparer for use by other packages that need to use java modules.
106*333d2b36SAndroid Build Coastguard Worker//
107*333d2b36SAndroid Build Coastguard Worker// package java
108*333d2b36SAndroid Build Coastguard Worker// var PrepareForIntegrationTestWithJava = GroupFixturePreparers(
109*333d2b36SAndroid Build Coastguard Worker//    android.PrepareForIntegrationTestWithAndroid,
110*333d2b36SAndroid Build Coastguard Worker//    FixtureRegisterWithContext(RegisterAGroupOfRelatedModulesMutatorsAndSingletons),
111*333d2b36SAndroid Build Coastguard Worker//    FixtureRegisterWithContext(RegisterAnotherGroupOfRelatedModulesMutatorsAndSingletons),
112*333d2b36SAndroid Build Coastguard Worker//    ...
113*333d2b36SAndroid Build Coastguard Worker// )
114*333d2b36SAndroid Build Coastguard Worker//
115*333d2b36SAndroid Build Coastguard Worker// Some files to use in tests in the java package.
116*333d2b36SAndroid Build Coastguard Worker//
117*333d2b36SAndroid Build Coastguard Worker// var javaMockFS = android.MockFS{
118*333d2b36SAndroid Build Coastguard Worker//    "api/current.txt":        nil,
119*333d2b36SAndroid Build Coastguard Worker//    "api/removed.txt":        nil,
120*333d2b36SAndroid Build Coastguard Worker//    ...
121*333d2b36SAndroid Build Coastguard Worker// }
122*333d2b36SAndroid Build Coastguard Worker//
123*333d2b36SAndroid Build Coastguard Worker// A package private preparer for use for testing java within the java package.
124*333d2b36SAndroid Build Coastguard Worker//
125*333d2b36SAndroid Build Coastguard Worker// var prepareForJavaTest = android.GroupFixturePreparers(
126*333d2b36SAndroid Build Coastguard Worker//    PrepareForIntegrationTestWithJava,
127*333d2b36SAndroid Build Coastguard Worker//    FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
128*333d2b36SAndroid Build Coastguard Worker//      ctx.RegisterModuleType("test_module", testModule)
129*333d2b36SAndroid Build Coastguard Worker//    }),
130*333d2b36SAndroid Build Coastguard Worker//    javaMockFS.AddToFixture(),
131*333d2b36SAndroid Build Coastguard Worker//    ...
132*333d2b36SAndroid Build Coastguard Worker// }
133*333d2b36SAndroid Build Coastguard Worker//
134*333d2b36SAndroid Build Coastguard Worker// func TestJavaStuff(t *testing.T) {
135*333d2b36SAndroid Build Coastguard Worker//   result := android.GroupFixturePreparers(
136*333d2b36SAndroid Build Coastguard Worker//       prepareForJavaTest,
137*333d2b36SAndroid Build Coastguard Worker//       android.FixtureWithRootAndroidBp(`java_library {....}`),
138*333d2b36SAndroid Build Coastguard Worker//       android.MockFS{...}.AddToFixture(),
139*333d2b36SAndroid Build Coastguard Worker//   ).RunTest(t)
140*333d2b36SAndroid Build Coastguard Worker//   ... test result ...
141*333d2b36SAndroid Build Coastguard Worker// }
142*333d2b36SAndroid Build Coastguard Worker//
143*333d2b36SAndroid Build Coastguard Worker// package cc
144*333d2b36SAndroid Build Coastguard Worker// var PrepareForTestWithCC = android.GroupFixturePreparers(
145*333d2b36SAndroid Build Coastguard Worker//    android.PrepareForArchMutator,
146*333d2b36SAndroid Build Coastguard Worker//    android.prepareForPrebuilts,
147*333d2b36SAndroid Build Coastguard Worker//    FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
148*333d2b36SAndroid Build Coastguard Worker//    ...
149*333d2b36SAndroid Build Coastguard Worker// )
150*333d2b36SAndroid Build Coastguard Worker//
151*333d2b36SAndroid Build Coastguard Worker// package apex
152*333d2b36SAndroid Build Coastguard Worker//
153*333d2b36SAndroid Build Coastguard Worker// var PrepareForApex = GroupFixturePreparers(
154*333d2b36SAndroid Build Coastguard Worker//    ...
155*333d2b36SAndroid Build Coastguard Worker// )
156*333d2b36SAndroid Build Coastguard Worker//
157*333d2b36SAndroid Build Coastguard Worker// Use modules and mutators from java, cc and apex. Any duplicate preparers (like
158*333d2b36SAndroid Build Coastguard Worker// android.PrepareForArchMutator) will be automatically deduped.
159*333d2b36SAndroid Build Coastguard Worker//
160*333d2b36SAndroid Build Coastguard Worker// var prepareForApexTest = android.GroupFixturePreparers(
161*333d2b36SAndroid Build Coastguard Worker//    PrepareForJava,
162*333d2b36SAndroid Build Coastguard Worker//    PrepareForCC,
163*333d2b36SAndroid Build Coastguard Worker//    PrepareForApex,
164*333d2b36SAndroid Build Coastguard Worker// )
165*333d2b36SAndroid Build Coastguard Worker//
166*333d2b36SAndroid Build Coastguard Worker
167*333d2b36SAndroid Build Coastguard Worker// A set of mock files to add to the mock file system.
168*333d2b36SAndroid Build Coastguard Workertype MockFS map[string][]byte
169*333d2b36SAndroid Build Coastguard Worker
170*333d2b36SAndroid Build Coastguard Worker// Merge adds the extra entries from the supplied map to this one.
171*333d2b36SAndroid Build Coastguard Worker//
172*333d2b36SAndroid Build Coastguard Worker// Fails if the supplied map files with the same paths are present in both of them.
173*333d2b36SAndroid Build Coastguard Workerfunc (fs MockFS) Merge(extra map[string][]byte) {
174*333d2b36SAndroid Build Coastguard Worker	for p, c := range extra {
175*333d2b36SAndroid Build Coastguard Worker		validateFixtureMockFSPath(p)
176*333d2b36SAndroid Build Coastguard Worker		if _, ok := fs[p]; ok {
177*333d2b36SAndroid Build Coastguard Worker			panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists", p))
178*333d2b36SAndroid Build Coastguard Worker		}
179*333d2b36SAndroid Build Coastguard Worker		fs[p] = c
180*333d2b36SAndroid Build Coastguard Worker	}
181*333d2b36SAndroid Build Coastguard Worker}
182*333d2b36SAndroid Build Coastguard Worker
183*333d2b36SAndroid Build Coastguard Worker// Ensure that tests cannot add paths into the mock file system which would not be allowed in the
184*333d2b36SAndroid Build Coastguard Worker// runtime, e.g. absolute paths, paths relative to the 'out/' directory.
185*333d2b36SAndroid Build Coastguard Workerfunc validateFixtureMockFSPath(path string) {
186*333d2b36SAndroid Build Coastguard Worker	// This uses validateSafePath rather than validatePath because the latter prevents adding files
187*333d2b36SAndroid Build Coastguard Worker	// that include a $ but there are tests that allow files with a $ to be used, albeit only by
188*333d2b36SAndroid Build Coastguard Worker	// globbing.
189*333d2b36SAndroid Build Coastguard Worker	validatedPath, err := validateSafePath(path)
190*333d2b36SAndroid Build Coastguard Worker	if err != nil {
191*333d2b36SAndroid Build Coastguard Worker		panic(err)
192*333d2b36SAndroid Build Coastguard Worker	}
193*333d2b36SAndroid Build Coastguard Worker
194*333d2b36SAndroid Build Coastguard Worker	// Make sure that the path is canonical.
195*333d2b36SAndroid Build Coastguard Worker	if validatedPath != path {
196*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("path %q is not a canonical path, use %q instead", path, validatedPath))
197*333d2b36SAndroid Build Coastguard Worker	}
198*333d2b36SAndroid Build Coastguard Worker
199*333d2b36SAndroid Build Coastguard Worker	if path == "out" || strings.HasPrefix(path, "out/") {
200*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("cannot add output path %q to the mock file system", path))
201*333d2b36SAndroid Build Coastguard Worker	}
202*333d2b36SAndroid Build Coastguard Worker}
203*333d2b36SAndroid Build Coastguard Worker
204*333d2b36SAndroid Build Coastguard Workerfunc (fs MockFS) AddToFixture() FixturePreparer {
205*333d2b36SAndroid Build Coastguard Worker	return FixtureMergeMockFs(fs)
206*333d2b36SAndroid Build Coastguard Worker}
207*333d2b36SAndroid Build Coastguard Worker
208*333d2b36SAndroid Build Coastguard Worker// FixtureCustomPreparer allows for the modification of any aspect of the fixture.
209*333d2b36SAndroid Build Coastguard Worker//
210*333d2b36SAndroid Build Coastguard Worker// This should only be used if one of the other more specific preparers are not suitable.
211*333d2b36SAndroid Build Coastguard Workerfunc FixtureCustomPreparer(mutator func(fixture Fixture)) FixturePreparer {
212*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
213*333d2b36SAndroid Build Coastguard Worker		mutator(f)
214*333d2b36SAndroid Build Coastguard Worker	})
215*333d2b36SAndroid Build Coastguard Worker}
216*333d2b36SAndroid Build Coastguard Worker
217*333d2b36SAndroid Build Coastguard Worker// FixtureTestRunner determines the type of test to run.
218*333d2b36SAndroid Build Coastguard Worker//
219*333d2b36SAndroid Build Coastguard Worker// If no custom FixtureTestRunner is provided (using the FixtureSetTestRunner) then the default test
220*333d2b36SAndroid Build Coastguard Worker// runner will run a standard Soong test that corresponds to what happens when Soong is run on the
221*333d2b36SAndroid Build Coastguard Worker// command line.
222*333d2b36SAndroid Build Coastguard Workertype FixtureTestRunner interface {
223*333d2b36SAndroid Build Coastguard Worker	// FinalPreparer is a function that is run immediately before parsing the blueprint files. It is
224*333d2b36SAndroid Build Coastguard Worker	// intended to perform the initialization needed by PostParseProcessor.
225*333d2b36SAndroid Build Coastguard Worker	//
226*333d2b36SAndroid Build Coastguard Worker	// It returns a CustomTestResult that is passed into PostParseProcessor and returned from
227*333d2b36SAndroid Build Coastguard Worker	// FixturePreparer.RunTestWithCustomResult. If it needs to return some custom data then it must
228*333d2b36SAndroid Build Coastguard Worker	// provide its own implementation of CustomTestResult and return an instance of that. Otherwise,
229*333d2b36SAndroid Build Coastguard Worker	// it can just return the supplied *TestResult.
230*333d2b36SAndroid Build Coastguard Worker	FinalPreparer(result *TestResult) CustomTestResult
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	// PostParseProcessor is called after successfully parsing the blueprint files and can do further
233*333d2b36SAndroid Build Coastguard Worker	// work on the result of parsing the files.
234*333d2b36SAndroid Build Coastguard Worker	//
235*333d2b36SAndroid Build Coastguard Worker	// Successfully parsing simply means that no errors were encountered when parsing the blueprint
236*333d2b36SAndroid Build Coastguard Worker	// files.
237*333d2b36SAndroid Build Coastguard Worker	//
238*333d2b36SAndroid Build Coastguard Worker	// This must collate any information useful for testing, e.g. errs, ninja deps and custom data in
239*333d2b36SAndroid Build Coastguard Worker	// the supplied result.
240*333d2b36SAndroid Build Coastguard Worker	PostParseProcessor(result CustomTestResult)
241*333d2b36SAndroid Build Coastguard Worker}
242*333d2b36SAndroid Build Coastguard Worker
243*333d2b36SAndroid Build Coastguard Worker// FixtureSetTestRunner sets the FixtureTestRunner in the fixture.
244*333d2b36SAndroid Build Coastguard Worker//
245*333d2b36SAndroid Build Coastguard Worker// It is an error if more than one of these is applied to a single fixture. If none of these are
246*333d2b36SAndroid Build Coastguard Worker// applied then the fixture will use the defaultTestRunner which will run the test as if it was
247*333d2b36SAndroid Build Coastguard Worker// being run in `m <target>`.
248*333d2b36SAndroid Build Coastguard Workerfunc FixtureSetTestRunner(testRunner FixtureTestRunner) FixturePreparer {
249*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(fixture *fixture) {
250*333d2b36SAndroid Build Coastguard Worker		if fixture.testRunner != nil {
251*333d2b36SAndroid Build Coastguard Worker			panic("fixture test runner has already been set")
252*333d2b36SAndroid Build Coastguard Worker		}
253*333d2b36SAndroid Build Coastguard Worker		fixture.testRunner = testRunner
254*333d2b36SAndroid Build Coastguard Worker	})
255*333d2b36SAndroid Build Coastguard Worker}
256*333d2b36SAndroid Build Coastguard Worker
257*333d2b36SAndroid Build Coastguard Worker// Modify the config
258*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
259*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
260*333d2b36SAndroid Build Coastguard Worker		mutator(f.config)
261*333d2b36SAndroid Build Coastguard Worker	})
262*333d2b36SAndroid Build Coastguard Worker}
263*333d2b36SAndroid Build Coastguard Worker
264*333d2b36SAndroid Build Coastguard Worker// Modify the config and context
265*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyConfigAndContext(mutator func(config Config, ctx *TestContext)) FixturePreparer {
266*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
267*333d2b36SAndroid Build Coastguard Worker		mutator(f.config, f.ctx)
268*333d2b36SAndroid Build Coastguard Worker	})
269*333d2b36SAndroid Build Coastguard Worker}
270*333d2b36SAndroid Build Coastguard Worker
271*333d2b36SAndroid Build Coastguard Worker// Modify the context
272*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyContext(mutator func(ctx *TestContext)) FixturePreparer {
273*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
274*333d2b36SAndroid Build Coastguard Worker		mutator(f.ctx)
275*333d2b36SAndroid Build Coastguard Worker	})
276*333d2b36SAndroid Build Coastguard Worker}
277*333d2b36SAndroid Build Coastguard Worker
278*333d2b36SAndroid Build Coastguard Worker// Sync the mock filesystem with the current config, then modify the context,
279*333d2b36SAndroid Build Coastguard Worker// This allows context modification that requires filesystem access.
280*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyContextWithMockFs(mutator func(ctx *TestContext)) FixturePreparer {
281*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
282*333d2b36SAndroid Build Coastguard Worker		f.config.mockFileSystem("", f.mockFS)
283*333d2b36SAndroid Build Coastguard Worker		mutator(f.ctx)
284*333d2b36SAndroid Build Coastguard Worker	})
285*333d2b36SAndroid Build Coastguard Worker}
286*333d2b36SAndroid Build Coastguard Worker
287*333d2b36SAndroid Build Coastguard Workerfunc FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
288*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
289*333d2b36SAndroid Build Coastguard Worker}
290*333d2b36SAndroid Build Coastguard Worker
291*333d2b36SAndroid Build Coastguard Worker// Modify the mock filesystem
292*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyMockFS(mutator func(fs MockFS)) FixturePreparer {
293*333d2b36SAndroid Build Coastguard Worker	return newSimpleFixturePreparer(func(f *fixture) {
294*333d2b36SAndroid Build Coastguard Worker		mutator(f.mockFS)
295*333d2b36SAndroid Build Coastguard Worker
296*333d2b36SAndroid Build Coastguard Worker		// Make sure that invalid paths were not added to the mock filesystem.
297*333d2b36SAndroid Build Coastguard Worker		for p, _ := range f.mockFS {
298*333d2b36SAndroid Build Coastguard Worker			validateFixtureMockFSPath(p)
299*333d2b36SAndroid Build Coastguard Worker		}
300*333d2b36SAndroid Build Coastguard Worker	})
301*333d2b36SAndroid Build Coastguard Worker}
302*333d2b36SAndroid Build Coastguard Worker
303*333d2b36SAndroid Build Coastguard Worker// Merge the supplied file system into the mock filesystem.
304*333d2b36SAndroid Build Coastguard Worker//
305*333d2b36SAndroid Build Coastguard Worker// Paths that already exist in the mock file system are overridden.
306*333d2b36SAndroid Build Coastguard Workerfunc FixtureMergeMockFs(mockFS MockFS) FixturePreparer {
307*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyMockFS(func(fs MockFS) {
308*333d2b36SAndroid Build Coastguard Worker		fs.Merge(mockFS)
309*333d2b36SAndroid Build Coastguard Worker	})
310*333d2b36SAndroid Build Coastguard Worker}
311*333d2b36SAndroid Build Coastguard Worker
312*333d2b36SAndroid Build Coastguard Worker// Add a file to the mock filesystem
313*333d2b36SAndroid Build Coastguard Worker//
314*333d2b36SAndroid Build Coastguard Worker// Fail if the filesystem already contains a file with that path, use FixtureOverrideFile instead.
315*333d2b36SAndroid Build Coastguard Workerfunc FixtureAddFile(path string, contents []byte) FixturePreparer {
316*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyMockFS(func(fs MockFS) {
317*333d2b36SAndroid Build Coastguard Worker		validateFixtureMockFSPath(path)
318*333d2b36SAndroid Build Coastguard Worker		if _, ok := fs[path]; ok {
319*333d2b36SAndroid Build Coastguard Worker			panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists, use FixtureOverride*File instead", path))
320*333d2b36SAndroid Build Coastguard Worker		}
321*333d2b36SAndroid Build Coastguard Worker		fs[path] = contents
322*333d2b36SAndroid Build Coastguard Worker	})
323*333d2b36SAndroid Build Coastguard Worker}
324*333d2b36SAndroid Build Coastguard Worker
325*333d2b36SAndroid Build Coastguard Worker// Add a text file to the mock filesystem
326*333d2b36SAndroid Build Coastguard Worker//
327*333d2b36SAndroid Build Coastguard Worker// Fail if the filesystem already contains a file with that path.
328*333d2b36SAndroid Build Coastguard Workerfunc FixtureAddTextFile(path string, contents string) FixturePreparer {
329*333d2b36SAndroid Build Coastguard Worker	return FixtureAddFile(path, []byte(contents))
330*333d2b36SAndroid Build Coastguard Worker}
331*333d2b36SAndroid Build Coastguard Worker
332*333d2b36SAndroid Build Coastguard Worker// Override a file in the mock filesystem
333*333d2b36SAndroid Build Coastguard Worker//
334*333d2b36SAndroid Build Coastguard Worker// If the file does not exist this behaves as FixtureAddFile.
335*333d2b36SAndroid Build Coastguard Workerfunc FixtureOverrideFile(path string, contents []byte) FixturePreparer {
336*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyMockFS(func(fs MockFS) {
337*333d2b36SAndroid Build Coastguard Worker		fs[path] = contents
338*333d2b36SAndroid Build Coastguard Worker	})
339*333d2b36SAndroid Build Coastguard Worker}
340*333d2b36SAndroid Build Coastguard Worker
341*333d2b36SAndroid Build Coastguard Worker// Override a text file in the mock filesystem
342*333d2b36SAndroid Build Coastguard Worker//
343*333d2b36SAndroid Build Coastguard Worker// If the file does not exist this behaves as FixtureAddTextFile.
344*333d2b36SAndroid Build Coastguard Workerfunc FixtureOverrideTextFile(path string, contents string) FixturePreparer {
345*333d2b36SAndroid Build Coastguard Worker	return FixtureOverrideFile(path, []byte(contents))
346*333d2b36SAndroid Build Coastguard Worker}
347*333d2b36SAndroid Build Coastguard Worker
348*333d2b36SAndroid Build Coastguard Worker// Add the root Android.bp file with the supplied contents.
349*333d2b36SAndroid Build Coastguard Workerfunc FixtureWithRootAndroidBp(contents string) FixturePreparer {
350*333d2b36SAndroid Build Coastguard Worker	return FixtureAddTextFile("Android.bp", contents)
351*333d2b36SAndroid Build Coastguard Worker}
352*333d2b36SAndroid Build Coastguard Worker
353*333d2b36SAndroid Build Coastguard Worker// Merge some environment variables into the fixture.
354*333d2b36SAndroid Build Coastguard Workerfunc FixtureMergeEnv(env map[string]string) FixturePreparer {
355*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyConfig(func(config Config) {
356*333d2b36SAndroid Build Coastguard Worker		for k, v := range env {
357*333d2b36SAndroid Build Coastguard Worker			if k == "PATH" {
358*333d2b36SAndroid Build Coastguard Worker				panic("Cannot set PATH environment variable")
359*333d2b36SAndroid Build Coastguard Worker			}
360*333d2b36SAndroid Build Coastguard Worker			config.env[k] = v
361*333d2b36SAndroid Build Coastguard Worker		}
362*333d2b36SAndroid Build Coastguard Worker	})
363*333d2b36SAndroid Build Coastguard Worker}
364*333d2b36SAndroid Build Coastguard Worker
365*333d2b36SAndroid Build Coastguard Worker// Modify the env.
366*333d2b36SAndroid Build Coastguard Worker//
367*333d2b36SAndroid Build Coastguard Worker// Will panic if the mutator changes the PATH environment variable.
368*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
369*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyConfig(func(config Config) {
370*333d2b36SAndroid Build Coastguard Worker		oldPath := config.env["PATH"]
371*333d2b36SAndroid Build Coastguard Worker		mutator(config.env)
372*333d2b36SAndroid Build Coastguard Worker		newPath := config.env["PATH"]
373*333d2b36SAndroid Build Coastguard Worker		if newPath != oldPath {
374*333d2b36SAndroid Build Coastguard Worker			panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
375*333d2b36SAndroid Build Coastguard Worker		}
376*333d2b36SAndroid Build Coastguard Worker	})
377*333d2b36SAndroid Build Coastguard Worker}
378*333d2b36SAndroid Build Coastguard Worker
379*333d2b36SAndroid Build Coastguard Worker// Allow access to the product variables when preparing the fixture.
380*333d2b36SAndroid Build Coastguard Workertype FixtureProductVariables struct {
381*333d2b36SAndroid Build Coastguard Worker	*ProductVariables
382*333d2b36SAndroid Build Coastguard Worker}
383*333d2b36SAndroid Build Coastguard Worker
384*333d2b36SAndroid Build Coastguard Worker// Modify product variables.
385*333d2b36SAndroid Build Coastguard Workerfunc FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
386*333d2b36SAndroid Build Coastguard Worker	return FixtureModifyConfig(func(config Config) {
387*333d2b36SAndroid Build Coastguard Worker		productVariables := FixtureProductVariables{&config.productVariables}
388*333d2b36SAndroid Build Coastguard Worker		mutator(productVariables)
389*333d2b36SAndroid Build Coastguard Worker	})
390*333d2b36SAndroid Build Coastguard Worker}
391*333d2b36SAndroid Build Coastguard Worker
392*333d2b36SAndroid Build Coastguard Workervar PrepareForSkipTestOnMac = newSimpleFixturePreparer(func(fixture *fixture) {
393*333d2b36SAndroid Build Coastguard Worker	if runtime.GOOS != "linux" {
394*333d2b36SAndroid Build Coastguard Worker		fixture.t.Skip("Test is only supported on linux.")
395*333d2b36SAndroid Build Coastguard Worker	}
396*333d2b36SAndroid Build Coastguard Worker})
397*333d2b36SAndroid Build Coastguard Worker
398*333d2b36SAndroid Build Coastguard Worker// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
399*333d2b36SAndroid Build Coastguard Worker// state before running the test.
400*333d2b36SAndroid Build Coastguard Worker//
401*333d2b36SAndroid Build Coastguard Worker// This must only be added temporarily to a test for local debugging and must be removed from the
402*333d2b36SAndroid Build Coastguard Worker// test before submitting.
403*333d2b36SAndroid Build Coastguard Workervar PrepareForDebug_DO_NOT_SUBMIT = newSimpleFixturePreparer(func(fixture *fixture) {
404*333d2b36SAndroid Build Coastguard Worker	fixture.debug = true
405*333d2b36SAndroid Build Coastguard Worker})
406*333d2b36SAndroid Build Coastguard Worker
407*333d2b36SAndroid Build Coastguard Worker// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
408*333d2b36SAndroid Build Coastguard Worker// the supplied FixturePreparer instances in order.
409*333d2b36SAndroid Build Coastguard Worker//
410*333d2b36SAndroid Build Coastguard Worker// Before preparing the fixture the list of preparers is flattened by replacing each
411*333d2b36SAndroid Build Coastguard Worker// instance of GroupFixturePreparers with its contents.
412*333d2b36SAndroid Build Coastguard Workerfunc GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
413*333d2b36SAndroid Build Coastguard Worker	all := dedupAndFlattenPreparers(nil, preparers)
414*333d2b36SAndroid Build Coastguard Worker	return newFixturePreparer(all)
415*333d2b36SAndroid Build Coastguard Worker}
416*333d2b36SAndroid Build Coastguard Worker
417*333d2b36SAndroid Build Coastguard Worker// NullFixturePreparer is a preparer that does nothing.
418*333d2b36SAndroid Build Coastguard Workervar NullFixturePreparer = GroupFixturePreparers()
419*333d2b36SAndroid Build Coastguard Worker
420*333d2b36SAndroid Build Coastguard Worker// OptionalFixturePreparer will return the supplied preparer if it is non-nil, otherwise it will
421*333d2b36SAndroid Build Coastguard Worker// return the NullFixturePreparer
422*333d2b36SAndroid Build Coastguard Workerfunc OptionalFixturePreparer(preparer FixturePreparer) FixturePreparer {
423*333d2b36SAndroid Build Coastguard Worker	if preparer == nil {
424*333d2b36SAndroid Build Coastguard Worker		return NullFixturePreparer
425*333d2b36SAndroid Build Coastguard Worker	} else {
426*333d2b36SAndroid Build Coastguard Worker		return preparer
427*333d2b36SAndroid Build Coastguard Worker	}
428*333d2b36SAndroid Build Coastguard Worker}
429*333d2b36SAndroid Build Coastguard Worker
430*333d2b36SAndroid Build Coastguard Worker// FixturePreparer provides the ability to create, modify and then run tests within a fixture.
431*333d2b36SAndroid Build Coastguard Workertype FixturePreparer interface {
432*333d2b36SAndroid Build Coastguard Worker	// Return the flattened and deduped list of simpleFixturePreparer pointers.
433*333d2b36SAndroid Build Coastguard Worker	list() []*simpleFixturePreparer
434*333d2b36SAndroid Build Coastguard Worker
435*333d2b36SAndroid Build Coastguard Worker	// Create a Fixture.
436*333d2b36SAndroid Build Coastguard Worker	Fixture(t *testing.T) Fixture
437*333d2b36SAndroid Build Coastguard Worker
438*333d2b36SAndroid Build Coastguard Worker	// ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
439*333d2b36SAndroid Build Coastguard Worker	// to check the errors (may be 0) reported by the test.
440*333d2b36SAndroid Build Coastguard Worker	//
441*333d2b36SAndroid Build Coastguard Worker	// The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
442*333d2b36SAndroid Build Coastguard Worker	// errors are reported.
443*333d2b36SAndroid Build Coastguard Worker	ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer
444*333d2b36SAndroid Build Coastguard Worker
445*333d2b36SAndroid Build Coastguard Worker	// Run the test, checking any errors reported and returning a TestResult instance.
446*333d2b36SAndroid Build Coastguard Worker	//
447*333d2b36SAndroid Build Coastguard Worker	// Shorthand for Fixture(t).RunTest()
448*333d2b36SAndroid Build Coastguard Worker	RunTest(t *testing.T) *TestResult
449*333d2b36SAndroid Build Coastguard Worker
450*333d2b36SAndroid Build Coastguard Worker	// RunTestWithCustomResult runs the test just as RunTest(t) does but instead of returning a
451*333d2b36SAndroid Build Coastguard Worker	// *TestResult it returns the CustomTestResult that was returned by the custom
452*333d2b36SAndroid Build Coastguard Worker	// FixtureTestRunner.PostParseProcessor method that ran the test, or the *TestResult if that
453*333d2b36SAndroid Build Coastguard Worker	// method returned nil.
454*333d2b36SAndroid Build Coastguard Worker	//
455*333d2b36SAndroid Build Coastguard Worker	// This method must be used when needing to access custom data collected by the
456*333d2b36SAndroid Build Coastguard Worker	// FixtureTestRunner.PostParseProcessor method.
457*333d2b36SAndroid Build Coastguard Worker	//
458*333d2b36SAndroid Build Coastguard Worker	// e.g. something like this
459*333d2b36SAndroid Build Coastguard Worker	//
460*333d2b36SAndroid Build Coastguard Worker	//   preparers := ...FixtureSetTestRunner(&myTestRunner)...
461*333d2b36SAndroid Build Coastguard Worker	//   customResult := preparers.RunTestWithCustomResult(t).(*myCustomTestResult)
462*333d2b36SAndroid Build Coastguard Worker	//   doSomething(customResult.data)
463*333d2b36SAndroid Build Coastguard Worker	RunTestWithCustomResult(t *testing.T) CustomTestResult
464*333d2b36SAndroid Build Coastguard Worker
465*333d2b36SAndroid Build Coastguard Worker	// Run the test with the supplied Android.bp file.
466*333d2b36SAndroid Build Coastguard Worker	//
467*333d2b36SAndroid Build Coastguard Worker	// preparer.RunTestWithBp(t, bp) is shorthand for
468*333d2b36SAndroid Build Coastguard Worker	// android.GroupFixturePreparers(preparer, android.FixtureWithRootAndroidBp(bp)).RunTest(t)
469*333d2b36SAndroid Build Coastguard Worker	RunTestWithBp(t *testing.T, bp string) *TestResult
470*333d2b36SAndroid Build Coastguard Worker
471*333d2b36SAndroid Build Coastguard Worker	// RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
472*333d2b36SAndroid Build Coastguard Worker	// the test fixture.
473*333d2b36SAndroid Build Coastguard Worker	//
474*333d2b36SAndroid Build Coastguard Worker	// In order to allow the Config object to be customized separately to the TestContext a lot of
475*333d2b36SAndroid Build Coastguard Worker	// existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
476*333d2b36SAndroid Build Coastguard Worker	// from the test and then have the TestContext created and configured automatically. e.g.
477*333d2b36SAndroid Build Coastguard Worker	// testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
478*333d2b36SAndroid Build Coastguard Worker	//
479*333d2b36SAndroid Build Coastguard Worker	// This method allows those methods to be migrated to use the test fixture pattern without
480*333d2b36SAndroid Build Coastguard Worker	// requiring that every test that uses those methods be migrated at the same time. That allows
481*333d2b36SAndroid Build Coastguard Worker	// those tests to benefit from correctness in the order of registration quickly.
482*333d2b36SAndroid Build Coastguard Worker	//
483*333d2b36SAndroid Build Coastguard Worker	// This method discards the config (along with its mock file system, product variables,
484*333d2b36SAndroid Build Coastguard Worker	// environment, etc.) that may have been set up by FixturePreparers.
485*333d2b36SAndroid Build Coastguard Worker	//
486*333d2b36SAndroid Build Coastguard Worker	// deprecated
487*333d2b36SAndroid Build Coastguard Worker	RunTestWithConfig(t *testing.T, config Config) *TestResult
488*333d2b36SAndroid Build Coastguard Worker}
489*333d2b36SAndroid Build Coastguard Worker
490*333d2b36SAndroid Build Coastguard Worker// dedupAndFlattenPreparers removes any duplicates and flattens any composite FixturePreparer
491*333d2b36SAndroid Build Coastguard Worker// instances.
492*333d2b36SAndroid Build Coastguard Worker//
493*333d2b36SAndroid Build Coastguard Worker// base      - a list of already flattened and deduped preparers that will be applied first before
494*333d2b36SAndroid Build Coastguard Worker//
495*333d2b36SAndroid Build Coastguard Worker//	the list of additional preparers. Any duplicates of these in the additional preparers
496*333d2b36SAndroid Build Coastguard Worker//	will be ignored.
497*333d2b36SAndroid Build Coastguard Worker//
498*333d2b36SAndroid Build Coastguard Worker// preparers - a list of additional unflattened, undeduped preparers that will be applied after the
499*333d2b36SAndroid Build Coastguard Worker//
500*333d2b36SAndroid Build Coastguard Worker//	base preparers.
501*333d2b36SAndroid Build Coastguard Worker//
502*333d2b36SAndroid Build Coastguard Worker// Returns a deduped and flattened list of the preparers starting with the ones in base with any
503*333d2b36SAndroid Build Coastguard Worker// additional ones from the preparers list added afterwards.
504*333d2b36SAndroid Build Coastguard Workerfunc dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers []FixturePreparer) []*simpleFixturePreparer {
505*333d2b36SAndroid Build Coastguard Worker	if len(preparers) == 0 {
506*333d2b36SAndroid Build Coastguard Worker		return base
507*333d2b36SAndroid Build Coastguard Worker	}
508*333d2b36SAndroid Build Coastguard Worker
509*333d2b36SAndroid Build Coastguard Worker	list := make([]*simpleFixturePreparer, len(base))
510*333d2b36SAndroid Build Coastguard Worker	visited := make(map[*simpleFixturePreparer]struct{})
511*333d2b36SAndroid Build Coastguard Worker
512*333d2b36SAndroid Build Coastguard Worker	// Mark the already flattened and deduped preparers, if any, as having been seen so that
513*333d2b36SAndroid Build Coastguard Worker	// duplicates of these in the additional preparers will be discarded. Add them to the output
514*333d2b36SAndroid Build Coastguard Worker	// list.
515*333d2b36SAndroid Build Coastguard Worker	for i, s := range base {
516*333d2b36SAndroid Build Coastguard Worker		visited[s] = struct{}{}
517*333d2b36SAndroid Build Coastguard Worker		list[i] = s
518*333d2b36SAndroid Build Coastguard Worker	}
519*333d2b36SAndroid Build Coastguard Worker
520*333d2b36SAndroid Build Coastguard Worker	for _, p := range preparers {
521*333d2b36SAndroid Build Coastguard Worker		for _, s := range p.list() {
522*333d2b36SAndroid Build Coastguard Worker			if _, seen := visited[s]; !seen {
523*333d2b36SAndroid Build Coastguard Worker				visited[s] = struct{}{}
524*333d2b36SAndroid Build Coastguard Worker				list = append(list, s)
525*333d2b36SAndroid Build Coastguard Worker			}
526*333d2b36SAndroid Build Coastguard Worker		}
527*333d2b36SAndroid Build Coastguard Worker	}
528*333d2b36SAndroid Build Coastguard Worker
529*333d2b36SAndroid Build Coastguard Worker	return list
530*333d2b36SAndroid Build Coastguard Worker}
531*333d2b36SAndroid Build Coastguard Worker
532*333d2b36SAndroid Build Coastguard Worker// compositeFixturePreparer is a FixturePreparer created from a list of fixture preparers.
533*333d2b36SAndroid Build Coastguard Workertype compositeFixturePreparer struct {
534*333d2b36SAndroid Build Coastguard Worker	baseFixturePreparer
535*333d2b36SAndroid Build Coastguard Worker	// The flattened and deduped list of simpleFixturePreparer pointers encapsulated within this
536*333d2b36SAndroid Build Coastguard Worker	// composite preparer.
537*333d2b36SAndroid Build Coastguard Worker	preparers []*simpleFixturePreparer
538*333d2b36SAndroid Build Coastguard Worker}
539*333d2b36SAndroid Build Coastguard Worker
540*333d2b36SAndroid Build Coastguard Workerfunc (c *compositeFixturePreparer) list() []*simpleFixturePreparer {
541*333d2b36SAndroid Build Coastguard Worker	return c.preparers
542*333d2b36SAndroid Build Coastguard Worker}
543*333d2b36SAndroid Build Coastguard Worker
544*333d2b36SAndroid Build Coastguard Workerfunc newFixturePreparer(preparers []*simpleFixturePreparer) FixturePreparer {
545*333d2b36SAndroid Build Coastguard Worker	if len(preparers) == 1 {
546*333d2b36SAndroid Build Coastguard Worker		return preparers[0]
547*333d2b36SAndroid Build Coastguard Worker	}
548*333d2b36SAndroid Build Coastguard Worker	p := &compositeFixturePreparer{
549*333d2b36SAndroid Build Coastguard Worker		preparers: preparers,
550*333d2b36SAndroid Build Coastguard Worker	}
551*333d2b36SAndroid Build Coastguard Worker	p.initBaseFixturePreparer(p)
552*333d2b36SAndroid Build Coastguard Worker	return p
553*333d2b36SAndroid Build Coastguard Worker}
554*333d2b36SAndroid Build Coastguard Worker
555*333d2b36SAndroid Build Coastguard Worker// simpleFixturePreparer is a FixturePreparer that applies a function to a fixture.
556*333d2b36SAndroid Build Coastguard Workertype simpleFixturePreparer struct {
557*333d2b36SAndroid Build Coastguard Worker	baseFixturePreparer
558*333d2b36SAndroid Build Coastguard Worker	function func(fixture *fixture)
559*333d2b36SAndroid Build Coastguard Worker}
560*333d2b36SAndroid Build Coastguard Worker
561*333d2b36SAndroid Build Coastguard Workerfunc (s *simpleFixturePreparer) list() []*simpleFixturePreparer {
562*333d2b36SAndroid Build Coastguard Worker	return []*simpleFixturePreparer{s}
563*333d2b36SAndroid Build Coastguard Worker}
564*333d2b36SAndroid Build Coastguard Worker
565*333d2b36SAndroid Build Coastguard Workerfunc newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer {
566*333d2b36SAndroid Build Coastguard Worker	p := &simpleFixturePreparer{function: preparer}
567*333d2b36SAndroid Build Coastguard Worker	p.initBaseFixturePreparer(p)
568*333d2b36SAndroid Build Coastguard Worker	return p
569*333d2b36SAndroid Build Coastguard Worker}
570*333d2b36SAndroid Build Coastguard Worker
571*333d2b36SAndroid Build Coastguard Worker// FixtureErrorHandler determines how to respond to errors reported by the code under test.
572*333d2b36SAndroid Build Coastguard Worker//
573*333d2b36SAndroid Build Coastguard Worker// Some possible responses:
574*333d2b36SAndroid Build Coastguard Worker//   - Fail the test if any errors are reported, see FixtureExpectsNoErrors.
575*333d2b36SAndroid Build Coastguard Worker//   - Fail the test if at least one error that matches a pattern is not reported see
576*333d2b36SAndroid Build Coastguard Worker//     FixtureExpectsAtLeastOneErrorMatchingPattern
577*333d2b36SAndroid Build Coastguard Worker//   - Fail the test if any unexpected errors are reported.
578*333d2b36SAndroid Build Coastguard Worker//
579*333d2b36SAndroid Build Coastguard Worker// Although at the moment all the error handlers are implemented as simply a wrapper around a
580*333d2b36SAndroid Build Coastguard Worker// function this is defined as an interface to allow future enhancements, e.g. provide different
581*333d2b36SAndroid Build Coastguard Worker// ways other than patterns to match an error and to combine handlers together.
582*333d2b36SAndroid Build Coastguard Workertype FixtureErrorHandler interface {
583*333d2b36SAndroid Build Coastguard Worker	// CheckErrors checks the errors reported.
584*333d2b36SAndroid Build Coastguard Worker	//
585*333d2b36SAndroid Build Coastguard Worker	// The supplied result can be used to access the state of the code under test just as the main
586*333d2b36SAndroid Build Coastguard Worker	// body of the test would but if any errors other than ones expected are reported the state may
587*333d2b36SAndroid Build Coastguard Worker	// be indeterminate.
588*333d2b36SAndroid Build Coastguard Worker	CheckErrors(t *testing.T, result *TestResult)
589*333d2b36SAndroid Build Coastguard Worker}
590*333d2b36SAndroid Build Coastguard Worker
591*333d2b36SAndroid Build Coastguard Workertype simpleErrorHandler struct {
592*333d2b36SAndroid Build Coastguard Worker	function func(t *testing.T, result *TestResult)
593*333d2b36SAndroid Build Coastguard Worker}
594*333d2b36SAndroid Build Coastguard Worker
595*333d2b36SAndroid Build Coastguard Workerfunc (h simpleErrorHandler) CheckErrors(t *testing.T, result *TestResult) {
596*333d2b36SAndroid Build Coastguard Worker	t.Helper()
597*333d2b36SAndroid Build Coastguard Worker	h.function(t, result)
598*333d2b36SAndroid Build Coastguard Worker}
599*333d2b36SAndroid Build Coastguard Worker
600*333d2b36SAndroid Build Coastguard Worker// The default fixture error handler.
601*333d2b36SAndroid Build Coastguard Worker//
602*333d2b36SAndroid Build Coastguard Worker// Will fail the test immediately if any errors are reported.
603*333d2b36SAndroid Build Coastguard Worker//
604*333d2b36SAndroid Build Coastguard Worker// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
605*333d2b36SAndroid Build Coastguard Worker// which the test is being run which means that the RunTest() method will not return.
606*333d2b36SAndroid Build Coastguard Workervar FixtureExpectsNoErrors = FixtureCustomErrorHandler(
607*333d2b36SAndroid Build Coastguard Worker	func(t *testing.T, result *TestResult) {
608*333d2b36SAndroid Build Coastguard Worker		t.Helper()
609*333d2b36SAndroid Build Coastguard Worker		FailIfErrored(t, result.Errs)
610*333d2b36SAndroid Build Coastguard Worker	},
611*333d2b36SAndroid Build Coastguard Worker)
612*333d2b36SAndroid Build Coastguard Worker
613*333d2b36SAndroid Build Coastguard Worker// FixtureIgnoreErrors ignores any errors.
614*333d2b36SAndroid Build Coastguard Worker//
615*333d2b36SAndroid Build Coastguard Worker// If this is used then it is the responsibility of the test to check the TestResult.Errs does not
616*333d2b36SAndroid Build Coastguard Worker// contain any unexpected errors.
617*333d2b36SAndroid Build Coastguard Workervar FixtureIgnoreErrors = FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
618*333d2b36SAndroid Build Coastguard Worker	// Ignore the errors
619*333d2b36SAndroid Build Coastguard Worker})
620*333d2b36SAndroid Build Coastguard Worker
621*333d2b36SAndroid Build Coastguard Worker// FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail
622*333d2b36SAndroid Build Coastguard Worker// if at least one error that matches the regular expression is not found.
623*333d2b36SAndroid Build Coastguard Worker//
624*333d2b36SAndroid Build Coastguard Worker// The test will be failed if:
625*333d2b36SAndroid Build Coastguard Worker// * No errors are reported.
626*333d2b36SAndroid Build Coastguard Worker// * One or more errors are reported but none match the pattern.
627*333d2b36SAndroid Build Coastguard Worker//
628*333d2b36SAndroid Build Coastguard Worker// The test will not fail if:
629*333d2b36SAndroid Build Coastguard Worker// * Multiple errors are reported that do not match the pattern as long as one does match.
630*333d2b36SAndroid Build Coastguard Worker//
631*333d2b36SAndroid Build Coastguard Worker// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
632*333d2b36SAndroid Build Coastguard Worker// which the test is being run which means that the RunTest() method will not return.
633*333d2b36SAndroid Build Coastguard Workerfunc FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
634*333d2b36SAndroid Build Coastguard Worker	return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
635*333d2b36SAndroid Build Coastguard Worker		t.Helper()
636*333d2b36SAndroid Build Coastguard Worker		if !FailIfNoMatchingErrors(t, pattern, result.Errs) {
637*333d2b36SAndroid Build Coastguard Worker			t.FailNow()
638*333d2b36SAndroid Build Coastguard Worker		}
639*333d2b36SAndroid Build Coastguard Worker	})
640*333d2b36SAndroid Build Coastguard Worker}
641*333d2b36SAndroid Build Coastguard Worker
642*333d2b36SAndroid Build Coastguard Worker// FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail
643*333d2b36SAndroid Build Coastguard Worker// if there are any unexpected errors.
644*333d2b36SAndroid Build Coastguard Worker//
645*333d2b36SAndroid Build Coastguard Worker// The test will be failed if:
646*333d2b36SAndroid Build Coastguard Worker// * The number of errors reported does not exactly match the patterns.
647*333d2b36SAndroid Build Coastguard Worker// * One or more of the reported errors do not match a pattern.
648*333d2b36SAndroid Build Coastguard Worker// * No patterns are provided and one or more errors are reported.
649*333d2b36SAndroid Build Coastguard Worker//
650*333d2b36SAndroid Build Coastguard Worker// The test will not fail if:
651*333d2b36SAndroid Build Coastguard Worker// * One or more of the patterns does not match an error.
652*333d2b36SAndroid Build Coastguard Worker//
653*333d2b36SAndroid Build Coastguard Worker// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
654*333d2b36SAndroid Build Coastguard Worker// which the test is being run which means that the RunTest() method will not return.
655*333d2b36SAndroid Build Coastguard Workerfunc FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
656*333d2b36SAndroid Build Coastguard Worker	return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
657*333d2b36SAndroid Build Coastguard Worker		t.Helper()
658*333d2b36SAndroid Build Coastguard Worker		CheckErrorsAgainstExpectations(t, result.Errs, patterns)
659*333d2b36SAndroid Build Coastguard Worker	})
660*333d2b36SAndroid Build Coastguard Worker}
661*333d2b36SAndroid Build Coastguard Worker
662*333d2b36SAndroid Build Coastguard Worker// FixtureExpectsOneErrorPattern returns an error handler that will cause the test to fail
663*333d2b36SAndroid Build Coastguard Worker// if there is more than one error or the error does not match the pattern.
664*333d2b36SAndroid Build Coastguard Worker//
665*333d2b36SAndroid Build Coastguard Worker// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
666*333d2b36SAndroid Build Coastguard Worker// which the test is being run which means that the RunTest() method will not return.
667*333d2b36SAndroid Build Coastguard Workerfunc FixtureExpectsOneErrorPattern(pattern string) FixtureErrorHandler {
668*333d2b36SAndroid Build Coastguard Worker	return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
669*333d2b36SAndroid Build Coastguard Worker		t.Helper()
670*333d2b36SAndroid Build Coastguard Worker		CheckErrorsAgainstExpectations(t, result.Errs, []string{pattern})
671*333d2b36SAndroid Build Coastguard Worker	})
672*333d2b36SAndroid Build Coastguard Worker}
673*333d2b36SAndroid Build Coastguard Worker
674*333d2b36SAndroid Build Coastguard Worker// FixtureCustomErrorHandler creates a custom error handler
675*333d2b36SAndroid Build Coastguard Workerfunc FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler {
676*333d2b36SAndroid Build Coastguard Worker	return simpleErrorHandler{
677*333d2b36SAndroid Build Coastguard Worker		function: function,
678*333d2b36SAndroid Build Coastguard Worker	}
679*333d2b36SAndroid Build Coastguard Worker}
680*333d2b36SAndroid Build Coastguard Worker
681*333d2b36SAndroid Build Coastguard Worker// Fixture defines the test environment.
682*333d2b36SAndroid Build Coastguard Workertype Fixture interface {
683*333d2b36SAndroid Build Coastguard Worker	// Config returns the fixture's configuration.
684*333d2b36SAndroid Build Coastguard Worker	Config() Config
685*333d2b36SAndroid Build Coastguard Worker
686*333d2b36SAndroid Build Coastguard Worker	// Context returns the fixture's test context.
687*333d2b36SAndroid Build Coastguard Worker	Context() *TestContext
688*333d2b36SAndroid Build Coastguard Worker
689*333d2b36SAndroid Build Coastguard Worker	// MockFS returns the fixture's mock filesystem.
690*333d2b36SAndroid Build Coastguard Worker	MockFS() MockFS
691*333d2b36SAndroid Build Coastguard Worker
692*333d2b36SAndroid Build Coastguard Worker	// Run the test, checking any errors reported and returning a TestResult instance.
693*333d2b36SAndroid Build Coastguard Worker	RunTest() CustomTestResult
694*333d2b36SAndroid Build Coastguard Worker}
695*333d2b36SAndroid Build Coastguard Worker
696*333d2b36SAndroid Build Coastguard Worker// Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
697*333d2b36SAndroid Build Coastguard Workertype testContext struct {
698*333d2b36SAndroid Build Coastguard Worker	*TestContext
699*333d2b36SAndroid Build Coastguard Worker}
700*333d2b36SAndroid Build Coastguard Worker
701*333d2b36SAndroid Build Coastguard Worker// The result of running a test.
702*333d2b36SAndroid Build Coastguard Workertype TestResult struct {
703*333d2b36SAndroid Build Coastguard Worker	testContext
704*333d2b36SAndroid Build Coastguard Worker
705*333d2b36SAndroid Build Coastguard Worker	fixture *fixture
706*333d2b36SAndroid Build Coastguard Worker	Config  Config
707*333d2b36SAndroid Build Coastguard Worker
708*333d2b36SAndroid Build Coastguard Worker	// The errors that were reported during the test.
709*333d2b36SAndroid Build Coastguard Worker	Errs []error
710*333d2b36SAndroid Build Coastguard Worker
711*333d2b36SAndroid Build Coastguard Worker	// The ninja deps is a list of the ninja files dependencies that were added by the modules and
712*333d2b36SAndroid Build Coastguard Worker	// singletons via the *.AddNinjaFileDeps() methods.
713*333d2b36SAndroid Build Coastguard Worker	NinjaDeps []string
714*333d2b36SAndroid Build Coastguard Worker}
715*333d2b36SAndroid Build Coastguard Worker
716*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) testResult() *TestResult { return r }
717*333d2b36SAndroid Build Coastguard Worker
718*333d2b36SAndroid Build Coastguard Worker// CustomTestResult is the interface that FixtureTestRunner implementations who wish to return
719*333d2b36SAndroid Build Coastguard Worker// custom data must implement. It must embed *TestResult and initialize that to the value passed
720*333d2b36SAndroid Build Coastguard Worker// into the method. It is returned from the FixtureTestRunner.FinalPreparer, passed into the
721*333d2b36SAndroid Build Coastguard Worker// FixtureTestRunner.PostParseProcessor and returned from FixturePreparer.RunTestWithCustomResult.
722*333d2b36SAndroid Build Coastguard Worker//
723*333d2b36SAndroid Build Coastguard Worker// e.g. something like this:
724*333d2b36SAndroid Build Coastguard Worker//
725*333d2b36SAndroid Build Coastguard Worker//		type myCustomTestResult struct {
726*333d2b36SAndroid Build Coastguard Worker//		    *android.TestResult
727*333d2b36SAndroid Build Coastguard Worker//		    data []string
728*333d2b36SAndroid Build Coastguard Worker//		}
729*333d2b36SAndroid Build Coastguard Worker//
730*333d2b36SAndroid Build Coastguard Worker//		func (r *myTestRunner) FinalPreparer(result *TestResult) CustomTestResult {
731*333d2b36SAndroid Build Coastguard Worker//	     ... do some final test preparation ...
732*333d2b36SAndroid Build Coastguard Worker//	     return &myCustomTestResult{TestResult: result)
733*333d2b36SAndroid Build Coastguard Worker//	 }
734*333d2b36SAndroid Build Coastguard Worker//
735*333d2b36SAndroid Build Coastguard Worker//		func (r *myTestRunner) PostParseProcessor(result CustomTestResult) {
736*333d2b36SAndroid Build Coastguard Worker//		    ...
737*333d2b36SAndroid Build Coastguard Worker//		    myData := []string {....}
738*333d2b36SAndroid Build Coastguard Worker//		    ...
739*333d2b36SAndroid Build Coastguard Worker//		    customResult := result.(*myCustomTestResult)
740*333d2b36SAndroid Build Coastguard Worker//	     customResult.data = myData
741*333d2b36SAndroid Build Coastguard Worker//		}
742*333d2b36SAndroid Build Coastguard Workertype CustomTestResult interface {
743*333d2b36SAndroid Build Coastguard Worker	// testResult returns the embedded *TestResult.
744*333d2b36SAndroid Build Coastguard Worker	testResult() *TestResult
745*333d2b36SAndroid Build Coastguard Worker}
746*333d2b36SAndroid Build Coastguard Worker
747*333d2b36SAndroid Build Coastguard Workervar _ CustomTestResult = (*TestResult)(nil)
748*333d2b36SAndroid Build Coastguard Worker
749*333d2b36SAndroid Build Coastguard Workertype TestPathContext struct {
750*333d2b36SAndroid Build Coastguard Worker	*TestResult
751*333d2b36SAndroid Build Coastguard Worker}
752*333d2b36SAndroid Build Coastguard Worker
753*333d2b36SAndroid Build Coastguard Workervar _ PathContext = &TestPathContext{}
754*333d2b36SAndroid Build Coastguard Worker
755*333d2b36SAndroid Build Coastguard Workerfunc (t *TestPathContext) Config() Config {
756*333d2b36SAndroid Build Coastguard Worker	return t.TestResult.Config
757*333d2b36SAndroid Build Coastguard Worker}
758*333d2b36SAndroid Build Coastguard Worker
759*333d2b36SAndroid Build Coastguard Workerfunc (t *TestPathContext) AddNinjaFileDeps(deps ...string) {
760*333d2b36SAndroid Build Coastguard Worker	panic("unimplemented")
761*333d2b36SAndroid Build Coastguard Worker}
762*333d2b36SAndroid Build Coastguard Worker
763*333d2b36SAndroid Build Coastguard Workerfunc createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
764*333d2b36SAndroid Build Coastguard Worker	config := TestConfig(buildDir, nil, "", nil)
765*333d2b36SAndroid Build Coastguard Worker	ctx := newTestContextForFixture(config)
766*333d2b36SAndroid Build Coastguard Worker	fixture := &fixture{
767*333d2b36SAndroid Build Coastguard Worker		preparers: preparers,
768*333d2b36SAndroid Build Coastguard Worker		t:         t,
769*333d2b36SAndroid Build Coastguard Worker		config:    config,
770*333d2b36SAndroid Build Coastguard Worker		ctx:       ctx,
771*333d2b36SAndroid Build Coastguard Worker		mockFS:    make(MockFS),
772*333d2b36SAndroid Build Coastguard Worker		// Set the default error handler.
773*333d2b36SAndroid Build Coastguard Worker		errorHandler: FixtureExpectsNoErrors,
774*333d2b36SAndroid Build Coastguard Worker	}
775*333d2b36SAndroid Build Coastguard Worker
776*333d2b36SAndroid Build Coastguard Worker	for _, preparer := range preparers {
777*333d2b36SAndroid Build Coastguard Worker		preparer.function(fixture)
778*333d2b36SAndroid Build Coastguard Worker	}
779*333d2b36SAndroid Build Coastguard Worker
780*333d2b36SAndroid Build Coastguard Worker	return fixture
781*333d2b36SAndroid Build Coastguard Worker}
782*333d2b36SAndroid Build Coastguard Worker
783*333d2b36SAndroid Build Coastguard Workertype baseFixturePreparer struct {
784*333d2b36SAndroid Build Coastguard Worker	self FixturePreparer
785*333d2b36SAndroid Build Coastguard Worker}
786*333d2b36SAndroid Build Coastguard Worker
787*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) initBaseFixturePreparer(self FixturePreparer) {
788*333d2b36SAndroid Build Coastguard Worker	b.self = self
789*333d2b36SAndroid Build Coastguard Worker}
790*333d2b36SAndroid Build Coastguard Worker
791*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) Fixture(t *testing.T) Fixture {
792*333d2b36SAndroid Build Coastguard Worker	return createFixture(t, t.TempDir(), b.self.list())
793*333d2b36SAndroid Build Coastguard Worker}
794*333d2b36SAndroid Build Coastguard Worker
795*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
796*333d2b36SAndroid Build Coastguard Worker	return GroupFixturePreparers(b.self, newSimpleFixturePreparer(func(fixture *fixture) {
797*333d2b36SAndroid Build Coastguard Worker		fixture.errorHandler = errorHandler
798*333d2b36SAndroid Build Coastguard Worker	}))
799*333d2b36SAndroid Build Coastguard Worker}
800*333d2b36SAndroid Build Coastguard Worker
801*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) RunTest(t *testing.T) *TestResult {
802*333d2b36SAndroid Build Coastguard Worker	t.Helper()
803*333d2b36SAndroid Build Coastguard Worker	return b.RunTestWithCustomResult(t).testResult()
804*333d2b36SAndroid Build Coastguard Worker}
805*333d2b36SAndroid Build Coastguard Worker
806*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) RunTestWithCustomResult(t *testing.T) CustomTestResult {
807*333d2b36SAndroid Build Coastguard Worker	t.Helper()
808*333d2b36SAndroid Build Coastguard Worker	fixture := b.self.Fixture(t)
809*333d2b36SAndroid Build Coastguard Worker	return fixture.RunTest()
810*333d2b36SAndroid Build Coastguard Worker}
811*333d2b36SAndroid Build Coastguard Worker
812*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
813*333d2b36SAndroid Build Coastguard Worker	t.Helper()
814*333d2b36SAndroid Build Coastguard Worker	return GroupFixturePreparers(b.self, FixtureWithRootAndroidBp(bp)).RunTest(t)
815*333d2b36SAndroid Build Coastguard Worker}
816*333d2b36SAndroid Build Coastguard Worker
817*333d2b36SAndroid Build Coastguard Workerfunc (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
818*333d2b36SAndroid Build Coastguard Worker	t.Helper()
819*333d2b36SAndroid Build Coastguard Worker	// Create the fixture as normal.
820*333d2b36SAndroid Build Coastguard Worker	fixture := b.self.Fixture(t).(*fixture)
821*333d2b36SAndroid Build Coastguard Worker
822*333d2b36SAndroid Build Coastguard Worker	// Discard the mock filesystem as otherwise that will override the one in the config.
823*333d2b36SAndroid Build Coastguard Worker	fixture.mockFS = nil
824*333d2b36SAndroid Build Coastguard Worker
825*333d2b36SAndroid Build Coastguard Worker	// Replace the config with the supplied one in the fixture.
826*333d2b36SAndroid Build Coastguard Worker	fixture.config = config
827*333d2b36SAndroid Build Coastguard Worker
828*333d2b36SAndroid Build Coastguard Worker	// Ditto with config derived information in the TestContext.
829*333d2b36SAndroid Build Coastguard Worker	ctx := fixture.ctx
830*333d2b36SAndroid Build Coastguard Worker	ctx.config = config
831*333d2b36SAndroid Build Coastguard Worker	ctx.SetFs(ctx.config.fs)
832*333d2b36SAndroid Build Coastguard Worker	if ctx.config.mockBpList != "" {
833*333d2b36SAndroid Build Coastguard Worker		ctx.SetModuleListFile(ctx.config.mockBpList)
834*333d2b36SAndroid Build Coastguard Worker	}
835*333d2b36SAndroid Build Coastguard Worker
836*333d2b36SAndroid Build Coastguard Worker	return fixture.RunTest().testResult()
837*333d2b36SAndroid Build Coastguard Worker}
838*333d2b36SAndroid Build Coastguard Worker
839*333d2b36SAndroid Build Coastguard Workertype fixture struct {
840*333d2b36SAndroid Build Coastguard Worker	// The preparers used to create this fixture.
841*333d2b36SAndroid Build Coastguard Worker	preparers []*simpleFixturePreparer
842*333d2b36SAndroid Build Coastguard Worker
843*333d2b36SAndroid Build Coastguard Worker	// The test runner used in this fixture, defaults to defaultTestRunner if not set.
844*333d2b36SAndroid Build Coastguard Worker	testRunner FixtureTestRunner
845*333d2b36SAndroid Build Coastguard Worker
846*333d2b36SAndroid Build Coastguard Worker	// The gotest state of the go test within which this was created.
847*333d2b36SAndroid Build Coastguard Worker	t *testing.T
848*333d2b36SAndroid Build Coastguard Worker
849*333d2b36SAndroid Build Coastguard Worker	// The configuration prepared for this fixture.
850*333d2b36SAndroid Build Coastguard Worker	config Config
851*333d2b36SAndroid Build Coastguard Worker
852*333d2b36SAndroid Build Coastguard Worker	// The test context prepared for this fixture.
853*333d2b36SAndroid Build Coastguard Worker	ctx *TestContext
854*333d2b36SAndroid Build Coastguard Worker
855*333d2b36SAndroid Build Coastguard Worker	// The mock filesystem prepared for this fixture.
856*333d2b36SAndroid Build Coastguard Worker	mockFS MockFS
857*333d2b36SAndroid Build Coastguard Worker
858*333d2b36SAndroid Build Coastguard Worker	// The error handler used to check the errors, if any, that are reported.
859*333d2b36SAndroid Build Coastguard Worker	errorHandler FixtureErrorHandler
860*333d2b36SAndroid Build Coastguard Worker
861*333d2b36SAndroid Build Coastguard Worker	// Debug mode status
862*333d2b36SAndroid Build Coastguard Worker	debug bool
863*333d2b36SAndroid Build Coastguard Worker}
864*333d2b36SAndroid Build Coastguard Worker
865*333d2b36SAndroid Build Coastguard Workerfunc (f *fixture) Config() Config {
866*333d2b36SAndroid Build Coastguard Worker	return f.config
867*333d2b36SAndroid Build Coastguard Worker}
868*333d2b36SAndroid Build Coastguard Worker
869*333d2b36SAndroid Build Coastguard Workerfunc (f *fixture) Context() *TestContext {
870*333d2b36SAndroid Build Coastguard Worker	return f.ctx
871*333d2b36SAndroid Build Coastguard Worker}
872*333d2b36SAndroid Build Coastguard Worker
873*333d2b36SAndroid Build Coastguard Workerfunc (f *fixture) MockFS() MockFS {
874*333d2b36SAndroid Build Coastguard Worker	return f.mockFS
875*333d2b36SAndroid Build Coastguard Worker}
876*333d2b36SAndroid Build Coastguard Worker
877*333d2b36SAndroid Build Coastguard Workerfunc (f *fixture) RunTest() CustomTestResult {
878*333d2b36SAndroid Build Coastguard Worker	f.t.Helper()
879*333d2b36SAndroid Build Coastguard Worker
880*333d2b36SAndroid Build Coastguard Worker	// If in debug mode output the state of the fixture before running the test.
881*333d2b36SAndroid Build Coastguard Worker	if f.debug {
882*333d2b36SAndroid Build Coastguard Worker		f.outputDebugState()
883*333d2b36SAndroid Build Coastguard Worker	}
884*333d2b36SAndroid Build Coastguard Worker
885*333d2b36SAndroid Build Coastguard Worker	ctx := f.ctx
886*333d2b36SAndroid Build Coastguard Worker
887*333d2b36SAndroid Build Coastguard Worker	// Do not use the fixture's mockFS to initialize the config's mock file system if it has been
888*333d2b36SAndroid Build Coastguard Worker	// cleared by RunTestWithConfig.
889*333d2b36SAndroid Build Coastguard Worker	if f.mockFS != nil {
890*333d2b36SAndroid Build Coastguard Worker		// The TestConfig() method assumes that the mock filesystem is available when creating so
891*333d2b36SAndroid Build Coastguard Worker		// creates the mock file system immediately. Similarly, the NewTestContext(Config) method
892*333d2b36SAndroid Build Coastguard Worker		// assumes that the supplied Config's FileSystem has been properly initialized before it is
893*333d2b36SAndroid Build Coastguard Worker		// called and so it takes its own reference to the filesystem. However, fixtures create the
894*333d2b36SAndroid Build Coastguard Worker		// Config and TestContext early so they can be modified by preparers at which time the mockFS
895*333d2b36SAndroid Build Coastguard Worker		// has not been populated (because it too is modified by preparers). So, this reinitializes the
896*333d2b36SAndroid Build Coastguard Worker		// Config and TestContext's FileSystem using the now populated mockFS.
897*333d2b36SAndroid Build Coastguard Worker		f.config.mockFileSystem("", f.mockFS)
898*333d2b36SAndroid Build Coastguard Worker
899*333d2b36SAndroid Build Coastguard Worker		ctx.SetFs(ctx.config.fs)
900*333d2b36SAndroid Build Coastguard Worker		if ctx.config.mockBpList != "" {
901*333d2b36SAndroid Build Coastguard Worker			ctx.SetModuleListFile(ctx.config.mockBpList)
902*333d2b36SAndroid Build Coastguard Worker		}
903*333d2b36SAndroid Build Coastguard Worker	}
904*333d2b36SAndroid Build Coastguard Worker
905*333d2b36SAndroid Build Coastguard Worker	// Create and set the Context's NameInterface. It needs to be created here as it depends on the
906*333d2b36SAndroid Build Coastguard Worker	// configuration that has been prepared for this fixture.
907*333d2b36SAndroid Build Coastguard Worker	resolver := NewNameResolver(ctx.config)
908*333d2b36SAndroid Build Coastguard Worker
909*333d2b36SAndroid Build Coastguard Worker	// Set the NameInterface in the main Context.
910*333d2b36SAndroid Build Coastguard Worker	ctx.SetNameInterface(resolver)
911*333d2b36SAndroid Build Coastguard Worker
912*333d2b36SAndroid Build Coastguard Worker	// Set the NameResolver in the TestContext.
913*333d2b36SAndroid Build Coastguard Worker	ctx.NameResolver = resolver
914*333d2b36SAndroid Build Coastguard Worker
915*333d2b36SAndroid Build Coastguard Worker	// If test runner has not been set then use the default runner.
916*333d2b36SAndroid Build Coastguard Worker	if f.testRunner == nil {
917*333d2b36SAndroid Build Coastguard Worker		f.testRunner = defaultTestRunner
918*333d2b36SAndroid Build Coastguard Worker	}
919*333d2b36SAndroid Build Coastguard Worker
920*333d2b36SAndroid Build Coastguard Worker	// Create the result to collate result information.
921*333d2b36SAndroid Build Coastguard Worker	result := &TestResult{
922*333d2b36SAndroid Build Coastguard Worker		testContext: testContext{ctx},
923*333d2b36SAndroid Build Coastguard Worker		fixture:     f,
924*333d2b36SAndroid Build Coastguard Worker		Config:      f.config,
925*333d2b36SAndroid Build Coastguard Worker	}
926*333d2b36SAndroid Build Coastguard Worker
927*333d2b36SAndroid Build Coastguard Worker	// Do any last minute preparation before parsing the blueprint files.
928*333d2b36SAndroid Build Coastguard Worker	customResult := f.testRunner.FinalPreparer(result)
929*333d2b36SAndroid Build Coastguard Worker
930*333d2b36SAndroid Build Coastguard Worker	// Parse the blueprint files adding the information to the result.
931*333d2b36SAndroid Build Coastguard Worker	extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
932*333d2b36SAndroid Build Coastguard Worker	result.NinjaDeps = append(result.NinjaDeps, extraNinjaDeps...)
933*333d2b36SAndroid Build Coastguard Worker	result.Errs = append(result.Errs, errs...)
934*333d2b36SAndroid Build Coastguard Worker
935*333d2b36SAndroid Build Coastguard Worker	if len(result.Errs) == 0 {
936*333d2b36SAndroid Build Coastguard Worker		// If parsing the blueprint files was successful then perform any additional processing.
937*333d2b36SAndroid Build Coastguard Worker		f.testRunner.PostParseProcessor(customResult)
938*333d2b36SAndroid Build Coastguard Worker	}
939*333d2b36SAndroid Build Coastguard Worker
940*333d2b36SAndroid Build Coastguard Worker	f.errorHandler.CheckErrors(f.t, result)
941*333d2b36SAndroid Build Coastguard Worker
942*333d2b36SAndroid Build Coastguard Worker	return customResult
943*333d2b36SAndroid Build Coastguard Worker}
944*333d2b36SAndroid Build Coastguard Worker
945*333d2b36SAndroid Build Coastguard Worker// standardTestRunner is the implementation of the default test runner
946*333d2b36SAndroid Build Coastguard Workertype standardTestRunner struct{}
947*333d2b36SAndroid Build Coastguard Worker
948*333d2b36SAndroid Build Coastguard Workerfunc (s *standardTestRunner) FinalPreparer(result *TestResult) CustomTestResult {
949*333d2b36SAndroid Build Coastguard Worker	// Register the hard coded mutators and singletons used by the standard Soong build as well as
950*333d2b36SAndroid Build Coastguard Worker	// any additional instances that have been registered with this fixture.
951*333d2b36SAndroid Build Coastguard Worker	result.TestContext.Register()
952*333d2b36SAndroid Build Coastguard Worker	return result
953*333d2b36SAndroid Build Coastguard Worker}
954*333d2b36SAndroid Build Coastguard Worker
955*333d2b36SAndroid Build Coastguard Workerfunc (s *standardTestRunner) PostParseProcessor(customResult CustomTestResult) {
956*333d2b36SAndroid Build Coastguard Worker	result := customResult.(*TestResult)
957*333d2b36SAndroid Build Coastguard Worker	ctx := result.TestContext
958*333d2b36SAndroid Build Coastguard Worker	cfg := result.Config
959*333d2b36SAndroid Build Coastguard Worker	// Prepare the build actions, i.e. run all the mutators, singletons and then invoke the
960*333d2b36SAndroid Build Coastguard Worker	// GenerateAndroidBuildActions methods on all the modules.
961*333d2b36SAndroid Build Coastguard Worker	extraNinjaDeps, errs := ctx.PrepareBuildActions(cfg)
962*333d2b36SAndroid Build Coastguard Worker	result.NinjaDeps = append(result.NinjaDeps, extraNinjaDeps...)
963*333d2b36SAndroid Build Coastguard Worker	result.CollateErrs(errs)
964*333d2b36SAndroid Build Coastguard Worker}
965*333d2b36SAndroid Build Coastguard Worker
966*333d2b36SAndroid Build Coastguard Workervar defaultTestRunner FixtureTestRunner = &standardTestRunner{}
967*333d2b36SAndroid Build Coastguard Worker
968*333d2b36SAndroid Build Coastguard Workerfunc (f *fixture) outputDebugState() {
969*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("Begin Fixture State for %s\n", f.t.Name())
970*333d2b36SAndroid Build Coastguard Worker	if len(f.config.env) == 0 {
971*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  Fixture Env is empty\n")
972*333d2b36SAndroid Build Coastguard Worker	} else {
973*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  Begin Env\n")
974*333d2b36SAndroid Build Coastguard Worker		for k, v := range f.config.env {
975*333d2b36SAndroid Build Coastguard Worker			fmt.Printf("  - %s=%s\n", k, v)
976*333d2b36SAndroid Build Coastguard Worker		}
977*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  End Env\n")
978*333d2b36SAndroid Build Coastguard Worker	}
979*333d2b36SAndroid Build Coastguard Worker	if len(f.mockFS) == 0 {
980*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  Mock FS is empty\n")
981*333d2b36SAndroid Build Coastguard Worker	} else {
982*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  Begin Mock FS Contents\n")
983*333d2b36SAndroid Build Coastguard Worker		for p, c := range f.mockFS {
984*333d2b36SAndroid Build Coastguard Worker			if c == nil {
985*333d2b36SAndroid Build Coastguard Worker				fmt.Printf("\n  - %s: nil\n", p)
986*333d2b36SAndroid Build Coastguard Worker			} else {
987*333d2b36SAndroid Build Coastguard Worker				contents := string(c)
988*333d2b36SAndroid Build Coastguard Worker				separator := "    ========================================================================"
989*333d2b36SAndroid Build Coastguard Worker				fmt.Printf("  - %s\n%s\n", p, separator)
990*333d2b36SAndroid Build Coastguard Worker				for i, line := range strings.Split(contents, "\n") {
991*333d2b36SAndroid Build Coastguard Worker					fmt.Printf("      %6d:    %s\n", i+1, line)
992*333d2b36SAndroid Build Coastguard Worker				}
993*333d2b36SAndroid Build Coastguard Worker				fmt.Printf("%s\n", separator)
994*333d2b36SAndroid Build Coastguard Worker			}
995*333d2b36SAndroid Build Coastguard Worker		}
996*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("  End Mock FS Contents\n")
997*333d2b36SAndroid Build Coastguard Worker	}
998*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("End Fixture State for %s\n", f.t.Name())
999*333d2b36SAndroid Build Coastguard Worker}
1000*333d2b36SAndroid Build Coastguard Worker
1001*333d2b36SAndroid Build Coastguard Worker// NormalizePathForTesting removes the test invocation specific build directory from the supplied
1002*333d2b36SAndroid Build Coastguard Worker// path.
1003*333d2b36SAndroid Build Coastguard Worker//
1004*333d2b36SAndroid Build Coastguard Worker// If the path is within the build directory (e.g. an OutputPath) then this returns the relative
1005*333d2b36SAndroid Build Coastguard Worker// path to avoid tests having to deal with the dynamically generated build directory.
1006*333d2b36SAndroid Build Coastguard Worker//
1007*333d2b36SAndroid Build Coastguard Worker// Otherwise, this returns the supplied path as it is almost certainly a source path that is
1008*333d2b36SAndroid Build Coastguard Worker// relative to the root of the source tree.
1009*333d2b36SAndroid Build Coastguard Worker//
1010*333d2b36SAndroid Build Coastguard Worker// Even though some information is removed from some paths and not others it should be possible to
1011*333d2b36SAndroid Build Coastguard Worker// differentiate between them by the paths themselves, e.g. output paths will likely include
1012*333d2b36SAndroid Build Coastguard Worker// ".intermediates" but source paths won't.
1013*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) NormalizePathForTesting(path Path) string {
1014*333d2b36SAndroid Build Coastguard Worker	pathContext := PathContextForTesting(r.Config)
1015*333d2b36SAndroid Build Coastguard Worker	pathAsString := path.String()
1016*333d2b36SAndroid Build Coastguard Worker	if rel, isRel := MaybeRel(pathContext, r.Config.SoongOutDir(), pathAsString); isRel {
1017*333d2b36SAndroid Build Coastguard Worker		return rel
1018*333d2b36SAndroid Build Coastguard Worker	}
1019*333d2b36SAndroid Build Coastguard Worker	return pathAsString
1020*333d2b36SAndroid Build Coastguard Worker}
1021*333d2b36SAndroid Build Coastguard Worker
1022*333d2b36SAndroid Build Coastguard Worker// NormalizePathsForTesting normalizes each path in the supplied list and returns their normalized
1023*333d2b36SAndroid Build Coastguard Worker// forms.
1024*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) NormalizePathsForTesting(paths Paths) []string {
1025*333d2b36SAndroid Build Coastguard Worker	var result []string
1026*333d2b36SAndroid Build Coastguard Worker	for _, path := range paths {
1027*333d2b36SAndroid Build Coastguard Worker		result = append(result, r.NormalizePathForTesting(path))
1028*333d2b36SAndroid Build Coastguard Worker	}
1029*333d2b36SAndroid Build Coastguard Worker	return result
1030*333d2b36SAndroid Build Coastguard Worker}
1031*333d2b36SAndroid Build Coastguard Worker
1032*333d2b36SAndroid Build Coastguard Worker// Preparer will return a FixturePreparer encapsulating all the preparers used to create the fixture
1033*333d2b36SAndroid Build Coastguard Worker// that produced this result.
1034*333d2b36SAndroid Build Coastguard Worker//
1035*333d2b36SAndroid Build Coastguard Worker// e.g. assuming that this result was created by running:
1036*333d2b36SAndroid Build Coastguard Worker//
1037*333d2b36SAndroid Build Coastguard Worker//	GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t)
1038*333d2b36SAndroid Build Coastguard Worker//
1039*333d2b36SAndroid Build Coastguard Worker// Then this method will be equivalent to running:
1040*333d2b36SAndroid Build Coastguard Worker//
1041*333d2b36SAndroid Build Coastguard Worker//	GroupFixturePreparers(preparer1, preparer2, preparer3)
1042*333d2b36SAndroid Build Coastguard Worker//
1043*333d2b36SAndroid Build Coastguard Worker// This is intended for use by tests whose output is Android.bp files to verify that those files
1044*333d2b36SAndroid Build Coastguard Worker// are valid, e.g. tests of the snapshots produced by the sdk module type.
1045*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) Preparer() FixturePreparer {
1046*333d2b36SAndroid Build Coastguard Worker	return newFixturePreparer(r.fixture.preparers)
1047*333d2b36SAndroid Build Coastguard Worker}
1048*333d2b36SAndroid Build Coastguard Worker
1049*333d2b36SAndroid Build Coastguard Worker// Module returns the module with the specific name and of the specified variant.
1050*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) Module(name string, variant string) Module {
1051*333d2b36SAndroid Build Coastguard Worker	return r.ModuleForTests(name, variant).Module()
1052*333d2b36SAndroid Build Coastguard Worker}
1053*333d2b36SAndroid Build Coastguard Worker
1054*333d2b36SAndroid Build Coastguard Worker// CollateErrs adds additional errors to the result and returns true if there is more than one
1055*333d2b36SAndroid Build Coastguard Worker// error in the result.
1056*333d2b36SAndroid Build Coastguard Workerfunc (r *TestResult) CollateErrs(errs []error) bool {
1057*333d2b36SAndroid Build Coastguard Worker	r.Errs = append(r.Errs, errs...)
1058*333d2b36SAndroid Build Coastguard Worker	return len(r.Errs) > 0
1059*333d2b36SAndroid Build Coastguard Worker}
1060