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