testing.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. // Copyright 2017 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. "path/filepath"
  18. "regexp"
  19. "sort"
  20. "strings"
  21. "testing"
  22. "github.com/google/blueprint"
  23. )
  24. func NewTestContext(config Config) *TestContext {
  25. namespaceExportFilter := func(namespace *Namespace) bool {
  26. return true
  27. }
  28. nameResolver := NewNameResolver(namespaceExportFilter)
  29. ctx := &TestContext{
  30. Context: &Context{blueprint.NewContext(), config},
  31. NameResolver: nameResolver,
  32. }
  33. ctx.SetNameInterface(nameResolver)
  34. ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
  35. ctx.SetFs(ctx.config.fs)
  36. if ctx.config.mockBpList != "" {
  37. ctx.SetModuleListFile(ctx.config.mockBpList)
  38. }
  39. return ctx
  40. }
  41. func NewTestArchContext(config Config) *TestContext {
  42. ctx := NewTestContext(config)
  43. ctx.preDeps = append(ctx.preDeps, registerArchMutator)
  44. return ctx
  45. }
  46. type TestContext struct {
  47. *Context
  48. preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
  49. NameResolver *NameResolver
  50. }
  51. func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
  52. ctx.preArch = append(ctx.preArch, f)
  53. }
  54. func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
  55. // Register mutator function as normal for testing.
  56. ctx.PreArchMutators(f)
  57. }
  58. func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
  59. ctx.preDeps = append(ctx.preDeps, f)
  60. }
  61. func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
  62. ctx.postDeps = append(ctx.postDeps, f)
  63. }
  64. func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
  65. ctx.finalDeps = append(ctx.finalDeps, f)
  66. }
  67. func (ctx *TestContext) Register() {
  68. registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
  69. ctx.RegisterSingletonType("env", EnvSingleton)
  70. }
  71. func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
  72. // This function adapts the old style ParseFileList calls that are spread throughout the tests
  73. // to the new style that takes a config.
  74. return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config)
  75. }
  76. func (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) {
  77. // This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the
  78. // tests to the new style that takes a config.
  79. return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config)
  80. }
  81. func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
  82. ctx.Context.RegisterModuleType(name, ModuleFactoryAdaptor(factory))
  83. }
  84. func (ctx *TestContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
  85. s, m := SingletonModuleFactoryAdaptor(name, factory)
  86. ctx.RegisterSingletonType(name, s)
  87. ctx.RegisterModuleType(name, m)
  88. }
  89. func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
  90. ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
  91. }
  92. func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
  93. var module Module
  94. ctx.VisitAllModules(func(m blueprint.Module) {
  95. if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
  96. module = m.(Module)
  97. }
  98. })
  99. if module == nil {
  100. // find all the modules that do exist
  101. var allModuleNames []string
  102. var allVariants []string
  103. ctx.VisitAllModules(func(m blueprint.Module) {
  104. allModuleNames = append(allModuleNames, ctx.ModuleName(m))
  105. if ctx.ModuleName(m) == name {
  106. allVariants = append(allVariants, ctx.ModuleSubDir(m))
  107. }
  108. })
  109. sort.Strings(allModuleNames)
  110. sort.Strings(allVariants)
  111. if len(allVariants) == 0 {
  112. panic(fmt.Errorf("failed to find module %q. All modules:\n %s",
  113. name, strings.Join(allModuleNames, "\n ")))
  114. } else {
  115. panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n %s",
  116. name, variant, strings.Join(allVariants, "\n ")))
  117. }
  118. }
  119. return TestingModule{module}
  120. }
  121. func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
  122. var variants []string
  123. ctx.VisitAllModules(func(m blueprint.Module) {
  124. if ctx.ModuleName(m) == name {
  125. variants = append(variants, ctx.ModuleSubDir(m))
  126. }
  127. })
  128. return variants
  129. }
  130. // SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
  131. func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
  132. allSingletonNames := []string{}
  133. for _, s := range ctx.Singletons() {
  134. n := ctx.SingletonName(s)
  135. if n == name {
  136. return TestingSingleton{
  137. singleton: s.(*singletonAdaptor).Singleton,
  138. provider: s.(testBuildProvider),
  139. }
  140. }
  141. allSingletonNames = append(allSingletonNames, n)
  142. }
  143. panic(fmt.Errorf("failed to find singleton %q."+
  144. "\nall singletons: %v", name, allSingletonNames))
  145. }
  146. type testBuildProvider interface {
  147. BuildParamsForTests() []BuildParams
  148. RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
  149. }
  150. type TestingBuildParams struct {
  151. BuildParams
  152. RuleParams blueprint.RuleParams
  153. }
  154. func newTestingBuildParams(provider testBuildProvider, bparams BuildParams) TestingBuildParams {
  155. return TestingBuildParams{
  156. BuildParams: bparams,
  157. RuleParams: provider.RuleParamsForTests()[bparams.Rule],
  158. }
  159. }
  160. func maybeBuildParamsFromRule(provider testBuildProvider, rule string) (TestingBuildParams, []string) {
  161. var searchedRules []string
  162. for _, p := range provider.BuildParamsForTests() {
  163. searchedRules = append(searchedRules, p.Rule.String())
  164. if strings.Contains(p.Rule.String(), rule) {
  165. return newTestingBuildParams(provider, p), searchedRules
  166. }
  167. }
  168. return TestingBuildParams{}, searchedRules
  169. }
  170. func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
  171. p, searchRules := maybeBuildParamsFromRule(provider, rule)
  172. if p.Rule == nil {
  173. panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
  174. }
  175. return p
  176. }
  177. func maybeBuildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
  178. for _, p := range provider.BuildParamsForTests() {
  179. if strings.Contains(p.Description, desc) {
  180. return newTestingBuildParams(provider, p)
  181. }
  182. }
  183. return TestingBuildParams{}
  184. }
  185. func buildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
  186. p := maybeBuildParamsFromDescription(provider, desc)
  187. if p.Rule == nil {
  188. panic(fmt.Errorf("couldn't find description %q", desc))
  189. }
  190. return p
  191. }
  192. func maybeBuildParamsFromOutput(provider testBuildProvider, file string) (TestingBuildParams, []string) {
  193. var searchedOutputs []string
  194. for _, p := range provider.BuildParamsForTests() {
  195. outputs := append(WritablePaths(nil), p.Outputs...)
  196. outputs = append(outputs, p.ImplicitOutputs...)
  197. if p.Output != nil {
  198. outputs = append(outputs, p.Output)
  199. }
  200. for _, f := range outputs {
  201. if f.String() == file || f.Rel() == file {
  202. return newTestingBuildParams(provider, p), nil
  203. }
  204. searchedOutputs = append(searchedOutputs, f.Rel())
  205. }
  206. }
  207. return TestingBuildParams{}, searchedOutputs
  208. }
  209. func buildParamsFromOutput(provider testBuildProvider, file string) TestingBuildParams {
  210. p, searchedOutputs := maybeBuildParamsFromOutput(provider, file)
  211. if p.Rule == nil {
  212. panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
  213. file, searchedOutputs))
  214. }
  215. return p
  216. }
  217. func allOutputs(provider testBuildProvider) []string {
  218. var outputFullPaths []string
  219. for _, p := range provider.BuildParamsForTests() {
  220. outputs := append(WritablePaths(nil), p.Outputs...)
  221. outputs = append(outputs, p.ImplicitOutputs...)
  222. if p.Output != nil {
  223. outputs = append(outputs, p.Output)
  224. }
  225. outputFullPaths = append(outputFullPaths, outputs.Strings()...)
  226. }
  227. return outputFullPaths
  228. }
  229. // TestingModule is wrapper around an android.Module that provides methods to find information about individual
  230. // ctx.Build parameters for verification in tests.
  231. type TestingModule struct {
  232. module Module
  233. }
  234. // Module returns the Module wrapped by the TestingModule.
  235. func (m TestingModule) Module() Module {
  236. return m.module
  237. }
  238. // MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
  239. // BuildParams if no rule is found.
  240. func (m TestingModule) MaybeRule(rule string) TestingBuildParams {
  241. r, _ := maybeBuildParamsFromRule(m.module, rule)
  242. return r
  243. }
  244. // Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
  245. func (m TestingModule) Rule(rule string) TestingBuildParams {
  246. return buildParamsFromRule(m.module, rule)
  247. }
  248. // MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
  249. // BuildParams if no rule is found.
  250. func (m TestingModule) MaybeDescription(desc string) TestingBuildParams {
  251. return maybeBuildParamsFromDescription(m.module, desc)
  252. }
  253. // Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
  254. // found.
  255. func (m TestingModule) Description(desc string) TestingBuildParams {
  256. return buildParamsFromDescription(m.module, desc)
  257. }
  258. // MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
  259. // value matches the provided string. Returns an empty BuildParams if no rule is found.
  260. func (m TestingModule) MaybeOutput(file string) TestingBuildParams {
  261. p, _ := maybeBuildParamsFromOutput(m.module, file)
  262. return p
  263. }
  264. // Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
  265. // value matches the provided string. Panics if no rule is found.
  266. func (m TestingModule) Output(file string) TestingBuildParams {
  267. return buildParamsFromOutput(m.module, file)
  268. }
  269. // AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
  270. func (m TestingModule) AllOutputs() []string {
  271. return allOutputs(m.module)
  272. }
  273. // TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
  274. // ctx.Build parameters for verification in tests.
  275. type TestingSingleton struct {
  276. singleton Singleton
  277. provider testBuildProvider
  278. }
  279. // Singleton returns the Singleton wrapped by the TestingSingleton.
  280. func (s TestingSingleton) Singleton() Singleton {
  281. return s.singleton
  282. }
  283. // MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
  284. // BuildParams if no rule is found.
  285. func (s TestingSingleton) MaybeRule(rule string) TestingBuildParams {
  286. r, _ := maybeBuildParamsFromRule(s.provider, rule)
  287. return r
  288. }
  289. // Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
  290. func (s TestingSingleton) Rule(rule string) TestingBuildParams {
  291. return buildParamsFromRule(s.provider, rule)
  292. }
  293. // MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
  294. // BuildParams if no rule is found.
  295. func (s TestingSingleton) MaybeDescription(desc string) TestingBuildParams {
  296. return maybeBuildParamsFromDescription(s.provider, desc)
  297. }
  298. // Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
  299. // found.
  300. func (s TestingSingleton) Description(desc string) TestingBuildParams {
  301. return buildParamsFromDescription(s.provider, desc)
  302. }
  303. // MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
  304. // value matches the provided string. Returns an empty BuildParams if no rule is found.
  305. func (s TestingSingleton) MaybeOutput(file string) TestingBuildParams {
  306. p, _ := maybeBuildParamsFromOutput(s.provider, file)
  307. return p
  308. }
  309. // Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
  310. // value matches the provided string. Panics if no rule is found.
  311. func (s TestingSingleton) Output(file string) TestingBuildParams {
  312. return buildParamsFromOutput(s.provider, file)
  313. }
  314. // AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
  315. func (s TestingSingleton) AllOutputs() []string {
  316. return allOutputs(s.provider)
  317. }
  318. func FailIfErrored(t *testing.T, errs []error) {
  319. t.Helper()
  320. if len(errs) > 0 {
  321. for _, err := range errs {
  322. t.Error(err)
  323. }
  324. t.FailNow()
  325. }
  326. }
  327. func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
  328. t.Helper()
  329. matcher, err := regexp.Compile(pattern)
  330. if err != nil {
  331. t.Errorf("failed to compile regular expression %q because %s", pattern, err)
  332. }
  333. found := false
  334. for _, err := range errs {
  335. if matcher.FindStringIndex(err.Error()) != nil {
  336. found = true
  337. break
  338. }
  339. }
  340. if !found {
  341. t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
  342. for i, err := range errs {
  343. t.Errorf("errs[%d] = %q", i, err)
  344. }
  345. }
  346. }
  347. func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
  348. t.Helper()
  349. if expectedErrorPatterns == nil {
  350. FailIfErrored(t, errs)
  351. } else {
  352. for _, expectedError := range expectedErrorPatterns {
  353. FailIfNoMatchingErrors(t, expectedError, errs)
  354. }
  355. if len(errs) > len(expectedErrorPatterns) {
  356. t.Errorf("additional errors found, expected %d, found %d",
  357. len(expectedErrorPatterns), len(errs))
  358. for i, expectedError := range expectedErrorPatterns {
  359. t.Errorf("expectedErrors[%d] = %s", i, expectedError)
  360. }
  361. for i, err := range errs {
  362. t.Errorf("errs[%d] = %s", i, err)
  363. }
  364. }
  365. }
  366. }
  367. func SetKatiEnabledForTests(config Config) {
  368. config.katiEnabled = true
  369. }
  370. func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) []AndroidMkEntries {
  371. var p AndroidMkEntriesProvider
  372. var ok bool
  373. if p, ok = mod.(AndroidMkEntriesProvider); !ok {
  374. t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
  375. }
  376. entriesList := p.AndroidMkEntries()
  377. for i, _ := range entriesList {
  378. entriesList[i].fillInEntries(config, bpPath, mod)
  379. }
  380. return entriesList
  381. }
  382. func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData {
  383. var p AndroidMkDataProvider
  384. var ok bool
  385. if p, ok = mod.(AndroidMkDataProvider); !ok {
  386. t.Errorf("module does not implement AndroidMkDataProvider: " + mod.Name())
  387. }
  388. data := p.AndroidMk()
  389. data.fillInData(config, bpPath, mod)
  390. return data
  391. }
  392. // Normalize the path for testing.
  393. //
  394. // If the path is relative to the build directory then return the relative path
  395. // to avoid tests having to deal with the dynamically generated build directory.
  396. //
  397. // Otherwise, return the supplied path as it is almost certainly a source path
  398. // that is relative to the root of the source tree.
  399. //
  400. // The build and source paths should be distinguishable based on their contents.
  401. func NormalizePathForTesting(path Path) string {
  402. p := path.String()
  403. if w, ok := path.(WritablePath); ok {
  404. rel, err := filepath.Rel(w.buildDir(), p)
  405. if err != nil {
  406. panic(err)
  407. }
  408. return rel
  409. }
  410. return p
  411. }
  412. func NormalizePathsForTesting(paths Paths) []string {
  413. var result []string
  414. for _, path := range paths {
  415. relative := NormalizePathForTesting(path)
  416. result = append(result, relative)
  417. }
  418. return result
  419. }