blob: 5ad47e8c9f3fd02401efa58ccf7518cd7207a37a [file] [log] [blame]
Paul Duffin35816122021-02-24 01:49:52 +00001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
Paul Duffinbbccfcf2021-03-03 00:44:00 +000018 "fmt"
Colin Cross5dc62c92023-02-15 12:20:19 -080019 "runtime"
Paul Duffin80f4cea2021-03-16 14:08:00 +000020 "strings"
Paul Duffin35816122021-02-24 01:49:52 +000021 "testing"
22)
23
24// Provides support for creating test fixtures on which tests can be run. Reduces duplication
25// of test setup by allow tests to easily reuse setup code.
26//
27// Fixture
28// =======
29// These determine the environment within which a test can be run. Fixtures are mutable and are
Paul Duffin4814bb82021-03-29 01:55:10 +010030// created and mutated by FixturePreparer instances. They are created by first creating a base
31// Fixture (which is essentially empty) and then applying FixturePreparer instances to it to modify
32// the environment.
Paul Duffin35816122021-02-24 01:49:52 +000033//
34// FixturePreparer
35// ===============
36// These are responsible for modifying a Fixture in preparation for it to run a test. Preparers are
37// intended to be immutable and able to prepare multiple Fixture objects simultaneously without
38// them sharing any data.
39//
Paul Duffinff2aa692021-03-19 18:20:59 +000040// They provide the basic capabilities for running tests too.
41//
42// FixturePreparers are only ever applied once per test fixture. Prior to application the list of
Paul Duffin35816122021-02-24 01:49:52 +000043// FixturePreparers are flattened and deduped while preserving the order they first appear in the
44// list. This makes it easy to reuse, group and combine FixturePreparers together.
45//
46// Each small self contained piece of test setup should be their own FixturePreparer. e.g.
47// * A group of related modules.
48// * A group of related mutators.
49// * A combination of both.
50// * Configuration.
51//
52// They should not overlap, e.g. the same module type should not be registered by different
53// FixturePreparers as using them both would cause a build error. In that case the preparer should
54// be split into separate parts and combined together using FixturePreparers(...).
55//
56// e.g. attempting to use AllPreparers in preparing a Fixture would break as it would attempt to
57// register module bar twice:
58// var Preparer1 = FixtureRegisterWithContext(RegisterModuleFooAndBar)
59// var Preparer2 = FixtureRegisterWithContext(RegisterModuleBarAndBaz)
Paul Duffina560d5a2021-02-28 01:38:51 +000060// var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
Paul Duffin35816122021-02-24 01:49:52 +000061//
62// However, when restructured like this it would work fine:
63// var PreparerFoo = FixtureRegisterWithContext(RegisterModuleFoo)
64// var PreparerBar = FixtureRegisterWithContext(RegisterModuleBar)
65// var PreparerBaz = FixtureRegisterWithContext(RegisterModuleBaz)
Paul Duffina560d5a2021-02-28 01:38:51 +000066// var Preparer1 = GroupFixturePreparers(RegisterModuleFoo, RegisterModuleBar)
67// var Preparer2 = GroupFixturePreparers(RegisterModuleBar, RegisterModuleBaz)
68// var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
Paul Duffin35816122021-02-24 01:49:52 +000069//
70// As after deduping and flattening AllPreparers would result in the following preparers being
71// applied:
72// 1. PreparerFoo
73// 2. PreparerBar
74// 3. PreparerBaz
75//
76// Preparers can be used for both integration and unit tests.
77//
78// Integration tests typically use all the module types, mutators and singletons that are available
79// for that package to try and replicate the behavior of the runtime build as closely as possible.
80// However, that realism comes at a cost of increased fragility (as they can be broken by changes in
81// many different parts of the build) and also increased runtime, especially if they use lots of
82// singletons and mutators.
83//
84// Unit tests on the other hand try and minimize the amount of code being tested which makes them
85// less susceptible to changes elsewhere in the build and quick to run but at a cost of potentially
86// not testing realistic scenarios.
87//
88// Supporting unit tests effectively require that preparers are available at the lowest granularity
89// possible. Supporting integration tests effectively require that the preparers are organized into
90// groups that provide all the functionality available.
91//
92// At least in terms of tests that check the behavior of build components via processing
93// `Android.bp` there is no clear separation between a unit test and an integration test. Instead
94// they vary from one end that tests a single module (e.g. filegroup) to the other end that tests a
95// whole system of modules, mutators and singletons (e.g. apex + hiddenapi).
96//
97// TestResult
98// ==========
99// These are created by running tests in a Fixture and provide access to the Config and TestContext
100// in which the tests were run.
101//
102// Example
103// =======
104//
105// An exported preparer for use by other packages that need to use java modules.
106//
107// package java
Paul Duffina560d5a2021-02-28 01:38:51 +0000108// var PrepareForIntegrationTestWithJava = GroupFixturePreparers(
Paul Duffin35816122021-02-24 01:49:52 +0000109// android.PrepareForIntegrationTestWithAndroid,
110// FixtureRegisterWithContext(RegisterAGroupOfRelatedModulesMutatorsAndSingletons),
111// FixtureRegisterWithContext(RegisterAnotherGroupOfRelatedModulesMutatorsAndSingletons),
112// ...
113// )
114//
115// Some files to use in tests in the java package.
116//
117// var javaMockFS = android.MockFS{
Paul Duffinff2aa692021-03-19 18:20:59 +0000118// "api/current.txt": nil,
119// "api/removed.txt": nil,
Paul Duffin35816122021-02-24 01:49:52 +0000120// ...
121// }
122//
Paul Duffinff2aa692021-03-19 18:20:59 +0000123// A package private preparer for use for testing java within the java package.
Paul Duffin35816122021-02-24 01:49:52 +0000124//
Paul Duffinff2aa692021-03-19 18:20:59 +0000125// var prepareForJavaTest = android.GroupFixturePreparers(
126// PrepareForIntegrationTestWithJava,
127// FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
128// ctx.RegisterModuleType("test_module", testModule)
129// }),
130// javaMockFS.AddToFixture(),
131// ...
132// }
133//
134// func TestJavaStuff(t *testing.T) {
Paul Duffin3cb2c062021-03-22 19:24:26 +0000135// result := android.GroupFixturePreparers(
Paul Duffinff2aa692021-03-19 18:20:59 +0000136// prepareForJavaTest,
137// android.FixtureWithRootAndroidBp(`java_library {....}`),
138// android.MockFS{...}.AddToFixture(),
139// ).RunTest(t)
140// ... test result ...
141// }
142//
143// package cc
144// var PrepareForTestWithCC = android.GroupFixturePreparers(
145// android.PrepareForArchMutator,
146// android.prepareForPrebuilts,
147// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
148// ...
149// )
150//
151// package apex
152//
153// var PrepareForApex = GroupFixturePreparers(
154// ...
155// )
156//
157// Use modules and mutators from java, cc and apex. Any duplicate preparers (like
158// android.PrepareForArchMutator) will be automatically deduped.
159//
160// var prepareForApexTest = android.GroupFixturePreparers(
161// PrepareForJava,
162// PrepareForCC,
163// PrepareForApex,
164// )
165//
Paul Duffin35816122021-02-24 01:49:52 +0000166
167// A set of mock files to add to the mock file system.
168type MockFS map[string][]byte
169
Paul Duffin6e9a4002021-03-11 19:01:26 +0000170// Merge adds the extra entries from the supplied map to this one.
171//
172// Fails if the supplied map files with the same paths are present in both of them.
Paul Duffin35816122021-02-24 01:49:52 +0000173func (fs MockFS) Merge(extra map[string][]byte) {
174 for p, c := range extra {
Paul Duffin80f4cea2021-03-16 14:08:00 +0000175 validateFixtureMockFSPath(p)
Paul Duffin6e9a4002021-03-11 19:01:26 +0000176 if _, ok := fs[p]; ok {
177 panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists", p))
178 }
Paul Duffin35816122021-02-24 01:49:52 +0000179 fs[p] = c
180 }
181}
182
Paul Duffin80f4cea2021-03-16 14:08:00 +0000183// Ensure that tests cannot add paths into the mock file system which would not be allowed in the
184// runtime, e.g. absolute paths, paths relative to the 'out/' directory.
185func validateFixtureMockFSPath(path string) {
186 // This uses validateSafePath rather than validatePath because the latter prevents adding files
187 // that include a $ but there are tests that allow files with a $ to be used, albeit only by
188 // globbing.
189 validatedPath, err := validateSafePath(path)
190 if err != nil {
191 panic(err)
192 }
193
194 // Make sure that the path is canonical.
195 if validatedPath != path {
196 panic(fmt.Errorf("path %q is not a canonical path, use %q instead", path, validatedPath))
197 }
198
199 if path == "out" || strings.HasPrefix(path, "out/") {
200 panic(fmt.Errorf("cannot add output path %q to the mock file system", path))
201 }
202}
203
Paul Duffin35816122021-02-24 01:49:52 +0000204func (fs MockFS) AddToFixture() FixturePreparer {
205 return FixtureMergeMockFs(fs)
206}
207
Paul Duffinae542a52021-03-09 03:15:28 +0000208// FixtureCustomPreparer allows for the modification of any aspect of the fixture.
209//
210// This should only be used if one of the other more specific preparers are not suitable.
211func FixtureCustomPreparer(mutator func(fixture Fixture)) FixturePreparer {
212 return newSimpleFixturePreparer(func(f *fixture) {
213 mutator(f)
214 })
215}
216
Paul Duffin4c0765a2022-10-29 17:48:00 +0100217// FixtureTestRunner determines the type of test to run.
218//
219// If no custom FixtureTestRunner is provided (using the FixtureSetTestRunner) then the default test
220// runner will run a standard Soong test that corresponds to what happens when Soong is run on the
221// command line.
222type FixtureTestRunner interface {
223 // FinalPreparer is a function that is run immediately before parsing the blueprint files. It is
224 // intended to perform the initialization needed by PostParseProcessor.
225 //
226 // It returns a CustomTestResult that is passed into PostParseProcessor and returned from
227 // FixturePreparer.RunTestWithCustomResult. If it needs to return some custom data then it must
228 // provide its own implementation of CustomTestResult and return an instance of that. Otherwise,
229 // it can just return the supplied *TestResult.
230 FinalPreparer(result *TestResult) CustomTestResult
231
232 // PostParseProcessor is called after successfully parsing the blueprint files and can do further
233 // work on the result of parsing the files.
234 //
235 // Successfully parsing simply means that no errors were encountered when parsing the blueprint
236 // files.
237 //
238 // This must collate any information useful for testing, e.g. errs, ninja deps and custom data in
239 // the supplied result.
240 PostParseProcessor(result CustomTestResult)
241}
242
243// FixtureSetTestRunner sets the FixtureTestRunner in the fixture.
244//
245// It is an error if more than one of these is applied to a single fixture. If none of these are
246// applied then the fixture will use the defaultTestRunner which will run the test as if it was
247// being run in `m <target>`.
248func FixtureSetTestRunner(testRunner FixtureTestRunner) FixturePreparer {
249 return newSimpleFixturePreparer(func(fixture *fixture) {
250 if fixture.testRunner != nil {
251 panic("fixture test runner has already been set")
252 }
253 fixture.testRunner = testRunner
254 })
255}
256
Paul Duffin35816122021-02-24 01:49:52 +0000257// Modify the config
258func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
259 return newSimpleFixturePreparer(func(f *fixture) {
260 mutator(f.config)
261 })
262}
263
264// Modify the config and context
265func FixtureModifyConfigAndContext(mutator func(config Config, ctx *TestContext)) FixturePreparer {
266 return newSimpleFixturePreparer(func(f *fixture) {
267 mutator(f.config, f.ctx)
268 })
269}
270
271// Modify the context
272func FixtureModifyContext(mutator func(ctx *TestContext)) FixturePreparer {
273 return newSimpleFixturePreparer(func(f *fixture) {
274 mutator(f.ctx)
275 })
276}
277
Chris Parsons5011e612023-09-13 23:33:20 +0000278// Sync the mock filesystem with the current config, then modify the context,
279// This allows context modification that requires filesystem access.
280func FixtureModifyContextWithMockFs(mutator func(ctx *TestContext)) FixturePreparer {
281 return newSimpleFixturePreparer(func(f *fixture) {
282 f.config.mockFileSystem("", f.mockFS)
283 mutator(f.ctx)
284 })
285}
286
Paul Duffin35816122021-02-24 01:49:52 +0000287func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
288 return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
289}
290
291// Modify the mock filesystem
292func FixtureModifyMockFS(mutator func(fs MockFS)) FixturePreparer {
293 return newSimpleFixturePreparer(func(f *fixture) {
294 mutator(f.mockFS)
Paul Duffin80f4cea2021-03-16 14:08:00 +0000295
296 // Make sure that invalid paths were not added to the mock filesystem.
297 for p, _ := range f.mockFS {
298 validateFixtureMockFSPath(p)
299 }
Paul Duffin35816122021-02-24 01:49:52 +0000300 })
301}
302
303// Merge the supplied file system into the mock filesystem.
304//
305// Paths that already exist in the mock file system are overridden.
306func FixtureMergeMockFs(mockFS MockFS) FixturePreparer {
307 return FixtureModifyMockFS(func(fs MockFS) {
308 fs.Merge(mockFS)
309 })
310}
311
312// Add a file to the mock filesystem
Paul Duffin6e9a4002021-03-11 19:01:26 +0000313//
314// Fail if the filesystem already contains a file with that path, use FixtureOverrideFile instead.
Paul Duffin35816122021-02-24 01:49:52 +0000315func FixtureAddFile(path string, contents []byte) FixturePreparer {
316 return FixtureModifyMockFS(func(fs MockFS) {
Paul Duffin80f4cea2021-03-16 14:08:00 +0000317 validateFixtureMockFSPath(path)
Paul Duffin6e9a4002021-03-11 19:01:26 +0000318 if _, ok := fs[path]; ok {
319 panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists, use FixtureOverride*File instead", path))
320 }
Paul Duffin35816122021-02-24 01:49:52 +0000321 fs[path] = contents
322 })
323}
324
325// Add a text file to the mock filesystem
Paul Duffin6e9a4002021-03-11 19:01:26 +0000326//
327// Fail if the filesystem already contains a file with that path.
Paul Duffin35816122021-02-24 01:49:52 +0000328func FixtureAddTextFile(path string, contents string) FixturePreparer {
329 return FixtureAddFile(path, []byte(contents))
330}
331
Paul Duffin6e9a4002021-03-11 19:01:26 +0000332// Override a file in the mock filesystem
333//
334// If the file does not exist this behaves as FixtureAddFile.
335func FixtureOverrideFile(path string, contents []byte) FixturePreparer {
336 return FixtureModifyMockFS(func(fs MockFS) {
337 fs[path] = contents
338 })
339}
340
341// Override a text file in the mock filesystem
342//
343// If the file does not exist this behaves as FixtureAddTextFile.
344func FixtureOverrideTextFile(path string, contents string) FixturePreparer {
345 return FixtureOverrideFile(path, []byte(contents))
346}
347
Paul Duffin35816122021-02-24 01:49:52 +0000348// Add the root Android.bp file with the supplied contents.
349func FixtureWithRootAndroidBp(contents string) FixturePreparer {
350 return FixtureAddTextFile("Android.bp", contents)
351}
352
Paul Duffinbbccfcf2021-03-03 00:44:00 +0000353// Merge some environment variables into the fixture.
354func FixtureMergeEnv(env map[string]string) FixturePreparer {
355 return FixtureModifyConfig(func(config Config) {
356 for k, v := range env {
357 if k == "PATH" {
358 panic("Cannot set PATH environment variable")
359 }
360 config.env[k] = v
361 }
362 })
363}
364
365// Modify the env.
366//
367// Will panic if the mutator changes the PATH environment variable.
368func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
369 return FixtureModifyConfig(func(config Config) {
370 oldPath := config.env["PATH"]
371 mutator(config.env)
372 newPath := config.env["PATH"]
373 if newPath != oldPath {
374 panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
375 }
376 })
377}
378
Paul Duffin2e0323d2021-03-04 15:11:01 +0000379// Allow access to the product variables when preparing the fixture.
380type FixtureProductVariables struct {
Cole Faustf8231dd2023-04-21 17:37:11 -0700381 *ProductVariables
Paul Duffin2e0323d2021-03-04 15:11:01 +0000382}
383
384// Modify product variables.
385func FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
386 return FixtureModifyConfig(func(config Config) {
387 productVariables := FixtureProductVariables{&config.productVariables}
388 mutator(productVariables)
389 })
390}
391
Colin Cross5dc62c92023-02-15 12:20:19 -0800392var PrepareForSkipTestOnMac = newSimpleFixturePreparer(func(fixture *fixture) {
393 if runtime.GOOS != "linux" {
394 fixture.t.Skip("Test is only supported on linux.")
395 }
396})
397
Paul Duffin64715ba2021-04-20 22:42:17 +0100398// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
399// state before running the test.
400//
401// This must only be added temporarily to a test for local debugging and must be removed from the
402// test before submitting.
403var PrepareForDebug_DO_NOT_SUBMIT = newSimpleFixturePreparer(func(fixture *fixture) {
404 fixture.debug = true
405})
406
Paul Duffina560d5a2021-02-28 01:38:51 +0000407// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
408// the supplied FixturePreparer instances in order.
409//
410// Before preparing the fixture the list of preparers is flattened by replacing each
411// instance of GroupFixturePreparers with its contents.
412func GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
Paul Duffinff2aa692021-03-19 18:20:59 +0000413 all := dedupAndFlattenPreparers(nil, preparers)
414 return newFixturePreparer(all)
Paul Duffin35816122021-02-24 01:49:52 +0000415}
416
Paul Duffin50deaae2021-03-16 17:46:12 +0000417// NullFixturePreparer is a preparer that does nothing.
418var NullFixturePreparer = GroupFixturePreparers()
419
420// OptionalFixturePreparer will return the supplied preparer if it is non-nil, otherwise it will
421// return the NullFixturePreparer
422func OptionalFixturePreparer(preparer FixturePreparer) FixturePreparer {
423 if preparer == nil {
424 return NullFixturePreparer
425 } else {
426 return preparer
427 }
428}
429
Paul Duffinff2aa692021-03-19 18:20:59 +0000430// FixturePreparer provides the ability to create, modify and then run tests within a fixture.
Paul Duffin35816122021-02-24 01:49:52 +0000431type FixturePreparer interface {
Paul Duffin4ca67522021-03-20 01:25:12 +0000432 // Return the flattened and deduped list of simpleFixturePreparer pointers.
433 list() []*simpleFixturePreparer
Paul Duffinff2aa692021-03-19 18:20:59 +0000434
Paul Duffinff2aa692021-03-19 18:20:59 +0000435 // Create a Fixture.
Paul Duffin34a7fff2021-03-30 22:11:24 +0100436 Fixture(t *testing.T) Fixture
Paul Duffinff2aa692021-03-19 18:20:59 +0000437
438 // ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
439 // to check the errors (may be 0) reported by the test.
440 //
441 // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
442 // errors are reported.
443 ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer
444
445 // Run the test, checking any errors reported and returning a TestResult instance.
446 //
Paul Duffin55e740e2021-03-29 02:06:19 +0100447 // Shorthand for Fixture(t).RunTest()
448 RunTest(t *testing.T) *TestResult
Paul Duffinff2aa692021-03-19 18:20:59 +0000449
Paul Duffin4c0765a2022-10-29 17:48:00 +0100450 // RunTestWithCustomResult runs the test just as RunTest(t) does but instead of returning a
451 // *TestResult it returns the CustomTestResult that was returned by the custom
452 // FixtureTestRunner.PostParseProcessor method that ran the test, or the *TestResult if that
453 // method returned nil.
454 //
455 // This method must be used when needing to access custom data collected by the
456 // FixtureTestRunner.PostParseProcessor method.
457 //
458 // e.g. something like this
459 //
460 // preparers := ...FixtureSetTestRunner(&myTestRunner)...
461 // customResult := preparers.RunTestWithCustomResult(t).(*myCustomTestResult)
462 // doSomething(customResult.data)
463 RunTestWithCustomResult(t *testing.T) CustomTestResult
464
Paul Duffinff2aa692021-03-19 18:20:59 +0000465 // Run the test with the supplied Android.bp file.
466 //
Paul Duffin55e740e2021-03-29 02:06:19 +0100467 // preparer.RunTestWithBp(t, bp) is shorthand for
468 // android.GroupFixturePreparers(preparer, android.FixtureWithRootAndroidBp(bp)).RunTest(t)
Paul Duffinff2aa692021-03-19 18:20:59 +0000469 RunTestWithBp(t *testing.T, bp string) *TestResult
470
471 // RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
472 // the test fixture.
473 //
474 // In order to allow the Config object to be customized separately to the TestContext a lot of
475 // existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
476 // from the test and then have the TestContext created and configured automatically. e.g.
477 // testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
478 //
479 // This method allows those methods to be migrated to use the test fixture pattern without
480 // requiring that every test that uses those methods be migrated at the same time. That allows
481 // those tests to benefit from correctness in the order of registration quickly.
482 //
483 // This method discards the config (along with its mock file system, product variables,
484 // environment, etc.) that may have been set up by FixturePreparers.
485 //
486 // deprecated
487 RunTestWithConfig(t *testing.T, config Config) *TestResult
Paul Duffin35816122021-02-24 01:49:52 +0000488}
489
490// dedupAndFlattenPreparers removes any duplicates and flattens any composite FixturePreparer
491// instances.
492//
493// base - a list of already flattened and deduped preparers that will be applied first before
Colin Crossd079e0b2022-08-16 10:27:33 -0700494//
495// the list of additional preparers. Any duplicates of these in the additional preparers
496// will be ignored.
Paul Duffin35816122021-02-24 01:49:52 +0000497//
498// preparers - a list of additional unflattened, undeduped preparers that will be applied after the
Colin Crossd079e0b2022-08-16 10:27:33 -0700499//
500// base preparers.
Paul Duffin35816122021-02-24 01:49:52 +0000501//
Paul Duffin59251822021-03-15 22:20:12 +0000502// Returns a deduped and flattened list of the preparers starting with the ones in base with any
503// additional ones from the preparers list added afterwards.
Paul Duffin4ca67522021-03-20 01:25:12 +0000504func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers []FixturePreparer) []*simpleFixturePreparer {
Paul Duffin59251822021-03-15 22:20:12 +0000505 if len(preparers) == 0 {
506 return base
507 }
508
509 list := make([]*simpleFixturePreparer, len(base))
Paul Duffin35816122021-02-24 01:49:52 +0000510 visited := make(map[*simpleFixturePreparer]struct{})
511
512 // Mark the already flattened and deduped preparers, if any, as having been seen so that
Paul Duffin59251822021-03-15 22:20:12 +0000513 // duplicates of these in the additional preparers will be discarded. Add them to the output
514 // list.
515 for i, s := range base {
Paul Duffin35816122021-02-24 01:49:52 +0000516 visited[s] = struct{}{}
Paul Duffin59251822021-03-15 22:20:12 +0000517 list[i] = s
Paul Duffin35816122021-02-24 01:49:52 +0000518 }
519
Paul Duffin4ca67522021-03-20 01:25:12 +0000520 for _, p := range preparers {
521 for _, s := range p.list() {
522 if _, seen := visited[s]; !seen {
523 visited[s] = struct{}{}
524 list = append(list, s)
525 }
Paul Duffin35816122021-02-24 01:49:52 +0000526 }
Paul Duffin4ca67522021-03-20 01:25:12 +0000527 }
528
Paul Duffin35816122021-02-24 01:49:52 +0000529 return list
530}
531
532// compositeFixturePreparer is a FixturePreparer created from a list of fixture preparers.
533type compositeFixturePreparer struct {
Paul Duffinff2aa692021-03-19 18:20:59 +0000534 baseFixturePreparer
Paul Duffin4ca67522021-03-20 01:25:12 +0000535 // The flattened and deduped list of simpleFixturePreparer pointers encapsulated within this
536 // composite preparer.
Paul Duffin35816122021-02-24 01:49:52 +0000537 preparers []*simpleFixturePreparer
538}
539
Paul Duffin4ca67522021-03-20 01:25:12 +0000540func (c *compositeFixturePreparer) list() []*simpleFixturePreparer {
541 return c.preparers
Paul Duffin35816122021-02-24 01:49:52 +0000542}
543
Paul Duffinff2aa692021-03-19 18:20:59 +0000544func newFixturePreparer(preparers []*simpleFixturePreparer) FixturePreparer {
545 if len(preparers) == 1 {
546 return preparers[0]
547 }
548 p := &compositeFixturePreparer{
549 preparers: preparers,
550 }
551 p.initBaseFixturePreparer(p)
552 return p
553}
554
Paul Duffin35816122021-02-24 01:49:52 +0000555// simpleFixturePreparer is a FixturePreparer that applies a function to a fixture.
556type simpleFixturePreparer struct {
Paul Duffinff2aa692021-03-19 18:20:59 +0000557 baseFixturePreparer
Paul Duffin35816122021-02-24 01:49:52 +0000558 function func(fixture *fixture)
559}
560
Paul Duffin4ca67522021-03-20 01:25:12 +0000561func (s *simpleFixturePreparer) list() []*simpleFixturePreparer {
562 return []*simpleFixturePreparer{s}
Paul Duffin35816122021-02-24 01:49:52 +0000563}
564
565func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer {
Paul Duffinff2aa692021-03-19 18:20:59 +0000566 p := &simpleFixturePreparer{function: preparer}
567 p.initBaseFixturePreparer(p)
568 return p
Paul Duffin35816122021-02-24 01:49:52 +0000569}
570
Paul Duffincfd33742021-02-27 11:59:02 +0000571// FixtureErrorHandler determines how to respond to errors reported by the code under test.
572//
573// Some possible responses:
Colin Crossd079e0b2022-08-16 10:27:33 -0700574// - Fail the test if any errors are reported, see FixtureExpectsNoErrors.
575// - Fail the test if at least one error that matches a pattern is not reported see
576// FixtureExpectsAtLeastOneErrorMatchingPattern
577// - Fail the test if any unexpected errors are reported.
Paul Duffincfd33742021-02-27 11:59:02 +0000578//
579// Although at the moment all the error handlers are implemented as simply a wrapper around a
580// function this is defined as an interface to allow future enhancements, e.g. provide different
581// ways other than patterns to match an error and to combine handlers together.
582type FixtureErrorHandler interface {
583 // CheckErrors checks the errors reported.
584 //
585 // The supplied result can be used to access the state of the code under test just as the main
586 // body of the test would but if any errors other than ones expected are reported the state may
587 // be indeterminate.
Paul Duffinc81854a2021-03-12 12:22:27 +0000588 CheckErrors(t *testing.T, result *TestResult)
Paul Duffincfd33742021-02-27 11:59:02 +0000589}
590
591type simpleErrorHandler struct {
Paul Duffinc81854a2021-03-12 12:22:27 +0000592 function func(t *testing.T, result *TestResult)
Paul Duffincfd33742021-02-27 11:59:02 +0000593}
594
Paul Duffinc81854a2021-03-12 12:22:27 +0000595func (h simpleErrorHandler) CheckErrors(t *testing.T, result *TestResult) {
596 t.Helper()
597 h.function(t, result)
Paul Duffincfd33742021-02-27 11:59:02 +0000598}
599
600// The default fixture error handler.
601//
602// Will fail the test immediately if any errors are reported.
Paul Duffinea8a3862021-03-04 17:58:33 +0000603//
604// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
605// which the test is being run which means that the RunTest() method will not return.
Paul Duffincfd33742021-02-27 11:59:02 +0000606var FixtureExpectsNoErrors = FixtureCustomErrorHandler(
Paul Duffinc81854a2021-03-12 12:22:27 +0000607 func(t *testing.T, result *TestResult) {
608 t.Helper()
609 FailIfErrored(t, result.Errs)
Paul Duffincfd33742021-02-27 11:59:02 +0000610 },
611)
612
Paul Duffin85034e92021-03-17 00:20:34 +0000613// FixtureIgnoreErrors ignores any errors.
614//
615// If this is used then it is the responsibility of the test to check the TestResult.Errs does not
616// contain any unexpected errors.
617var FixtureIgnoreErrors = FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
618 // Ignore the errors
619})
620
Paul Duffincfd33742021-02-27 11:59:02 +0000621// FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail
622// if at least one error that matches the regular expression is not found.
623//
624// The test will be failed if:
625// * No errors are reported.
626// * One or more errors are reported but none match the pattern.
627//
628// The test will not fail if:
629// * Multiple errors are reported that do not match the pattern as long as one does match.
Paul Duffinea8a3862021-03-04 17:58:33 +0000630//
631// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
632// which the test is being run which means that the RunTest() method will not return.
Paul Duffincfd33742021-02-27 11:59:02 +0000633func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
Paul Duffinc81854a2021-03-12 12:22:27 +0000634 return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
635 t.Helper()
636 if !FailIfNoMatchingErrors(t, pattern, result.Errs) {
637 t.FailNow()
Paul Duffinea8a3862021-03-04 17:58:33 +0000638 }
Paul Duffincfd33742021-02-27 11:59:02 +0000639 })
640}
641
642// FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail
643// if there are any unexpected errors.
644//
645// The test will be failed if:
646// * The number of errors reported does not exactly match the patterns.
647// * One or more of the reported errors do not match a pattern.
648// * No patterns are provided and one or more errors are reported.
649//
650// The test will not fail if:
651// * One or more of the patterns does not match an error.
Paul Duffinea8a3862021-03-04 17:58:33 +0000652//
653// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
654// which the test is being run which means that the RunTest() method will not return.
Paul Duffincfd33742021-02-27 11:59:02 +0000655func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
Paul Duffinc81854a2021-03-12 12:22:27 +0000656 return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
657 t.Helper()
658 CheckErrorsAgainstExpectations(t, result.Errs, patterns)
Paul Duffincfd33742021-02-27 11:59:02 +0000659 })
660}
661
Paul Duffin0fc6d322021-07-06 22:36:33 +0100662// FixtureExpectsOneErrorPattern returns an error handler that will cause the test to fail
663// if there is more than one error or the error does not match the pattern.
664//
665// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
666// which the test is being run which means that the RunTest() method will not return.
667func FixtureExpectsOneErrorPattern(pattern string) FixtureErrorHandler {
668 return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
669 t.Helper()
670 CheckErrorsAgainstExpectations(t, result.Errs, []string{pattern})
671 })
672}
673
Paul Duffincfd33742021-02-27 11:59:02 +0000674// FixtureCustomErrorHandler creates a custom error handler
Paul Duffinc81854a2021-03-12 12:22:27 +0000675func FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler {
Paul Duffincfd33742021-02-27 11:59:02 +0000676 return simpleErrorHandler{
677 function: function,
678 }
679}
680
Paul Duffin35816122021-02-24 01:49:52 +0000681// Fixture defines the test environment.
682type Fixture interface {
Paul Duffinae542a52021-03-09 03:15:28 +0000683 // Config returns the fixture's configuration.
684 Config() Config
685
686 // Context returns the fixture's test context.
687 Context() *TestContext
688
689 // MockFS returns the fixture's mock filesystem.
690 MockFS() MockFS
691
Paul Duffincfd33742021-02-27 11:59:02 +0000692 // Run the test, checking any errors reported and returning a TestResult instance.
Paul Duffin4c0765a2022-10-29 17:48:00 +0100693 RunTest() CustomTestResult
Paul Duffin35816122021-02-24 01:49:52 +0000694}
695
Paul Duffin35816122021-02-24 01:49:52 +0000696// Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
697type testContext struct {
698 *TestContext
699}
700
701// The result of running a test.
702type TestResult struct {
Paul Duffin35816122021-02-24 01:49:52 +0000703 testContext
704
705 fixture *fixture
706 Config Config
Paul Duffin942481b2021-03-04 18:58:11 +0000707
708 // The errors that were reported during the test.
709 Errs []error
Paul Duffin78c36212021-03-16 23:57:12 +0000710
711 // The ninja deps is a list of the ninja files dependencies that were added by the modules and
712 // singletons via the *.AddNinjaFileDeps() methods.
713 NinjaDeps []string
Paul Duffin35816122021-02-24 01:49:52 +0000714}
715
Paul Duffin4c0765a2022-10-29 17:48:00 +0100716func (r *TestResult) testResult() *TestResult { return r }
717
718// CustomTestResult is the interface that FixtureTestRunner implementations who wish to return
719// custom data must implement. It must embed *TestResult and initialize that to the value passed
720// into the method. It is returned from the FixtureTestRunner.FinalPreparer, passed into the
721// FixtureTestRunner.PostParseProcessor and returned from FixturePreparer.RunTestWithCustomResult.
722//
723// e.g. something like this:
724//
725// type myCustomTestResult struct {
726// *android.TestResult
727// data []string
728// }
729//
730// func (r *myTestRunner) FinalPreparer(result *TestResult) CustomTestResult {
731// ... do some final test preparation ...
732// return &myCustomTestResult{TestResult: result)
733// }
734//
735// func (r *myTestRunner) PostParseProcessor(result CustomTestResult) {
736// ...
737// myData := []string {....}
738// ...
739// customResult := result.(*myCustomTestResult)
740// customResult.data = myData
741// }
742type CustomTestResult interface {
743 // testResult returns the embedded *TestResult.
744 testResult() *TestResult
745}
746
747var _ CustomTestResult = (*TestResult)(nil)
748
Sam Delmerico2351eac2022-05-24 17:10:02 +0000749type TestPathContext struct {
750 *TestResult
751}
752
753var _ PathContext = &TestPathContext{}
754
755func (t *TestPathContext) Config() Config {
756 return t.TestResult.Config
757}
758
759func (t *TestPathContext) AddNinjaFileDeps(deps ...string) {
760 panic("unimplemented")
761}
762
Paul Duffin34a7fff2021-03-30 22:11:24 +0100763func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
Paul Duffindff5ff02021-03-15 15:42:40 +0000764 config := TestConfig(buildDir, nil, "", nil)
Paul Duffin3f7bf9f2022-11-08 12:21:15 +0000765 ctx := newTestContextForFixture(config)
Paul Duffin35816122021-02-24 01:49:52 +0000766 fixture := &fixture{
Paul Duffin34a7fff2021-03-30 22:11:24 +0100767 preparers: preparers,
Paul Duffincff464f2021-03-19 18:13:46 +0000768 t: t,
769 config: config,
770 ctx: ctx,
771 mockFS: make(MockFS),
772 // Set the default error handler.
773 errorHandler: FixtureExpectsNoErrors,
Paul Duffin35816122021-02-24 01:49:52 +0000774 }
775
Paul Duffin34a7fff2021-03-30 22:11:24 +0100776 for _, preparer := range preparers {
Paul Duffin35816122021-02-24 01:49:52 +0000777 preparer.function(fixture)
778 }
779
780 return fixture
781}
782
Paul Duffinff2aa692021-03-19 18:20:59 +0000783type baseFixturePreparer struct {
784 self FixturePreparer
785}
786
787func (b *baseFixturePreparer) initBaseFixturePreparer(self FixturePreparer) {
788 b.self = self
789}
790
Paul Duffin34a7fff2021-03-30 22:11:24 +0100791func (b *baseFixturePreparer) Fixture(t *testing.T) Fixture {
792 return createFixture(t, t.TempDir(), b.self.list())
Paul Duffinff2aa692021-03-19 18:20:59 +0000793}
794
795func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
Paul Duffin79abe572021-03-29 02:16:14 +0100796 return GroupFixturePreparers(b.self, newSimpleFixturePreparer(func(fixture *fixture) {
Paul Duffincff464f2021-03-19 18:13:46 +0000797 fixture.errorHandler = errorHandler
798 }))
Paul Duffincfd33742021-02-27 11:59:02 +0000799}
800
Paul Duffin55e740e2021-03-29 02:06:19 +0100801func (b *baseFixturePreparer) RunTest(t *testing.T) *TestResult {
Paul Duffin35816122021-02-24 01:49:52 +0000802 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +0100803 return b.RunTestWithCustomResult(t).testResult()
804}
805
806func (b *baseFixturePreparer) RunTestWithCustomResult(t *testing.T) CustomTestResult {
807 t.Helper()
Paul Duffin55e740e2021-03-29 02:06:19 +0100808 fixture := b.self.Fixture(t)
Paul Duffin35816122021-02-24 01:49:52 +0000809 return fixture.RunTest()
810}
811
Paul Duffinff2aa692021-03-19 18:20:59 +0000812func (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
Paul Duffin35816122021-02-24 01:49:52 +0000813 t.Helper()
Paul Duffin55e740e2021-03-29 02:06:19 +0100814 return GroupFixturePreparers(b.self, FixtureWithRootAndroidBp(bp)).RunTest(t)
Paul Duffin35816122021-02-24 01:49:52 +0000815}
816
Paul Duffinff2aa692021-03-19 18:20:59 +0000817func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
Paul Duffin72018ad2021-03-04 19:36:49 +0000818 t.Helper()
819 // Create the fixture as normal.
Paul Duffinff2aa692021-03-19 18:20:59 +0000820 fixture := b.self.Fixture(t).(*fixture)
Paul Duffin72018ad2021-03-04 19:36:49 +0000821
822 // Discard the mock filesystem as otherwise that will override the one in the config.
823 fixture.mockFS = nil
824
825 // Replace the config with the supplied one in the fixture.
826 fixture.config = config
827
828 // Ditto with config derived information in the TestContext.
829 ctx := fixture.ctx
830 ctx.config = config
831 ctx.SetFs(ctx.config.fs)
832 if ctx.config.mockBpList != "" {
833 ctx.SetModuleListFile(ctx.config.mockBpList)
834 }
835
Paul Duffin4c0765a2022-10-29 17:48:00 +0100836 return fixture.RunTest().testResult()
Paul Duffin72018ad2021-03-04 19:36:49 +0000837}
838
Paul Duffin35816122021-02-24 01:49:52 +0000839type fixture struct {
Paul Duffin59251822021-03-15 22:20:12 +0000840 // The preparers used to create this fixture.
841 preparers []*simpleFixturePreparer
Paul Duffincfd33742021-02-27 11:59:02 +0000842
Paul Duffin4c0765a2022-10-29 17:48:00 +0100843 // The test runner used in this fixture, defaults to defaultTestRunner if not set.
844 testRunner FixtureTestRunner
845
Paul Duffincfd33742021-02-27 11:59:02 +0000846 // The gotest state of the go test within which this was created.
847 t *testing.T
848
849 // The configuration prepared for this fixture.
850 config Config
851
852 // The test context prepared for this fixture.
853 ctx *TestContext
854
855 // The mock filesystem prepared for this fixture.
856 mockFS MockFS
857
858 // The error handler used to check the errors, if any, that are reported.
859 errorHandler FixtureErrorHandler
Paul Duffin64715ba2021-04-20 22:42:17 +0100860
861 // Debug mode status
862 debug bool
Paul Duffin35816122021-02-24 01:49:52 +0000863}
864
Paul Duffinae542a52021-03-09 03:15:28 +0000865func (f *fixture) Config() Config {
866 return f.config
867}
868
869func (f *fixture) Context() *TestContext {
870 return f.ctx
871}
872
873func (f *fixture) MockFS() MockFS {
874 return f.mockFS
875}
876
Paul Duffin4c0765a2022-10-29 17:48:00 +0100877func (f *fixture) RunTest() CustomTestResult {
Paul Duffin35816122021-02-24 01:49:52 +0000878 f.t.Helper()
879
Paul Duffin64715ba2021-04-20 22:42:17 +0100880 // If in debug mode output the state of the fixture before running the test.
881 if f.debug {
882 f.outputDebugState()
883 }
884
Paul Duffin35816122021-02-24 01:49:52 +0000885 ctx := f.ctx
886
Paul Duffin72018ad2021-03-04 19:36:49 +0000887 // Do not use the fixture's mockFS to initialize the config's mock file system if it has been
888 // cleared by RunTestWithConfig.
889 if f.mockFS != nil {
890 // The TestConfig() method assumes that the mock filesystem is available when creating so
891 // creates the mock file system immediately. Similarly, the NewTestContext(Config) method
892 // assumes that the supplied Config's FileSystem has been properly initialized before it is
893 // called and so it takes its own reference to the filesystem. However, fixtures create the
894 // Config and TestContext early so they can be modified by preparers at which time the mockFS
895 // has not been populated (because it too is modified by preparers). So, this reinitializes the
896 // Config and TestContext's FileSystem using the now populated mockFS.
897 f.config.mockFileSystem("", f.mockFS)
898
899 ctx.SetFs(ctx.config.fs)
900 if ctx.config.mockBpList != "" {
901 ctx.SetModuleListFile(ctx.config.mockBpList)
902 }
Paul Duffin35816122021-02-24 01:49:52 +0000903 }
904
Paul Duffin3f7bf9f2022-11-08 12:21:15 +0000905 // Create and set the Context's NameInterface. It needs to be created here as it depends on the
906 // configuration that has been prepared for this fixture.
907 resolver := NewNameResolver(ctx.config)
908
909 // Set the NameInterface in the main Context.
910 ctx.SetNameInterface(resolver)
911
912 // Set the NameResolver in the TestContext.
913 ctx.NameResolver = resolver
914
Paul Duffin4c0765a2022-10-29 17:48:00 +0100915 // If test runner has not been set then use the default runner.
916 if f.testRunner == nil {
917 f.testRunner = defaultTestRunner
Paul Duffincfd33742021-02-27 11:59:02 +0000918 }
Paul Duffin35816122021-02-24 01:49:52 +0000919
Paul Duffin4c0765a2022-10-29 17:48:00 +0100920 // Create the result to collate result information.
Paul Duffin35816122021-02-24 01:49:52 +0000921 result := &TestResult{
Paul Duffin35816122021-02-24 01:49:52 +0000922 testContext: testContext{ctx},
923 fixture: f,
924 Config: f.config,
Paul Duffin4c0765a2022-10-29 17:48:00 +0100925 }
926
927 // Do any last minute preparation before parsing the blueprint files.
928 customResult := f.testRunner.FinalPreparer(result)
929
930 // Parse the blueprint files adding the information to the result.
931 extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
932 result.NinjaDeps = append(result.NinjaDeps, extraNinjaDeps...)
933 result.Errs = append(result.Errs, errs...)
934
935 if len(result.Errs) == 0 {
936 // If parsing the blueprint files was successful then perform any additional processing.
937 f.testRunner.PostParseProcessor(customResult)
Paul Duffin35816122021-02-24 01:49:52 +0000938 }
Paul Duffincfd33742021-02-27 11:59:02 +0000939
Paul Duffinc81854a2021-03-12 12:22:27 +0000940 f.errorHandler.CheckErrors(f.t, result)
Paul Duffincfd33742021-02-27 11:59:02 +0000941
Paul Duffin4c0765a2022-10-29 17:48:00 +0100942 return customResult
943}
944
945// standardTestRunner is the implementation of the default test runner
946type standardTestRunner struct{}
947
948func (s *standardTestRunner) FinalPreparer(result *TestResult) CustomTestResult {
949 // Register the hard coded mutators and singletons used by the standard Soong build as well as
950 // any additional instances that have been registered with this fixture.
951 result.TestContext.Register()
Paul Duffin35816122021-02-24 01:49:52 +0000952 return result
953}
954
Paul Duffin4c0765a2022-10-29 17:48:00 +0100955func (s *standardTestRunner) PostParseProcessor(customResult CustomTestResult) {
956 result := customResult.(*TestResult)
957 ctx := result.TestContext
958 cfg := result.Config
959 // Prepare the build actions, i.e. run all the mutators, singletons and then invoke the
960 // GenerateAndroidBuildActions methods on all the modules.
961 extraNinjaDeps, errs := ctx.PrepareBuildActions(cfg)
962 result.NinjaDeps = append(result.NinjaDeps, extraNinjaDeps...)
963 result.CollateErrs(errs)
964}
965
966var defaultTestRunner FixtureTestRunner = &standardTestRunner{}
967
Paul Duffin64715ba2021-04-20 22:42:17 +0100968func (f *fixture) outputDebugState() {
969 fmt.Printf("Begin Fixture State for %s\n", f.t.Name())
970 if len(f.config.env) == 0 {
971 fmt.Printf(" Fixture Env is empty\n")
972 } else {
973 fmt.Printf(" Begin Env\n")
974 for k, v := range f.config.env {
975 fmt.Printf(" - %s=%s\n", k, v)
976 }
977 fmt.Printf(" End Env\n")
978 }
979 if len(f.mockFS) == 0 {
980 fmt.Printf(" Mock FS is empty\n")
981 } else {
982 fmt.Printf(" Begin Mock FS Contents\n")
983 for p, c := range f.mockFS {
984 if c == nil {
985 fmt.Printf("\n - %s: nil\n", p)
986 } else {
987 contents := string(c)
988 separator := " ========================================================================"
989 fmt.Printf(" - %s\n%s\n", p, separator)
990 for i, line := range strings.Split(contents, "\n") {
991 fmt.Printf(" %6d: %s\n", i+1, line)
992 }
993 fmt.Printf("%s\n", separator)
994 }
995 }
996 fmt.Printf(" End Mock FS Contents\n")
997 }
998 fmt.Printf("End Fixture State for %s\n", f.t.Name())
999}
1000
Paul Duffin35816122021-02-24 01:49:52 +00001001// NormalizePathForTesting removes the test invocation specific build directory from the supplied
1002// path.
1003//
1004// If the path is within the build directory (e.g. an OutputPath) then this returns the relative
1005// path to avoid tests having to deal with the dynamically generated build directory.
1006//
1007// Otherwise, this returns the supplied path as it is almost certainly a source path that is
1008// relative to the root of the source tree.
1009//
1010// Even though some information is removed from some paths and not others it should be possible to
1011// differentiate between them by the paths themselves, e.g. output paths will likely include
1012// ".intermediates" but source paths won't.
1013func (r *TestResult) NormalizePathForTesting(path Path) string {
1014 pathContext := PathContextForTesting(r.Config)
1015 pathAsString := path.String()
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +02001016 if rel, isRel := MaybeRel(pathContext, r.Config.SoongOutDir(), pathAsString); isRel {
Paul Duffin35816122021-02-24 01:49:52 +00001017 return rel
1018 }
1019 return pathAsString
1020}
1021
1022// NormalizePathsForTesting normalizes each path in the supplied list and returns their normalized
1023// forms.
1024func (r *TestResult) NormalizePathsForTesting(paths Paths) []string {
1025 var result []string
1026 for _, path := range paths {
1027 result = append(result, r.NormalizePathForTesting(path))
1028 }
1029 return result
1030}
1031
Paul Duffin59251822021-03-15 22:20:12 +00001032// Preparer will return a FixturePreparer encapsulating all the preparers used to create the fixture
1033// that produced this result.
1034//
1035// e.g. assuming that this result was created by running:
Colin Crossd079e0b2022-08-16 10:27:33 -07001036//
1037// GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t)
Paul Duffin59251822021-03-15 22:20:12 +00001038//
1039// Then this method will be equivalent to running:
Colin Crossd079e0b2022-08-16 10:27:33 -07001040//
1041// GroupFixturePreparers(preparer1, preparer2, preparer3)
Paul Duffin59251822021-03-15 22:20:12 +00001042//
1043// This is intended for use by tests whose output is Android.bp files to verify that those files
1044// are valid, e.g. tests of the snapshots produced by the sdk module type.
1045func (r *TestResult) Preparer() FixturePreparer {
Paul Duffinff2aa692021-03-19 18:20:59 +00001046 return newFixturePreparer(r.fixture.preparers)
Paul Duffin59251822021-03-15 22:20:12 +00001047}
1048
Paul Duffin35816122021-02-24 01:49:52 +00001049// Module returns the module with the specific name and of the specified variant.
1050func (r *TestResult) Module(name string, variant string) Module {
1051 return r.ModuleForTests(name, variant).Module()
1052}
Paul Duffin4c0765a2022-10-29 17:48:00 +01001053
1054// CollateErrs adds additional errors to the result and returns true if there is more than one
1055// error in the result.
1056func (r *TestResult) CollateErrs(errs []error) bool {
1057 r.Errs = append(r.Errs, errs...)
1058 return len(r.Errs) > 0
1059}