fixture.go 30 KB

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