• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15package android
16
17import (
18	"fmt"
19	"path/filepath"
20	"regexp"
21	"sort"
22	"strings"
23	"sync"
24	"testing"
25
26	"github.com/google/blueprint"
27	"github.com/google/blueprint/proptools"
28)
29
30func NewTestContext(config Config) *TestContext {
31	namespaceExportFilter := func(namespace *Namespace) bool {
32		return true
33	}
34
35	nameResolver := NewNameResolver(namespaceExportFilter)
36	ctx := &TestContext{
37		Context:      &Context{blueprint.NewContext(), config},
38		NameResolver: nameResolver,
39	}
40
41	ctx.SetNameInterface(nameResolver)
42
43	ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
44
45	ctx.SetFs(ctx.config.fs)
46	if ctx.config.mockBpList != "" {
47		ctx.SetModuleListFile(ctx.config.mockBpList)
48	}
49
50	return ctx
51}
52
53var PrepareForTestWithArchMutator = GroupFixturePreparers(
54	// Configure architecture targets in the fixture config.
55	FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
56
57	// Add the arch mutator to the context.
58	FixtureRegisterWithContext(func(ctx RegistrationContext) {
59		ctx.PreDepsMutators(registerArchMutator)
60	}),
61)
62
63var PrepareForTestWithDefaults = FixtureRegisterWithContext(func(ctx RegistrationContext) {
64	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
65})
66
67var PrepareForTestWithComponentsMutator = FixtureRegisterWithContext(func(ctx RegistrationContext) {
68	ctx.PreArchMutators(RegisterComponentsMutator)
69})
70
71var PrepareForTestWithPrebuilts = FixtureRegisterWithContext(RegisterPrebuiltMutators)
72
73var PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx RegistrationContext) {
74	ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
75})
76
77var PrepareForTestWithLicenses = GroupFixturePreparers(
78	FixtureRegisterWithContext(RegisterLicenseKindBuildComponents),
79	FixtureRegisterWithContext(RegisterLicenseBuildComponents),
80	FixtureRegisterWithContext(registerLicenseMutators),
81)
82
83func registerLicenseMutators(ctx RegistrationContext) {
84	ctx.PreArchMutators(RegisterLicensesPackageMapper)
85	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
86	ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
87}
88
89var PrepareForTestWithLicenseDefaultModules = GroupFixturePreparers(
90	FixtureAddTextFile("build/soong/licenses/Android.bp", `
91		license {
92				name: "Android-Apache-2.0",
93				package_name: "Android",
94				license_kinds: ["SPDX-license-identifier-Apache-2.0"],
95				copyright_notice: "Copyright (C) The Android Open Source Project",
96				license_text: ["LICENSE"],
97		}
98
99		license_kind {
100				name: "SPDX-license-identifier-Apache-2.0",
101				conditions: ["notice"],
102				url: "https://spdx.org/licenses/Apache-2.0.html",
103		}
104
105		license_kind {
106				name: "legacy_unencumbered",
107				conditions: ["unencumbered"],
108		}
109	`),
110	FixtureAddFile("build/soong/licenses/LICENSE", nil),
111)
112
113// Test fixture preparer that will register most java build components.
114//
115// Singletons and mutators should only be added here if they are needed for a majority of java
116// module types, otherwise they should be added under a separate preparer to allow them to be
117// selected only when needed to reduce test execution time.
118//
119// Module types do not have much of an overhead unless they are used so this should include as many
120// module types as possible. The exceptions are those module types that require mutators and/or
121// singletons in order to function in which case they should be kept together in a separate
122// preparer.
123//
124// The mutators in this group were chosen because they are needed by the vast majority of tests.
125var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
126	// Sorted alphabetically as the actual order does not matter as tests automatically enforce the
127	// correct order.
128	PrepareForTestWithArchMutator,
129	PrepareForTestWithComponentsMutator,
130	PrepareForTestWithDefaults,
131	PrepareForTestWithFilegroup,
132	PrepareForTestWithOverrides,
133	PrepareForTestWithPackageModule,
134	PrepareForTestWithPrebuilts,
135	PrepareForTestWithVisibility,
136)
137
138// Prepares an integration test with all build components from the android package.
139//
140// This should only be used by tests that want to run with as much of the build enabled as possible.
141var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
142	PrepareForTestWithAndroidBuildComponents,
143)
144
145// Prepares a test that may be missing dependencies by setting allow_missing_dependencies to
146// true.
147var PrepareForTestWithAllowMissingDependencies = GroupFixturePreparers(
148	FixtureModifyProductVariables(func(variables FixtureProductVariables) {
149		variables.Allow_missing_dependencies = proptools.BoolPtr(true)
150	}),
151	FixtureModifyContext(func(ctx *TestContext) {
152		ctx.SetAllowMissingDependencies(true)
153	}),
154)
155
156// Prepares a test that disallows non-existent paths.
157var PrepareForTestDisallowNonExistentPaths = FixtureModifyConfig(func(config Config) {
158	config.TestAllowNonExistentPaths = false
159})
160
161func NewTestArchContext(config Config) *TestContext {
162	ctx := NewTestContext(config)
163	ctx.preDeps = append(ctx.preDeps, registerArchMutator)
164	return ctx
165}
166
167type TestContext struct {
168	*Context
169	preArch, preDeps, postDeps, finalDeps           []RegisterMutatorFunc
170	bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
171	NameResolver                                    *NameResolver
172
173	// The list of pre-singletons and singletons registered for the test.
174	preSingletons, singletons sortableComponents
175
176	// The order in which the pre-singletons, mutators and singletons will be run in this test
177	// context; for debugging.
178	preSingletonOrder, mutatorOrder, singletonOrder []string
179}
180
181func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
182	ctx.preArch = append(ctx.preArch, f)
183}
184
185func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
186	// Register mutator function as normal for testing.
187	ctx.PreArchMutators(f)
188}
189
190func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
191	ctx.preDeps = append(ctx.preDeps, f)
192}
193
194func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
195	ctx.postDeps = append(ctx.postDeps, f)
196}
197
198func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
199	ctx.finalDeps = append(ctx.finalDeps, f)
200}
201
202func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConfig) {
203	ctx.config.bp2buildPackageConfig = config
204}
205
206// RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
207// type to the equivalent Bazel target.
208func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
209	f := func(ctx RegisterMutatorsContext) {
210		ctx.TopDown(moduleType, m)
211	}
212	ctx.config.bp2buildModuleTypeConfig[moduleType] = true
213	ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
214}
215
216// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
217// into Bazel BUILD targets that should run prior to deps and conversion.
218func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
219	ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
220}
221
222// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
223// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
224func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
225	ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
226}
227
228// registeredComponentOrder defines the order in which a sortableComponent type is registered at
229// runtime and provides support for reordering the components registered for a test in the same
230// way.
231type registeredComponentOrder struct {
232	// The name of the component type, used for error messages.
233	componentType string
234
235	// The names of the registered components in the order in which they were registered.
236	namesInOrder []string
237
238	// Maps from the component name to its position in the runtime ordering.
239	namesToIndex map[string]int
240
241	// A function that defines the order between two named components that can be used to sort a slice
242	// of component names into the same order as they appear in namesInOrder.
243	less func(string, string) bool
244}
245
246// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
247// creates a registeredComponentOrder that contains a less function that can be used to sort a
248// subset of that list of names so it is in the same order as the original sortableComponents.
249func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
250	// Only the names from the existing order are needed for this so create a list of component names
251	// in the correct order.
252	namesInOrder := componentsToNames(existingOrder)
253
254	// Populate the map from name to position in the list.
255	nameToIndex := make(map[string]int)
256	for i, n := range namesInOrder {
257		nameToIndex[n] = i
258	}
259
260	// A function to use to map from a name to an index in the original order.
261	indexOf := func(name string) int {
262		index, ok := nameToIndex[name]
263		if !ok {
264			// Should never happen as tests that use components that are not known at runtime do not sort
265			// so should never use this function.
266			panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
267		}
268		return index
269	}
270
271	// The less function.
272	less := func(n1, n2 string) bool {
273		i1 := indexOf(n1)
274		i2 := indexOf(n2)
275		return i1 < i2
276	}
277
278	return registeredComponentOrder{
279		componentType: componentType,
280		namesInOrder:  namesInOrder,
281		namesToIndex:  nameToIndex,
282		less:          less,
283	}
284}
285
286// componentsToNames maps from the slice of components to a slice of their names.
287func componentsToNames(components sortableComponents) []string {
288	names := make([]string, len(components))
289	for i, c := range components {
290		names[i] = c.componentName()
291	}
292	return names
293}
294
295// enforceOrdering enforces the supplied components are in the same order as is defined in this
296// object.
297//
298// If the supplied components contains any components that are not registered at runtime, i.e. test
299// specific components, then it is impossible to sort them into an order that both matches the
300// runtime and also preserves the implicit ordering defined in the test. In that case it will not
301// sort the components, instead it will just check that the components are in the correct order.
302//
303// Otherwise, this will sort the supplied components in place.
304func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
305	// Check to see if the list of components contains any components that are
306	// not registered at runtime.
307	var unknownComponents []string
308	testOrder := componentsToNames(components)
309	for _, name := range testOrder {
310		if _, ok := o.namesToIndex[name]; !ok {
311			unknownComponents = append(unknownComponents, name)
312			break
313		}
314	}
315
316	// If the slice contains some unknown components then it is not possible to
317	// sort them into an order that matches the runtime while also preserving the
318	// order expected from the test, so in that case don't sort just check that
319	// the order of the known mutators does match.
320	if len(unknownComponents) > 0 {
321		// Check order.
322		o.checkTestOrder(testOrder, unknownComponents)
323	} else {
324		// Sort the components.
325		sort.Slice(components, func(i, j int) bool {
326			n1 := components[i].componentName()
327			n2 := components[j].componentName()
328			return o.less(n1, n2)
329		})
330	}
331}
332
333// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
334// panicking if it does not.
335func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
336	lastMatchingTest := -1
337	matchCount := 0
338	// Take a copy of the runtime order as it is modified during the comparison.
339	runtimeOrder := append([]string(nil), o.namesInOrder...)
340	componentType := o.componentType
341	for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
342		test := testOrder[i]
343		runtime := runtimeOrder[j]
344
345		if test == runtime {
346			testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
347			runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
348			lastMatchingTest = i
349			i += 1
350			j += 1
351			matchCount += 1
352		} else if _, ok := o.namesToIndex[test]; !ok {
353			// The test component is not registered globally so assume it is the correct place, treat it
354			// as having matched and skip it.
355			i += 1
356			matchCount += 1
357		} else {
358			// Assume that the test list is in the same order as the runtime list but the runtime list
359			// contains some components that are not present in the tests. So, skip the runtime component
360			// to try and find the next one that matches the current test component.
361			j += 1
362		}
363	}
364
365	// If every item in the test order was either test specific or matched one in the runtime then
366	// it is in the correct order. Otherwise, it was not so fail.
367	if matchCount != len(testOrder) {
368		// The test component names were not all matched with a runtime component name so there must
369		// either be a component present in the test that is not present in the runtime or they must be
370		// in the wrong order.
371		testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
372		panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
373			" Unfortunately it uses %s components in the wrong order.\n"+
374			"test order:\n    %s\n"+
375			"runtime order\n    %s\n",
376			SortedUniqueStrings(unknownComponents),
377			componentType,
378			strings.Join(testOrder, "\n    "),
379			strings.Join(runtimeOrder, "\n    ")))
380	}
381}
382
383// registrationSorter encapsulates the information needed to ensure that the test mutators are
384// registered, and thereby executed, in the same order as they are at runtime.
385//
386// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
387// only define the order for a subset of all the registered build components that are available for
388// the packages being tested.
389//
390// e.g if this is initialized during say the cc package initialization then any tests run in the
391// java package will not sort build components registered by the java package's init() functions.
392type registrationSorter struct {
393	// Used to ensure that this is only created once.
394	once sync.Once
395
396	// The order of pre-singletons
397	preSingletonOrder registeredComponentOrder
398
399	// The order of mutators
400	mutatorOrder registeredComponentOrder
401
402	// The order of singletons
403	singletonOrder registeredComponentOrder
404}
405
406// populate initializes this structure from globally registered build components.
407//
408// Only the first call has any effect.
409func (s *registrationSorter) populate() {
410	s.once.Do(func() {
411		// Create an ordering from the globally registered pre-singletons.
412		s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
413
414		// Created an ordering from the globally registered mutators.
415		globallyRegisteredMutators := collateGloballyRegisteredMutators()
416		s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
417
418		// Create an ordering from the globally registered singletons.
419		globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
420		s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
421	})
422}
423
424// Provides support for enforcing the same order in which build components are registered globally
425// to the order in which they are registered during tests.
426//
427// MUST only be accessed via the globallyRegisteredComponentsOrder func.
428var globalRegistrationSorter registrationSorter
429
430// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
431// correctly populated.
432func globallyRegisteredComponentsOrder() *registrationSorter {
433	globalRegistrationSorter.populate()
434	return &globalRegistrationSorter
435}
436
437func (ctx *TestContext) Register() {
438	globalOrder := globallyRegisteredComponentsOrder()
439
440	// Ensure that the pre-singletons used in the test are in the same order as they are used at
441	// runtime.
442	globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
443	ctx.preSingletons.registerAll(ctx.Context)
444
445	mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
446	// Ensure that the mutators used in the test are in the same order as they are used at runtime.
447	globalOrder.mutatorOrder.enforceOrdering(mutators)
448	mutators.registerAll(ctx.Context)
449
450	// Ensure that the singletons used in the test are in the same order as they are used at runtime.
451	globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
452	ctx.singletons.registerAll(ctx.Context)
453
454	// Save the sorted components order away to make them easy to access while debugging.
455	ctx.preSingletonOrder = componentsToNames(preSingletons)
456	ctx.mutatorOrder = componentsToNames(mutators)
457	ctx.singletonOrder = componentsToNames(singletons)
458}
459
460// RegisterForBazelConversion prepares a test context for bp2build conversion.
461func (ctx *TestContext) RegisterForBazelConversion() {
462	RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
463}
464
465func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
466	// This function adapts the old style ParseFileList calls that are spread throughout the tests
467	// to the new style that takes a config.
468	return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config)
469}
470
471func (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) {
472	// This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the
473	// tests to the new style that takes a config.
474	return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config)
475}
476
477func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
478	ctx.Context.RegisterModuleType(name, ModuleFactoryAdaptor(factory))
479}
480
481func (ctx *TestContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
482	s, m := SingletonModuleFactoryAdaptor(name, factory)
483	ctx.RegisterSingletonType(name, s)
484	ctx.RegisterModuleType(name, m)
485}
486
487func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
488	ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
489}
490
491func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
492	ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
493}
494
495func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
496	var module Module
497	ctx.VisitAllModules(func(m blueprint.Module) {
498		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
499			module = m.(Module)
500		}
501	})
502
503	if module == nil {
504		// find all the modules that do exist
505		var allModuleNames []string
506		var allVariants []string
507		ctx.VisitAllModules(func(m blueprint.Module) {
508			allModuleNames = append(allModuleNames, ctx.ModuleName(m))
509			if ctx.ModuleName(m) == name {
510				allVariants = append(allVariants, ctx.ModuleSubDir(m))
511			}
512		})
513		sort.Strings(allModuleNames)
514		sort.Strings(allVariants)
515
516		if len(allVariants) == 0 {
517			panic(fmt.Errorf("failed to find module %q. All modules:\n  %s",
518				name, strings.Join(allModuleNames, "\n  ")))
519		} else {
520			panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n  %s",
521				name, variant, strings.Join(allVariants, "\n  ")))
522		}
523	}
524
525	return newTestingModule(ctx.config, module)
526}
527
528func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
529	var variants []string
530	ctx.VisitAllModules(func(m blueprint.Module) {
531		if ctx.ModuleName(m) == name {
532			variants = append(variants, ctx.ModuleSubDir(m))
533		}
534	})
535	return variants
536}
537
538// SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
539func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
540	allSingletonNames := []string{}
541	for _, s := range ctx.Singletons() {
542		n := ctx.SingletonName(s)
543		if n == name {
544			return TestingSingleton{
545				baseTestingComponent: newBaseTestingComponent(ctx.config, s.(testBuildProvider)),
546				singleton:            s.(*singletonAdaptor).Singleton,
547			}
548		}
549		allSingletonNames = append(allSingletonNames, n)
550	}
551
552	panic(fmt.Errorf("failed to find singleton %q."+
553		"\nall singletons: %v", name, allSingletonNames))
554}
555
556func (ctx *TestContext) Config() Config {
557	return ctx.config
558}
559
560type testBuildProvider interface {
561	BuildParamsForTests() []BuildParams
562	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
563}
564
565type TestingBuildParams struct {
566	BuildParams
567	RuleParams blueprint.RuleParams
568
569	config Config
570}
571
572// RelativeToTop creates a new instance of this which has had any usages of the current test's
573// temporary and test specific build directory replaced with a path relative to the notional top.
574//
575// The parts of this structure which are changed are:
576// * BuildParams
577//   * Args
578//   * All Path, Paths, WritablePath and WritablePaths fields.
579//
580// * RuleParams
581//   * Command
582//   * Depfile
583//   * Rspfile
584//   * RspfileContent
585//   * SymlinkOutputs
586//   * CommandDeps
587//   * CommandOrderOnly
588//
589// See PathRelativeToTop for more details.
590//
591// deprecated: this is no longer needed as TestingBuildParams are created in this form.
592func (p TestingBuildParams) RelativeToTop() TestingBuildParams {
593	// If this is not a valid params then just return it back. That will make it easy to use with the
594	// Maybe...() methods.
595	if p.Rule == nil {
596		return p
597	}
598	if p.config.config == nil {
599		return p
600	}
601	// Take a copy of the build params and replace any args that contains test specific temporary
602	// paths with paths relative to the top.
603	bparams := p.BuildParams
604	bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile)
605	bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output)
606	bparams.Outputs = bparams.Outputs.RelativeToTop()
607	bparams.SymlinkOutput = normalizeWritablePathRelativeToTop(bparams.SymlinkOutput)
608	bparams.SymlinkOutputs = bparams.SymlinkOutputs.RelativeToTop()
609	bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput)
610	bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop()
611	bparams.Input = normalizePathRelativeToTop(bparams.Input)
612	bparams.Inputs = bparams.Inputs.RelativeToTop()
613	bparams.Implicit = normalizePathRelativeToTop(bparams.Implicit)
614	bparams.Implicits = bparams.Implicits.RelativeToTop()
615	bparams.OrderOnly = bparams.OrderOnly.RelativeToTop()
616	bparams.Validation = normalizePathRelativeToTop(bparams.Validation)
617	bparams.Validations = bparams.Validations.RelativeToTop()
618	bparams.Args = normalizeStringMapRelativeToTop(p.config, bparams.Args)
619
620	// Ditto for any fields in the RuleParams.
621	rparams := p.RuleParams
622	rparams.Command = normalizeStringRelativeToTop(p.config, rparams.Command)
623	rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile)
624	rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile)
625	rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent)
626	rparams.SymlinkOutputs = normalizeStringArrayRelativeToTop(p.config, rparams.SymlinkOutputs)
627	rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps)
628	rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly)
629
630	return TestingBuildParams{
631		BuildParams: bparams,
632		RuleParams:  rparams,
633	}
634}
635
636func normalizeWritablePathRelativeToTop(path WritablePath) WritablePath {
637	if path == nil {
638		return nil
639	}
640	return path.RelativeToTop().(WritablePath)
641}
642
643func normalizePathRelativeToTop(path Path) Path {
644	if path == nil {
645		return nil
646	}
647	return path.RelativeToTop()
648}
649
650// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton.
651type baseTestingComponent struct {
652	config   Config
653	provider testBuildProvider
654}
655
656func newBaseTestingComponent(config Config, provider testBuildProvider) baseTestingComponent {
657	return baseTestingComponent{config, provider}
658}
659
660// A function that will normalize a string containing paths, e.g. ninja command, by replacing
661// any references to the test specific temporary build directory that changes with each run to a
662// fixed path relative to a notional top directory.
663//
664// This is similar to StringPathRelativeToTop except that assumes the string is a single path
665// containing at most one instance of the temporary build directory at the start of the path while
666// this assumes that there can be any number at any position.
667func normalizeStringRelativeToTop(config Config, s string) string {
668	// The buildDir usually looks something like: /tmp/testFoo2345/001
669	//
670	// Replace any usage of the buildDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
671	// "out/soong".
672	outSoongDir := filepath.Clean(config.buildDir)
673	re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`)
674	s = re.ReplaceAllString(s, "out/soong")
675
676	// Replace any usage of the buildDir/.. with out, e.g. replace "/tmp/testFoo2345" with
677	// "out". This must come after the previous replacement otherwise this would replace
678	// "/tmp/testFoo2345/001" with "out/001" instead of "out/soong".
679	outDir := filepath.Dir(outSoongDir)
680	re = regexp.MustCompile(`\Q` + outDir + `\E\b`)
681	s = re.ReplaceAllString(s, "out")
682
683	return s
684}
685
686// normalizeStringArrayRelativeToTop creates a new slice constructed by applying
687// normalizeStringRelativeToTop to each item in the slice.
688func normalizeStringArrayRelativeToTop(config Config, slice []string) []string {
689	newSlice := make([]string, len(slice))
690	for i, s := range slice {
691		newSlice[i] = normalizeStringRelativeToTop(config, s)
692	}
693	return newSlice
694}
695
696// normalizeStringMapRelativeToTop creates a new map constructed by applying
697// normalizeStringRelativeToTop to each value in the map.
698func normalizeStringMapRelativeToTop(config Config, m map[string]string) map[string]string {
699	newMap := map[string]string{}
700	for k, v := range m {
701		newMap[k] = normalizeStringRelativeToTop(config, v)
702	}
703	return newMap
704}
705
706func (b baseTestingComponent) newTestingBuildParams(bparams BuildParams) TestingBuildParams {
707	return TestingBuildParams{
708		config:      b.config,
709		BuildParams: bparams,
710		RuleParams:  b.provider.RuleParamsForTests()[bparams.Rule],
711	}.RelativeToTop()
712}
713
714func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
715	var searchedRules []string
716	buildParams := b.provider.BuildParamsForTests()
717	for _, p := range buildParams {
718		ruleAsString := p.Rule.String()
719		searchedRules = append(searchedRules, ruleAsString)
720		if strings.Contains(ruleAsString, rule) {
721			return b.newTestingBuildParams(p), searchedRules
722		}
723	}
724	return TestingBuildParams{}, searchedRules
725}
726
727func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
728	p, searchRules := b.maybeBuildParamsFromRule(rule)
729	if p.Rule == nil {
730		panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
731	}
732	return p
733}
734
735func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) TestingBuildParams {
736	for _, p := range b.provider.BuildParamsForTests() {
737		if strings.Contains(p.Description, desc) {
738			return b.newTestingBuildParams(p)
739		}
740	}
741	return TestingBuildParams{}
742}
743
744func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
745	p := b.maybeBuildParamsFromDescription(desc)
746	if p.Rule == nil {
747		panic(fmt.Errorf("couldn't find description %q", desc))
748	}
749	return p
750}
751
752func (b baseTestingComponent) maybeBuildParamsFromOutput(file string) (TestingBuildParams, []string) {
753	var searchedOutputs []string
754	for _, p := range b.provider.BuildParamsForTests() {
755		outputs := append(WritablePaths(nil), p.Outputs...)
756		outputs = append(outputs, p.ImplicitOutputs...)
757		if p.Output != nil {
758			outputs = append(outputs, p.Output)
759		}
760		for _, f := range outputs {
761			if f.String() == file || f.Rel() == file || PathRelativeToTop(f) == file {
762				return b.newTestingBuildParams(p), nil
763			}
764			searchedOutputs = append(searchedOutputs, f.Rel())
765		}
766	}
767	return TestingBuildParams{}, searchedOutputs
768}
769
770func (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams {
771	p, searchedOutputs := b.maybeBuildParamsFromOutput(file)
772	if p.Rule == nil {
773		panic(fmt.Errorf("couldn't find output %q.\nall outputs:\n    %s\n",
774			file, strings.Join(searchedOutputs, "\n    ")))
775	}
776	return p
777}
778
779func (b baseTestingComponent) allOutputs() []string {
780	var outputFullPaths []string
781	for _, p := range b.provider.BuildParamsForTests() {
782		outputs := append(WritablePaths(nil), p.Outputs...)
783		outputs = append(outputs, p.ImplicitOutputs...)
784		if p.Output != nil {
785			outputs = append(outputs, p.Output)
786		}
787		outputFullPaths = append(outputFullPaths, outputs.Strings()...)
788	}
789	return outputFullPaths
790}
791
792// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Returns an empty
793// BuildParams if no rule is found.
794func (b baseTestingComponent) MaybeRule(rule string) TestingBuildParams {
795	r, _ := b.maybeBuildParamsFromRule(rule)
796	return r
797}
798
799// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Panics if no rule is found.
800func (b baseTestingComponent) Rule(rule string) TestingBuildParams {
801	return b.buildParamsFromRule(rule)
802}
803
804// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string.  Returns an empty
805// BuildParams if no rule is found.
806func (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams {
807	return b.maybeBuildParamsFromDescription(desc)
808}
809
810// Description finds a call to ctx.Build with BuildParams.Description set to a the given string.  Panics if no rule is
811// found.
812func (b baseTestingComponent) Description(desc string) TestingBuildParams {
813	return b.buildParamsFromDescription(desc)
814}
815
816// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
817// value matches the provided string.  Returns an empty BuildParams if no rule is found.
818func (b baseTestingComponent) MaybeOutput(file string) TestingBuildParams {
819	p, _ := b.maybeBuildParamsFromOutput(file)
820	return p
821}
822
823// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
824// value matches the provided string.  Panics if no rule is found.
825func (b baseTestingComponent) Output(file string) TestingBuildParams {
826	return b.buildParamsFromOutput(file)
827}
828
829// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
830func (b baseTestingComponent) AllOutputs() []string {
831	return b.allOutputs()
832}
833
834// TestingModule is wrapper around an android.Module that provides methods to find information about individual
835// ctx.Build parameters for verification in tests.
836type TestingModule struct {
837	baseTestingComponent
838	module Module
839}
840
841func newTestingModule(config Config, module Module) TestingModule {
842	return TestingModule{
843		newBaseTestingComponent(config, module),
844		module,
845	}
846}
847
848// Module returns the Module wrapped by the TestingModule.
849func (m TestingModule) Module() Module {
850	return m.module
851}
852
853// VariablesForTestsRelativeToTop returns a copy of the Module.VariablesForTests() with every value
854// having any temporary build dir usages replaced with paths relative to a notional top.
855func (m TestingModule) VariablesForTestsRelativeToTop() map[string]string {
856	return normalizeStringMapRelativeToTop(m.config, m.module.VariablesForTests())
857}
858
859// OutputFiles calls OutputFileProducer.OutputFiles on the encapsulated module, exits the test
860// immediately if there is an error and otherwise returns the result of calling Paths.RelativeToTop
861// on the returned Paths.
862func (m TestingModule) OutputFiles(t *testing.T, tag string) Paths {
863	producer, ok := m.module.(OutputFileProducer)
864	if !ok {
865		t.Fatalf("%q must implement OutputFileProducer\n", m.module.Name())
866	}
867	paths, err := producer.OutputFiles(tag)
868	if err != nil {
869		t.Fatal(err)
870	}
871
872	return paths.RelativeToTop()
873}
874
875// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
876// ctx.Build parameters for verification in tests.
877type TestingSingleton struct {
878	baseTestingComponent
879	singleton Singleton
880}
881
882// Singleton returns the Singleton wrapped by the TestingSingleton.
883func (s TestingSingleton) Singleton() Singleton {
884	return s.singleton
885}
886
887func FailIfErrored(t *testing.T, errs []error) {
888	t.Helper()
889	if len(errs) > 0 {
890		for _, err := range errs {
891			t.Error(err)
892		}
893		t.FailNow()
894	}
895}
896
897// Fail if no errors that matched the regular expression were found.
898//
899// Returns true if a matching error was found, false otherwise.
900func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool {
901	t.Helper()
902
903	matcher, err := regexp.Compile(pattern)
904	if err != nil {
905		t.Fatalf("failed to compile regular expression %q because %s", pattern, err)
906	}
907
908	found := false
909	for _, err := range errs {
910		if matcher.FindStringIndex(err.Error()) != nil {
911			found = true
912			break
913		}
914	}
915	if !found {
916		t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
917		for i, err := range errs {
918			t.Errorf("errs[%d] = %q", i, err)
919		}
920	}
921
922	return found
923}
924
925func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
926	t.Helper()
927
928	if expectedErrorPatterns == nil {
929		FailIfErrored(t, errs)
930	} else {
931		for _, expectedError := range expectedErrorPatterns {
932			FailIfNoMatchingErrors(t, expectedError, errs)
933		}
934		if len(errs) > len(expectedErrorPatterns) {
935			t.Errorf("additional errors found, expected %d, found %d",
936				len(expectedErrorPatterns), len(errs))
937			for i, expectedError := range expectedErrorPatterns {
938				t.Errorf("expectedErrors[%d] = %s", i, expectedError)
939			}
940			for i, err := range errs {
941				t.Errorf("errs[%d] = %s", i, err)
942			}
943			t.FailNow()
944		}
945	}
946}
947
948func SetKatiEnabledForTests(config Config) {
949	config.katiEnabled = true
950}
951
952func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
953	var p AndroidMkEntriesProvider
954	var ok bool
955	if p, ok = mod.(AndroidMkEntriesProvider); !ok {
956		t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
957	}
958
959	entriesList := p.AndroidMkEntries()
960	for i, _ := range entriesList {
961		entriesList[i].fillInEntries(ctx, mod)
962	}
963	return entriesList
964}
965
966func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
967	var p AndroidMkDataProvider
968	var ok bool
969	if p, ok = mod.(AndroidMkDataProvider); !ok {
970		t.Errorf("module does not implement AndroidMkDataProvider: " + mod.Name())
971	}
972	data := p.AndroidMk()
973	data.fillInData(ctx, mod)
974	return data
975}
976
977// Normalize the path for testing.
978//
979// If the path is relative to the build directory then return the relative path
980// to avoid tests having to deal with the dynamically generated build directory.
981//
982// Otherwise, return the supplied path as it is almost certainly a source path
983// that is relative to the root of the source tree.
984//
985// The build and source paths should be distinguishable based on their contents.
986//
987// deprecated: use PathRelativeToTop instead as it handles make install paths and differentiates
988// between output and source properly.
989func NormalizePathForTesting(path Path) string {
990	if path == nil {
991		return "<nil path>"
992	}
993	p := path.String()
994	if w, ok := path.(WritablePath); ok {
995		rel, err := filepath.Rel(w.getBuildDir(), p)
996		if err != nil {
997			panic(err)
998		}
999		return rel
1000	}
1001	return p
1002}
1003
1004// NormalizePathsForTesting creates a slice of strings where each string is the result of applying
1005// NormalizePathForTesting to the corresponding Path in the input slice.
1006//
1007// deprecated: use PathsRelativeToTop instead as it handles make install paths and differentiates
1008// between output and source properly.
1009func NormalizePathsForTesting(paths Paths) []string {
1010	var result []string
1011	for _, path := range paths {
1012		relative := NormalizePathForTesting(path)
1013		result = append(result, relative)
1014	}
1015	return result
1016}
1017
1018// PathRelativeToTop returns a string representation of the path relative to a notional top
1019// directory.
1020//
1021// It return "<nil path>" if the supplied path is nil, otherwise it returns the result of calling
1022// Path.RelativeToTop to obtain a relative Path and then calling Path.String on that to get the
1023// string representation.
1024func PathRelativeToTop(path Path) string {
1025	if path == nil {
1026		return "<nil path>"
1027	}
1028	return path.RelativeToTop().String()
1029}
1030
1031// PathsRelativeToTop creates a slice of strings where each string is the result of applying
1032// PathRelativeToTop to the corresponding Path in the input slice.
1033func PathsRelativeToTop(paths Paths) []string {
1034	var result []string
1035	for _, path := range paths {
1036		relative := PathRelativeToTop(path)
1037		result = append(result, relative)
1038	}
1039	return result
1040}
1041
1042// StringPathRelativeToTop returns a string representation of the path relative to a notional top
1043// directory.
1044//
1045// See Path.RelativeToTop for more details as to what `relative to top` means.
1046//
1047// This is provided for processing paths that have already been converted into a string, e.g. paths
1048// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
1049// which it can try and relativize paths. PathRelativeToTop must be used for process Path objects.
1050func StringPathRelativeToTop(soongOutDir string, path string) string {
1051	ensureTestOnly()
1052
1053	// A relative path must be a source path so leave it as it is.
1054	if !filepath.IsAbs(path) {
1055		return path
1056	}
1057
1058	// Check to see if the path is relative to the soong out dir.
1059	rel, isRel, err := maybeRelErr(soongOutDir, path)
1060	if err != nil {
1061		panic(err)
1062	}
1063
1064	if isRel {
1065		// The path is in the soong out dir so indicate that in the relative path.
1066		return filepath.Join("out/soong", rel)
1067	}
1068
1069	// Check to see if the path is relative to the top level out dir.
1070	outDir := filepath.Dir(soongOutDir)
1071	rel, isRel, err = maybeRelErr(outDir, path)
1072	if err != nil {
1073		panic(err)
1074	}
1075
1076	if isRel {
1077		// The path is in the out dir so indicate that in the relative path.
1078		return filepath.Join("out", rel)
1079	}
1080
1081	// This should never happen.
1082	panic(fmt.Errorf("internal error: absolute path %s is not relative to the out dir %s", path, outDir))
1083}
1084
1085// StringPathsRelativeToTop creates a slice of strings where each string is the result of applying
1086// StringPathRelativeToTop to the corresponding string path in the input slice.
1087//
1088// This is provided for processing paths that have already been converted into a string, e.g. paths
1089// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
1090// which it can try and relativize paths. PathsRelativeToTop must be used for process Paths objects.
1091func StringPathsRelativeToTop(soongOutDir string, paths []string) []string {
1092	var result []string
1093	for _, path := range paths {
1094		relative := StringPathRelativeToTop(soongOutDir, path)
1095		result = append(result, relative)
1096	}
1097	return result
1098}
1099
1100// StringRelativeToTop will normalize a string containing paths, e.g. ninja command, by replacing
1101// any references to the test specific temporary build directory that changes with each run to a
1102// fixed path relative to a notional top directory.
1103//
1104// This is similar to StringPathRelativeToTop except that assumes the string is a single path
1105// containing at most one instance of the temporary build directory at the start of the path while
1106// this assumes that there can be any number at any position.
1107func StringRelativeToTop(config Config, command string) string {
1108	return normalizeStringRelativeToTop(config, command)
1109}
1110
1111// StringsRelativeToTop will return a new slice such that each item in the new slice is the result
1112// of calling StringRelativeToTop on the corresponding item in the input slice.
1113func StringsRelativeToTop(config Config, command []string) []string {
1114	return normalizeStringArrayRelativeToTop(config, command)
1115}
1116