fixture.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. // 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. package android
  15. import (
  16. "fmt"
  17. "strings"
  18. "testing"
  19. )
  20. // Provides support for creating test fixtures on which tests can be run. Reduces duplication
  21. // of test setup by allow tests to easily reuse setup code.
  22. //
  23. // Fixture
  24. // =======
  25. // These determine the environment within which a test can be run. Fixtures are mutable and are
  26. // created by FixtureFactory instances and mutated by FixturePreparer instances. They are created by
  27. // first creating a base Fixture (which is essentially empty) and then applying FixturePreparer
  28. // instances to it to modify the environment.
  29. //
  30. // FixtureFactory (deprecated)
  31. // ===========================
  32. // These are responsible for creating fixtures. Factories are immutable and are intended to be
  33. // initialized once and reused to create multiple fixtures. Each factory has a list of fixture
  34. // preparers that prepare a fixture for running a test. Factories can also be used to create other
  35. // factories by extending them with additional fixture preparers.
  36. //
  37. // FixturePreparer
  38. // ===============
  39. // These are responsible for modifying a Fixture in preparation for it to run a test. Preparers are
  40. // intended to be immutable and able to prepare multiple Fixture objects simultaneously without
  41. // them sharing any data.
  42. //
  43. // They provide the basic capabilities for running tests too.
  44. //
  45. // FixturePreparers are only ever applied once per test fixture. Prior to application the list of
  46. // FixturePreparers are flattened and deduped while preserving the order they first appear in the
  47. // list. This makes it easy to reuse, group and combine FixturePreparers together.
  48. //
  49. // Each small self contained piece of test setup should be their own FixturePreparer. e.g.
  50. // * A group of related modules.
  51. // * A group of related mutators.
  52. // * A combination of both.
  53. // * Configuration.
  54. //
  55. // They should not overlap, e.g. the same module type should not be registered by different
  56. // FixturePreparers as using them both would cause a build error. In that case the preparer should
  57. // be split into separate parts and combined together using FixturePreparers(...).
  58. //
  59. // e.g. attempting to use AllPreparers in preparing a Fixture would break as it would attempt to
  60. // register module bar twice:
  61. // var Preparer1 = FixtureRegisterWithContext(RegisterModuleFooAndBar)
  62. // var Preparer2 = FixtureRegisterWithContext(RegisterModuleBarAndBaz)
  63. // var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
  64. //
  65. // However, when restructured like this it would work fine:
  66. // var PreparerFoo = FixtureRegisterWithContext(RegisterModuleFoo)
  67. // var PreparerBar = FixtureRegisterWithContext(RegisterModuleBar)
  68. // var PreparerBaz = FixtureRegisterWithContext(RegisterModuleBaz)
  69. // var Preparer1 = GroupFixturePreparers(RegisterModuleFoo, RegisterModuleBar)
  70. // var Preparer2 = GroupFixturePreparers(RegisterModuleBar, RegisterModuleBaz)
  71. // var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
  72. //
  73. // As after deduping and flattening AllPreparers would result in the following preparers being
  74. // applied:
  75. // 1. PreparerFoo
  76. // 2. PreparerBar
  77. // 3. PreparerBaz
  78. //
  79. // Preparers can be used for both integration and unit tests.
  80. //
  81. // Integration tests typically use all the module types, mutators and singletons that are available
  82. // for that package to try and replicate the behavior of the runtime build as closely as possible.
  83. // However, that realism comes at a cost of increased fragility (as they can be broken by changes in
  84. // many different parts of the build) and also increased runtime, especially if they use lots of
  85. // singletons and mutators.
  86. //
  87. // Unit tests on the other hand try and minimize the amount of code being tested which makes them
  88. // less susceptible to changes elsewhere in the build and quick to run but at a cost of potentially
  89. // not testing realistic scenarios.
  90. //
  91. // Supporting unit tests effectively require that preparers are available at the lowest granularity
  92. // possible. Supporting integration tests effectively require that the preparers are organized into
  93. // groups that provide all the functionality available.
  94. //
  95. // At least in terms of tests that check the behavior of build components via processing
  96. // `Android.bp` there is no clear separation between a unit test and an integration test. Instead
  97. // they vary from one end that tests a single module (e.g. filegroup) to the other end that tests a
  98. // whole system of modules, mutators and singletons (e.g. apex + hiddenapi).
  99. //
  100. // TestResult
  101. // ==========
  102. // These are created by running tests in a Fixture and provide access to the Config and TestContext
  103. // in which the tests were run.
  104. //
  105. // Example
  106. // =======
  107. //
  108. // An exported preparer for use by other packages that need to use java modules.
  109. //
  110. // package java
  111. // var PrepareForIntegrationTestWithJava = GroupFixturePreparers(
  112. // android.PrepareForIntegrationTestWithAndroid,
  113. // FixtureRegisterWithContext(RegisterAGroupOfRelatedModulesMutatorsAndSingletons),
  114. // FixtureRegisterWithContext(RegisterAnotherGroupOfRelatedModulesMutatorsAndSingletons),
  115. // ...
  116. // )
  117. //
  118. // Some files to use in tests in the java package.
  119. //
  120. // var javaMockFS = android.MockFS{
  121. // "api/current.txt": nil,
  122. // "api/removed.txt": nil,
  123. // ...
  124. // }
  125. //
  126. // A package private preparer for use for testing java within the java package.
  127. //
  128. // var prepareForJavaTest = android.GroupFixturePreparers(
  129. // PrepareForIntegrationTestWithJava,
  130. // FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
  131. // ctx.RegisterModuleType("test_module", testModule)
  132. // }),
  133. // javaMockFS.AddToFixture(),
  134. // ...
  135. // }
  136. //
  137. // func TestJavaStuff(t *testing.T) {
  138. // result := android.GroupFixturePreparers(
  139. // prepareForJavaTest,
  140. // android.FixtureWithRootAndroidBp(`java_library {....}`),
  141. // android.MockFS{...}.AddToFixture(),
  142. // ).RunTest(t)
  143. // ... test result ...
  144. // }
  145. //
  146. // package cc
  147. // var PrepareForTestWithCC = android.GroupFixturePreparers(
  148. // android.PrepareForArchMutator,
  149. // android.prepareForPrebuilts,
  150. // FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
  151. // ...
  152. // )
  153. //
  154. // package apex
  155. //
  156. // var PrepareForApex = GroupFixturePreparers(
  157. // ...
  158. // )
  159. //
  160. // Use modules and mutators from java, cc and apex. Any duplicate preparers (like
  161. // android.PrepareForArchMutator) will be automatically deduped.
  162. //
  163. // var prepareForApexTest = android.GroupFixturePreparers(
  164. // PrepareForJava,
  165. // PrepareForCC,
  166. // PrepareForApex,
  167. // )
  168. //
  169. // // FixtureFactory instances have been deprecated, this remains for informational purposes to
  170. // // help explain some of the existing code but will be removed along with FixtureFactory.
  171. //
  172. // var javaFixtureFactory = android.NewFixtureFactory(
  173. // PrepareForIntegrationTestWithJava,
  174. // FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
  175. // ctx.RegisterModuleType("test_module", testModule)
  176. // }),
  177. // javaMockFS.AddToFixture(),
  178. // ...
  179. // }
  180. //
  181. // func TestJavaStuff(t *testing.T) {
  182. // result := javaFixtureFactory.RunTest(t,
  183. // android.FixtureWithRootAndroidBp(`java_library {....}`),
  184. // android.MockFS{...}.AddToFixture(),
  185. // )
  186. // ... test result ...
  187. // }
  188. //
  189. // package cc
  190. // var PrepareForTestWithCC = GroupFixturePreparers(
  191. // android.PrepareForArchMutator,
  192. // android.prepareForPrebuilts,
  193. // FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
  194. // ...
  195. // )
  196. //
  197. // package apex
  198. //
  199. // var PrepareForApex = GroupFixturePreparers(
  200. // ...
  201. // )
  202. //
  203. // Use modules and mutators from java, cc and apex. Any duplicate preparers (like
  204. // android.PrepareForArchMutator) will be automatically deduped.
  205. //
  206. // var apexFixtureFactory = android.NewFixtureFactory(
  207. // PrepareForJava,
  208. // PrepareForCC,
  209. // PrepareForApex,
  210. // )
  211. // Factory for Fixture objects.
  212. //
  213. // This is configured with a set of FixturePreparer objects that are used to
  214. // initialize each Fixture instance this creates.
  215. //
  216. // deprecated: Use FixturePreparer instead.
  217. type FixtureFactory interface {
  218. FixturePreparer
  219. }
  220. // Create a new FixtureFactory that will apply the supplied preparers.
  221. //
  222. // The buildDirSupplier is a pointer to the package level buildDir variable that is initialized by
  223. // the package level setUp method. It has to be a pointer to the variable as the variable will not
  224. // have been initialized at the time the factory is created. If it is nil then a test specific
  225. // temporary directory will be created instead.
  226. //
  227. // deprecated: The functionality provided by FixtureFactory will be merged into FixturePreparer
  228. func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) FixtureFactory {
  229. f := &fixtureFactory{
  230. buildDirSupplier: buildDirSupplier,
  231. compositeFixturePreparer: compositeFixturePreparer{
  232. preparers: dedupAndFlattenPreparers(nil, preparers),
  233. },
  234. }
  235. f.initBaseFixturePreparer(f)
  236. return f
  237. }
  238. // A set of mock files to add to the mock file system.
  239. type MockFS map[string][]byte
  240. // Merge adds the extra entries from the supplied map to this one.
  241. //
  242. // Fails if the supplied map files with the same paths are present in both of them.
  243. func (fs MockFS) Merge(extra map[string][]byte) {
  244. for p, c := range extra {
  245. validateFixtureMockFSPath(p)
  246. if _, ok := fs[p]; ok {
  247. panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists", p))
  248. }
  249. fs[p] = c
  250. }
  251. }
  252. // Ensure that tests cannot add paths into the mock file system which would not be allowed in the
  253. // runtime, e.g. absolute paths, paths relative to the 'out/' directory.
  254. func validateFixtureMockFSPath(path string) {
  255. // This uses validateSafePath rather than validatePath because the latter prevents adding files
  256. // that include a $ but there are tests that allow files with a $ to be used, albeit only by
  257. // globbing.
  258. validatedPath, err := validateSafePath(path)
  259. if err != nil {
  260. panic(err)
  261. }
  262. // Make sure that the path is canonical.
  263. if validatedPath != path {
  264. panic(fmt.Errorf("path %q is not a canonical path, use %q instead", path, validatedPath))
  265. }
  266. if path == "out" || strings.HasPrefix(path, "out/") {
  267. panic(fmt.Errorf("cannot add output path %q to the mock file system", path))
  268. }
  269. }
  270. func (fs MockFS) AddToFixture() FixturePreparer {
  271. return FixtureMergeMockFs(fs)
  272. }
  273. // FixtureCustomPreparer allows for the modification of any aspect of the fixture.
  274. //
  275. // This should only be used if one of the other more specific preparers are not suitable.
  276. func FixtureCustomPreparer(mutator func(fixture Fixture)) FixturePreparer {
  277. return newSimpleFixturePreparer(func(f *fixture) {
  278. mutator(f)
  279. })
  280. }
  281. // Modify the config
  282. func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
  283. return newSimpleFixturePreparer(func(f *fixture) {
  284. mutator(f.config)
  285. })
  286. }
  287. // Modify the config and context
  288. func FixtureModifyConfigAndContext(mutator func(config Config, ctx *TestContext)) FixturePreparer {
  289. return newSimpleFixturePreparer(func(f *fixture) {
  290. mutator(f.config, f.ctx)
  291. })
  292. }
  293. // Modify the context
  294. func FixtureModifyContext(mutator func(ctx *TestContext)) FixturePreparer {
  295. return newSimpleFixturePreparer(func(f *fixture) {
  296. mutator(f.ctx)
  297. })
  298. }
  299. func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
  300. return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
  301. }
  302. // Modify the mock filesystem
  303. func FixtureModifyMockFS(mutator func(fs MockFS)) FixturePreparer {
  304. return newSimpleFixturePreparer(func(f *fixture) {
  305. mutator(f.mockFS)
  306. // Make sure that invalid paths were not added to the mock filesystem.
  307. for p, _ := range f.mockFS {
  308. validateFixtureMockFSPath(p)
  309. }
  310. })
  311. }
  312. // Merge the supplied file system into the mock filesystem.
  313. //
  314. // Paths that already exist in the mock file system are overridden.
  315. func FixtureMergeMockFs(mockFS MockFS) FixturePreparer {
  316. return FixtureModifyMockFS(func(fs MockFS) {
  317. fs.Merge(mockFS)
  318. })
  319. }
  320. // Add a file to the mock filesystem
  321. //
  322. // Fail if the filesystem already contains a file with that path, use FixtureOverrideFile instead.
  323. func FixtureAddFile(path string, contents []byte) FixturePreparer {
  324. return FixtureModifyMockFS(func(fs MockFS) {
  325. validateFixtureMockFSPath(path)
  326. if _, ok := fs[path]; ok {
  327. panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists, use FixtureOverride*File instead", path))
  328. }
  329. fs[path] = contents
  330. })
  331. }
  332. // Add a text file to the mock filesystem
  333. //
  334. // Fail if the filesystem already contains a file with that path.
  335. func FixtureAddTextFile(path string, contents string) FixturePreparer {
  336. return FixtureAddFile(path, []byte(contents))
  337. }
  338. // Override a file in the mock filesystem
  339. //
  340. // If the file does not exist this behaves as FixtureAddFile.
  341. func FixtureOverrideFile(path string, contents []byte) FixturePreparer {
  342. return FixtureModifyMockFS(func(fs MockFS) {
  343. fs[path] = contents
  344. })
  345. }
  346. // Override a text file in the mock filesystem
  347. //
  348. // If the file does not exist this behaves as FixtureAddTextFile.
  349. func FixtureOverrideTextFile(path string, contents string) FixturePreparer {
  350. return FixtureOverrideFile(path, []byte(contents))
  351. }
  352. // Add the root Android.bp file with the supplied contents.
  353. func FixtureWithRootAndroidBp(contents string) FixturePreparer {
  354. return FixtureAddTextFile("Android.bp", contents)
  355. }
  356. // Merge some environment variables into the fixture.
  357. func FixtureMergeEnv(env map[string]string) FixturePreparer {
  358. return FixtureModifyConfig(func(config Config) {
  359. for k, v := range env {
  360. if k == "PATH" {
  361. panic("Cannot set PATH environment variable")
  362. }
  363. config.env[k] = v
  364. }
  365. })
  366. }
  367. // Modify the env.
  368. //
  369. // Will panic if the mutator changes the PATH environment variable.
  370. func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
  371. return FixtureModifyConfig(func(config Config) {
  372. oldPath := config.env["PATH"]
  373. mutator(config.env)
  374. newPath := config.env["PATH"]
  375. if newPath != oldPath {
  376. panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
  377. }
  378. })
  379. }
  380. // Allow access to the product variables when preparing the fixture.
  381. type FixtureProductVariables struct {
  382. *productVariables
  383. }
  384. // Modify product variables.
  385. func FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
  386. return FixtureModifyConfig(func(config Config) {
  387. productVariables := FixtureProductVariables{&config.productVariables}
  388. mutator(productVariables)
  389. })
  390. }
  391. // GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
  392. // the supplied FixturePreparer instances in order.
  393. //
  394. // Before preparing the fixture the list of preparers is flattened by replacing each
  395. // instance of GroupFixturePreparers with its contents.
  396. func GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
  397. all := dedupAndFlattenPreparers(nil, preparers)
  398. return newFixturePreparer(all)
  399. }
  400. // NullFixturePreparer is a preparer that does nothing.
  401. var NullFixturePreparer = GroupFixturePreparers()
  402. // OptionalFixturePreparer will return the supplied preparer if it is non-nil, otherwise it will
  403. // return the NullFixturePreparer
  404. func OptionalFixturePreparer(preparer FixturePreparer) FixturePreparer {
  405. if preparer == nil {
  406. return NullFixturePreparer
  407. } else {
  408. return preparer
  409. }
  410. }
  411. // FixturePreparer provides the ability to create, modify and then run tests within a fixture.
  412. type FixturePreparer interface {
  413. // Return the flattened and deduped list of simpleFixturePreparer pointers.
  414. list() []*simpleFixturePreparer
  415. // Creates a copy of this instance and adds some additional preparers.
  416. //
  417. // Before the preparers are used they are combined with the preparers provided when the factory
  418. // was created, any groups of preparers are flattened, and the list is deduped so that each
  419. // preparer is only used once. See the file documentation in android/fixture.go for more details.
  420. //
  421. // deprecated: Use GroupFixturePreparers() instead.
  422. Extend(preparers ...FixturePreparer) FixturePreparer
  423. // Create a Fixture.
  424. Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
  425. // ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
  426. // to check the errors (may be 0) reported by the test.
  427. //
  428. // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
  429. // errors are reported.
  430. ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer
  431. // Run the test, checking any errors reported and returning a TestResult instance.
  432. //
  433. // Shorthand for Fixture(t).RunTest()
  434. RunTest(t *testing.T) *TestResult
  435. // Run the test with the supplied Android.bp file.
  436. //
  437. // preparer.RunTestWithBp(t, bp) is shorthand for
  438. // android.GroupFixturePreparers(preparer, android.FixtureWithRootAndroidBp(bp)).RunTest(t)
  439. RunTestWithBp(t *testing.T, bp string) *TestResult
  440. // RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
  441. // the test fixture.
  442. //
  443. // In order to allow the Config object to be customized separately to the TestContext a lot of
  444. // existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
  445. // from the test and then have the TestContext created and configured automatically. e.g.
  446. // testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
  447. //
  448. // This method allows those methods to be migrated to use the test fixture pattern without
  449. // requiring that every test that uses those methods be migrated at the same time. That allows
  450. // those tests to benefit from correctness in the order of registration quickly.
  451. //
  452. // This method discards the config (along with its mock file system, product variables,
  453. // environment, etc.) that may have been set up by FixturePreparers.
  454. //
  455. // deprecated
  456. RunTestWithConfig(t *testing.T, config Config) *TestResult
  457. }
  458. // dedupAndFlattenPreparers removes any duplicates and flattens any composite FixturePreparer
  459. // instances.
  460. //
  461. // base - a list of already flattened and deduped preparers that will be applied first before
  462. // the list of additional preparers. Any duplicates of these in the additional preparers
  463. // will be ignored.
  464. //
  465. // preparers - a list of additional unflattened, undeduped preparers that will be applied after the
  466. // base preparers.
  467. //
  468. // Returns a deduped and flattened list of the preparers starting with the ones in base with any
  469. // additional ones from the preparers list added afterwards.
  470. func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers []FixturePreparer) []*simpleFixturePreparer {
  471. if len(preparers) == 0 {
  472. return base
  473. }
  474. list := make([]*simpleFixturePreparer, len(base))
  475. visited := make(map[*simpleFixturePreparer]struct{})
  476. // Mark the already flattened and deduped preparers, if any, as having been seen so that
  477. // duplicates of these in the additional preparers will be discarded. Add them to the output
  478. // list.
  479. for i, s := range base {
  480. visited[s] = struct{}{}
  481. list[i] = s
  482. }
  483. for _, p := range preparers {
  484. for _, s := range p.list() {
  485. if _, seen := visited[s]; !seen {
  486. visited[s] = struct{}{}
  487. list = append(list, s)
  488. }
  489. }
  490. }
  491. return list
  492. }
  493. // compositeFixturePreparer is a FixturePreparer created from a list of fixture preparers.
  494. type compositeFixturePreparer struct {
  495. baseFixturePreparer
  496. // The flattened and deduped list of simpleFixturePreparer pointers encapsulated within this
  497. // composite preparer.
  498. preparers []*simpleFixturePreparer
  499. }
  500. func (c *compositeFixturePreparer) list() []*simpleFixturePreparer {
  501. return c.preparers
  502. }
  503. func newFixturePreparer(preparers []*simpleFixturePreparer) FixturePreparer {
  504. if len(preparers) == 1 {
  505. return preparers[0]
  506. }
  507. p := &compositeFixturePreparer{
  508. preparers: preparers,
  509. }
  510. p.initBaseFixturePreparer(p)
  511. return p
  512. }
  513. // simpleFixturePreparer is a FixturePreparer that applies a function to a fixture.
  514. type simpleFixturePreparer struct {
  515. baseFixturePreparer
  516. function func(fixture *fixture)
  517. }
  518. func (s *simpleFixturePreparer) list() []*simpleFixturePreparer {
  519. return []*simpleFixturePreparer{s}
  520. }
  521. func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer {
  522. p := &simpleFixturePreparer{function: preparer}
  523. p.initBaseFixturePreparer(p)
  524. return p
  525. }
  526. // FixtureErrorHandler determines how to respond to errors reported by the code under test.
  527. //
  528. // Some possible responses:
  529. // * Fail the test if any errors are reported, see FixtureExpectsNoErrors.
  530. // * Fail the test if at least one error that matches a pattern is not reported see
  531. // FixtureExpectsAtLeastOneErrorMatchingPattern
  532. // * Fail the test if any unexpected errors are reported.
  533. //
  534. // Although at the moment all the error handlers are implemented as simply a wrapper around a
  535. // function this is defined as an interface to allow future enhancements, e.g. provide different
  536. // ways other than patterns to match an error and to combine handlers together.
  537. type FixtureErrorHandler interface {
  538. // CheckErrors checks the errors reported.
  539. //
  540. // The supplied result can be used to access the state of the code under test just as the main
  541. // body of the test would but if any errors other than ones expected are reported the state may
  542. // be indeterminate.
  543. CheckErrors(t *testing.T, result *TestResult)
  544. }
  545. type simpleErrorHandler struct {
  546. function func(t *testing.T, result *TestResult)
  547. }
  548. func (h simpleErrorHandler) CheckErrors(t *testing.T, result *TestResult) {
  549. t.Helper()
  550. h.function(t, result)
  551. }
  552. // The default fixture error handler.
  553. //
  554. // Will fail the test immediately if any errors are reported.
  555. //
  556. // If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
  557. // which the test is being run which means that the RunTest() method will not return.
  558. var FixtureExpectsNoErrors = FixtureCustomErrorHandler(
  559. func(t *testing.T, result *TestResult) {
  560. t.Helper()
  561. FailIfErrored(t, result.Errs)
  562. },
  563. )
  564. // FixtureIgnoreErrors ignores any errors.
  565. //
  566. // If this is used then it is the responsibility of the test to check the TestResult.Errs does not
  567. // contain any unexpected errors.
  568. var FixtureIgnoreErrors = FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
  569. // Ignore the errors
  570. })
  571. // FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail
  572. // if at least one error that matches the regular expression is not found.
  573. //
  574. // The test will be failed if:
  575. // * No errors are reported.
  576. // * One or more errors are reported but none match the pattern.
  577. //
  578. // The test will not fail if:
  579. // * Multiple errors are reported that do not match the pattern as long as one does match.
  580. //
  581. // If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
  582. // which the test is being run which means that the RunTest() method will not return.
  583. func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
  584. return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
  585. t.Helper()
  586. if !FailIfNoMatchingErrors(t, pattern, result.Errs) {
  587. t.FailNow()
  588. }
  589. })
  590. }
  591. // FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail
  592. // if there are any unexpected errors.
  593. //
  594. // The test will be failed if:
  595. // * The number of errors reported does not exactly match the patterns.
  596. // * One or more of the reported errors do not match a pattern.
  597. // * No patterns are provided and one or more errors are reported.
  598. //
  599. // The test will not fail if:
  600. // * One or more of the patterns does not match an error.
  601. //
  602. // If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
  603. // which the test is being run which means that the RunTest() method will not return.
  604. func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
  605. return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
  606. t.Helper()
  607. CheckErrorsAgainstExpectations(t, result.Errs, patterns)
  608. })
  609. }
  610. // FixtureCustomErrorHandler creates a custom error handler
  611. func FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler {
  612. return simpleErrorHandler{
  613. function: function,
  614. }
  615. }
  616. // Fixture defines the test environment.
  617. type Fixture interface {
  618. // Config returns the fixture's configuration.
  619. Config() Config
  620. // Context returns the fixture's test context.
  621. Context() *TestContext
  622. // MockFS returns the fixture's mock filesystem.
  623. MockFS() MockFS
  624. // Run the test, checking any errors reported and returning a TestResult instance.
  625. RunTest() *TestResult
  626. }
  627. // Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
  628. type testContext struct {
  629. *TestContext
  630. }
  631. // The result of running a test.
  632. type TestResult struct {
  633. testContext
  634. fixture *fixture
  635. Config Config
  636. // The errors that were reported during the test.
  637. Errs []error
  638. // The ninja deps is a list of the ninja files dependencies that were added by the modules and
  639. // singletons via the *.AddNinjaFileDeps() methods.
  640. NinjaDeps []string
  641. }
  642. func createFixture(t *testing.T, buildDir string, base []*simpleFixturePreparer, extra []FixturePreparer) Fixture {
  643. all := dedupAndFlattenPreparers(base, extra)
  644. config := TestConfig(buildDir, nil, "", nil)
  645. ctx := NewTestContext(config)
  646. fixture := &fixture{
  647. preparers: all,
  648. t: t,
  649. config: config,
  650. ctx: ctx,
  651. mockFS: make(MockFS),
  652. // Set the default error handler.
  653. errorHandler: FixtureExpectsNoErrors,
  654. }
  655. for _, preparer := range all {
  656. preparer.function(fixture)
  657. }
  658. return fixture
  659. }
  660. type baseFixturePreparer struct {
  661. self FixturePreparer
  662. }
  663. func (b *baseFixturePreparer) initBaseFixturePreparer(self FixturePreparer) {
  664. b.self = self
  665. }
  666. func (b *baseFixturePreparer) Extend(preparers ...FixturePreparer) FixturePreparer {
  667. all := dedupAndFlattenPreparers(b.self.list(), preparers)
  668. return newFixturePreparer(all)
  669. }
  670. func (b *baseFixturePreparer) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
  671. return createFixture(t, t.TempDir(), b.self.list(), preparers)
  672. }
  673. func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
  674. return b.self.Extend(newSimpleFixturePreparer(func(fixture *fixture) {
  675. fixture.errorHandler = errorHandler
  676. }))
  677. }
  678. func (b *baseFixturePreparer) RunTest(t *testing.T) *TestResult {
  679. t.Helper()
  680. fixture := b.self.Fixture(t)
  681. return fixture.RunTest()
  682. }
  683. func (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
  684. t.Helper()
  685. return GroupFixturePreparers(b.self, FixtureWithRootAndroidBp(bp)).RunTest(t)
  686. }
  687. func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
  688. t.Helper()
  689. // Create the fixture as normal.
  690. fixture := b.self.Fixture(t).(*fixture)
  691. // Discard the mock filesystem as otherwise that will override the one in the config.
  692. fixture.mockFS = nil
  693. // Replace the config with the supplied one in the fixture.
  694. fixture.config = config
  695. // Ditto with config derived information in the TestContext.
  696. ctx := fixture.ctx
  697. ctx.config = config
  698. ctx.SetFs(ctx.config.fs)
  699. if ctx.config.mockBpList != "" {
  700. ctx.SetModuleListFile(ctx.config.mockBpList)
  701. }
  702. return fixture.RunTest()
  703. }
  704. var _ FixtureFactory = (*fixtureFactory)(nil)
  705. type fixtureFactory struct {
  706. compositeFixturePreparer
  707. buildDirSupplier *string
  708. }
  709. // Override to preserve the buildDirSupplier.
  710. func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixturePreparer {
  711. // If there is no buildDirSupplier then just use the default implementation.
  712. if f.buildDirSupplier == nil {
  713. return f.baseFixturePreparer.Extend(preparers...)
  714. }
  715. all := dedupAndFlattenPreparers(f.preparers, preparers)
  716. // Create a new factory which uses the same buildDirSupplier as the previous one.
  717. extendedFactory := &fixtureFactory{
  718. buildDirSupplier: f.buildDirSupplier,
  719. compositeFixturePreparer: compositeFixturePreparer{
  720. preparers: all,
  721. },
  722. }
  723. extendedFactory.initBaseFixturePreparer(extendedFactory)
  724. return extendedFactory
  725. }
  726. func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
  727. // If there is no buildDirSupplier then just use the default implementation.
  728. if f.buildDirSupplier == nil {
  729. return f.baseFixturePreparer.Fixture(t, preparers...)
  730. }
  731. // Retrieve the buildDir from the supplier.
  732. buildDir := *f.buildDirSupplier
  733. return createFixture(t, buildDir, f.preparers, preparers)
  734. }
  735. type fixture struct {
  736. // The preparers used to create this fixture.
  737. preparers []*simpleFixturePreparer
  738. // The gotest state of the go test within which this was created.
  739. t *testing.T
  740. // The configuration prepared for this fixture.
  741. config Config
  742. // The test context prepared for this fixture.
  743. ctx *TestContext
  744. // The mock filesystem prepared for this fixture.
  745. mockFS MockFS
  746. // The error handler used to check the errors, if any, that are reported.
  747. errorHandler FixtureErrorHandler
  748. }
  749. func (f *fixture) Config() Config {
  750. return f.config
  751. }
  752. func (f *fixture) Context() *TestContext {
  753. return f.ctx
  754. }
  755. func (f *fixture) MockFS() MockFS {
  756. return f.mockFS
  757. }
  758. func (f *fixture) RunTest() *TestResult {
  759. f.t.Helper()
  760. ctx := f.ctx
  761. // Do not use the fixture's mockFS to initialize the config's mock file system if it has been
  762. // cleared by RunTestWithConfig.
  763. if f.mockFS != nil {
  764. // The TestConfig() method assumes that the mock filesystem is available when creating so
  765. // creates the mock file system immediately. Similarly, the NewTestContext(Config) method
  766. // assumes that the supplied Config's FileSystem has been properly initialized before it is
  767. // called and so it takes its own reference to the filesystem. However, fixtures create the
  768. // Config and TestContext early so they can be modified by preparers at which time the mockFS
  769. // has not been populated (because it too is modified by preparers). So, this reinitializes the
  770. // Config and TestContext's FileSystem using the now populated mockFS.
  771. f.config.mockFileSystem("", f.mockFS)
  772. ctx.SetFs(ctx.config.fs)
  773. if ctx.config.mockBpList != "" {
  774. ctx.SetModuleListFile(ctx.config.mockBpList)
  775. }
  776. }
  777. ctx.Register()
  778. var ninjaDeps []string
  779. extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
  780. if len(errs) == 0 {
  781. ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
  782. extraNinjaDeps, errs = ctx.PrepareBuildActions(f.config)
  783. if len(errs) == 0 {
  784. ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
  785. }
  786. }
  787. result := &TestResult{
  788. testContext: testContext{ctx},
  789. fixture: f,
  790. Config: f.config,
  791. Errs: errs,
  792. NinjaDeps: ninjaDeps,
  793. }
  794. f.errorHandler.CheckErrors(f.t, result)
  795. return result
  796. }
  797. // NormalizePathForTesting removes the test invocation specific build directory from the supplied
  798. // path.
  799. //
  800. // If the path is within the build directory (e.g. an OutputPath) then this returns the relative
  801. // path to avoid tests having to deal with the dynamically generated build directory.
  802. //
  803. // Otherwise, this returns the supplied path as it is almost certainly a source path that is
  804. // relative to the root of the source tree.
  805. //
  806. // Even though some information is removed from some paths and not others it should be possible to
  807. // differentiate between them by the paths themselves, e.g. output paths will likely include
  808. // ".intermediates" but source paths won't.
  809. func (r *TestResult) NormalizePathForTesting(path Path) string {
  810. pathContext := PathContextForTesting(r.Config)
  811. pathAsString := path.String()
  812. if rel, isRel := MaybeRel(pathContext, r.Config.BuildDir(), pathAsString); isRel {
  813. return rel
  814. }
  815. return pathAsString
  816. }
  817. // NormalizePathsForTesting normalizes each path in the supplied list and returns their normalized
  818. // forms.
  819. func (r *TestResult) NormalizePathsForTesting(paths Paths) []string {
  820. var result []string
  821. for _, path := range paths {
  822. result = append(result, r.NormalizePathForTesting(path))
  823. }
  824. return result
  825. }
  826. // Preparer will return a FixturePreparer encapsulating all the preparers used to create the fixture
  827. // that produced this result.
  828. //
  829. // e.g. assuming that this result was created by running:
  830. // factory.Extend(preparer1, preparer2).RunTest(t, preparer3, preparer4)
  831. //
  832. // Then this method will be equivalent to running:
  833. // GroupFixturePreparers(preparer1, preparer2, preparer3, preparer4)
  834. //
  835. // This is intended for use by tests whose output is Android.bp files to verify that those files
  836. // are valid, e.g. tests of the snapshots produced by the sdk module type.
  837. func (r *TestResult) Preparer() FixturePreparer {
  838. return newFixturePreparer(r.fixture.preparers)
  839. }
  840. // Module returns the module with the specific name and of the specified variant.
  841. func (r *TestResult) Module(name string, variant string) Module {
  842. return r.ModuleForTests(name, variant).Module()
  843. }