2017-07-14 05:43:27 +08:00
|
|
|
// Copyright 2017 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package android
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-12-10 21:41:51 +08:00
|
|
|
"path/filepath"
|
2018-03-12 16:34:26 +08:00
|
|
|
"regexp"
|
2020-05-13 08:13:50 +08:00
|
|
|
"sort"
|
2017-07-14 05:43:27 +08:00
|
|
|
"strings"
|
2021-03-07 04:29:19 +08:00
|
|
|
"sync"
|
2018-03-12 16:29:17 +08:00
|
|
|
"testing"
|
2017-07-14 05:43:27 +08:00
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
2021-03-07 23:45:56 +08:00
|
|
|
"github.com/google/blueprint/proptools"
|
2017-07-14 05:43:27 +08:00
|
|
|
)
|
|
|
|
|
2020-10-30 08:09:13 +08:00
|
|
|
func NewTestContext(config Config) *TestContext {
|
2017-11-30 08:47:17 +08:00
|
|
|
namespaceExportFilter := func(namespace *Namespace) bool {
|
|
|
|
return true
|
|
|
|
}
|
2017-12-02 09:10:33 +08:00
|
|
|
|
|
|
|
nameResolver := NewNameResolver(namespaceExportFilter)
|
|
|
|
ctx := &TestContext{
|
2020-10-30 08:09:13 +08:00
|
|
|
Context: &Context{blueprint.NewContext(), config},
|
2017-12-02 09:10:33 +08:00
|
|
|
NameResolver: nameResolver,
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.SetNameInterface(nameResolver)
|
2017-11-30 08:47:17 +08:00
|
|
|
|
2019-03-05 14:33:56 +08:00
|
|
|
ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
|
|
|
|
|
2020-10-30 08:09:13 +08:00
|
|
|
ctx.SetFs(ctx.config.fs)
|
|
|
|
if ctx.config.mockBpList != "" {
|
|
|
|
ctx.SetModuleListFile(ctx.config.mockBpList)
|
|
|
|
}
|
|
|
|
|
2017-11-30 08:47:17 +08:00
|
|
|
return ctx
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
2021-02-28 09:38:51 +08:00
|
|
|
var PrepareForTestWithArchMutator = GroupFixturePreparers(
|
2021-02-24 09:49:52 +08:00
|
|
|
// Configure architecture targets in the fixture config.
|
|
|
|
FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
|
|
|
|
|
|
|
|
// Add the arch mutator to the context.
|
|
|
|
FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
|
|
|
ctx.PreDepsMutators(registerArchMutator)
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
|
|
|
|
var PrepareForTestWithDefaults = FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
|
|
|
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
|
|
|
|
})
|
|
|
|
|
|
|
|
var PrepareForTestWithComponentsMutator = FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
|
|
|
ctx.PreArchMutators(RegisterComponentsMutator)
|
|
|
|
})
|
|
|
|
|
|
|
|
var PrepareForTestWithPrebuilts = FixtureRegisterWithContext(RegisterPrebuiltMutators)
|
|
|
|
|
|
|
|
var PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
|
|
|
ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
|
|
|
|
})
|
|
|
|
|
2021-03-09 09:01:31 +08:00
|
|
|
// Test fixture preparer that will register most java build components.
|
|
|
|
//
|
|
|
|
// Singletons and mutators should only be added here if they are needed for a majority of java
|
|
|
|
// module types, otherwise they should be added under a separate preparer to allow them to be
|
|
|
|
// selected only when needed to reduce test execution time.
|
|
|
|
//
|
|
|
|
// Module types do not have much of an overhead unless they are used so this should include as many
|
|
|
|
// module types as possible. The exceptions are those module types that require mutators and/or
|
|
|
|
// singletons in order to function in which case they should be kept together in a separate
|
|
|
|
// preparer.
|
|
|
|
//
|
|
|
|
// The mutators in this group were chosen because they are needed by the vast majority of tests.
|
|
|
|
var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
|
2021-03-07 21:20:38 +08:00
|
|
|
// Sorted alphabetically as the actual order does not matter as tests automatically enforce the
|
|
|
|
// correct order.
|
2021-02-24 09:49:52 +08:00
|
|
|
PrepareForTestWithArchMutator,
|
|
|
|
PrepareForTestWithComponentsMutator,
|
2021-03-07 21:20:38 +08:00
|
|
|
PrepareForTestWithDefaults,
|
2021-02-24 09:49:52 +08:00
|
|
|
PrepareForTestWithFilegroup,
|
2021-03-07 21:20:38 +08:00
|
|
|
PrepareForTestWithOverrides,
|
|
|
|
PrepareForTestWithPackageModule,
|
|
|
|
PrepareForTestWithPrebuilts,
|
|
|
|
PrepareForTestWithVisibility,
|
2021-02-24 09:49:52 +08:00
|
|
|
)
|
|
|
|
|
2021-03-09 09:01:31 +08:00
|
|
|
// Prepares an integration test with all build components from the android package.
|
|
|
|
//
|
|
|
|
// This should only be used by tests that want to run with as much of the build enabled as possible.
|
|
|
|
var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
|
|
|
|
PrepareForTestWithAndroidBuildComponents,
|
|
|
|
)
|
|
|
|
|
2021-03-07 23:45:56 +08:00
|
|
|
// Prepares a test that may be missing dependencies by setting allow_missing_dependencies to
|
|
|
|
// true.
|
|
|
|
var PrepareForTestWithAllowMissingDependencies = GroupFixturePreparers(
|
|
|
|
FixtureModifyProductVariables(func(variables FixtureProductVariables) {
|
|
|
|
variables.Allow_missing_dependencies = proptools.BoolPtr(true)
|
|
|
|
}),
|
|
|
|
FixtureModifyContext(func(ctx *TestContext) {
|
|
|
|
ctx.SetAllowMissingDependencies(true)
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
|
2020-10-30 08:09:13 +08:00
|
|
|
func NewTestArchContext(config Config) *TestContext {
|
|
|
|
ctx := NewTestContext(config)
|
2017-09-16 08:33:55 +08:00
|
|
|
ctx.preDeps = append(ctx.preDeps, registerArchMutator)
|
|
|
|
return ctx
|
|
|
|
}
|
|
|
|
|
2017-07-14 05:43:27 +08:00
|
|
|
type TestContext struct {
|
2019-02-26 06:54:28 +08:00
|
|
|
*Context
|
2021-01-26 22:18:53 +08:00
|
|
|
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
|
|
|
|
bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
|
|
|
|
NameResolver *NameResolver
|
2021-03-07 04:29:19 +08:00
|
|
|
|
2021-03-07 20:24:44 +08:00
|
|
|
// The list of pre-singletons and singletons registered for the test.
|
|
|
|
preSingletons, singletons sortableComponents
|
|
|
|
|
2021-03-07 20:23:48 +08:00
|
|
|
// The order in which the pre-singletons, mutators and singletons will be run in this test
|
|
|
|
// context; for debugging.
|
|
|
|
preSingletonOrder, mutatorOrder, singletonOrder []string
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.preArch = append(ctx.preArch, f)
|
|
|
|
}
|
|
|
|
|
2020-01-14 20:09:36 +08:00
|
|
|
func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
|
|
|
|
// Register mutator function as normal for testing.
|
|
|
|
ctx.PreArchMutators(f)
|
|
|
|
}
|
|
|
|
|
2017-07-14 05:43:27 +08:00
|
|
|
func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.preDeps = append(ctx.preDeps, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.postDeps = append(ctx.postDeps, f)
|
|
|
|
}
|
|
|
|
|
2020-01-16 23:12:04 +08:00
|
|
|
func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.finalDeps = append(ctx.finalDeps, f)
|
|
|
|
}
|
|
|
|
|
2020-12-14 21:25:34 +08:00
|
|
|
// RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
|
|
|
|
// type to the equivalent Bazel target.
|
|
|
|
func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
|
|
|
|
f := func(ctx RegisterMutatorsContext) {
|
2021-01-26 22:18:53 +08:00
|
|
|
ctx.TopDown(moduleType, m)
|
2020-12-14 21:25:34 +08:00
|
|
|
}
|
2021-01-27 10:57:27 +08:00
|
|
|
ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
|
2020-12-14 21:25:34 +08:00
|
|
|
}
|
|
|
|
|
2021-01-26 22:18:53 +08:00
|
|
|
// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
|
|
|
|
// into Bazel BUILD targets that should run prior to deps and conversion.
|
|
|
|
func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
|
|
|
|
// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
|
|
|
|
func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
|
|
|
|
ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
|
|
|
|
}
|
|
|
|
|
2021-03-07 04:29:19 +08:00
|
|
|
// registeredComponentOrder defines the order in which a sortableComponent type is registered at
|
|
|
|
// runtime and provides support for reordering the components registered for a test in the same
|
|
|
|
// way.
|
|
|
|
type registeredComponentOrder struct {
|
|
|
|
// The name of the component type, used for error messages.
|
|
|
|
componentType string
|
|
|
|
|
|
|
|
// The names of the registered components in the order in which they were registered.
|
|
|
|
namesInOrder []string
|
|
|
|
|
|
|
|
// Maps from the component name to its position in the runtime ordering.
|
|
|
|
namesToIndex map[string]int
|
|
|
|
|
|
|
|
// A function that defines the order between two named components that can be used to sort a slice
|
|
|
|
// of component names into the same order as they appear in namesInOrder.
|
|
|
|
less func(string, string) bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
|
|
|
|
// creates a registeredComponentOrder that contains a less function that can be used to sort a
|
|
|
|
// subset of that list of names so it is in the same order as the original sortableComponents.
|
|
|
|
func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
|
|
|
|
// Only the names from the existing order are needed for this so create a list of component names
|
|
|
|
// in the correct order.
|
|
|
|
namesInOrder := componentsToNames(existingOrder)
|
|
|
|
|
|
|
|
// Populate the map from name to position in the list.
|
|
|
|
nameToIndex := make(map[string]int)
|
|
|
|
for i, n := range namesInOrder {
|
|
|
|
nameToIndex[n] = i
|
|
|
|
}
|
|
|
|
|
|
|
|
// A function to use to map from a name to an index in the original order.
|
|
|
|
indexOf := func(name string) int {
|
|
|
|
index, ok := nameToIndex[name]
|
|
|
|
if !ok {
|
|
|
|
// Should never happen as tests that use components that are not known at runtime do not sort
|
|
|
|
// so should never use this function.
|
|
|
|
panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
|
|
|
|
}
|
|
|
|
return index
|
|
|
|
}
|
|
|
|
|
|
|
|
// The less function.
|
|
|
|
less := func(n1, n2 string) bool {
|
|
|
|
i1 := indexOf(n1)
|
|
|
|
i2 := indexOf(n2)
|
|
|
|
return i1 < i2
|
|
|
|
}
|
|
|
|
|
|
|
|
return registeredComponentOrder{
|
|
|
|
componentType: componentType,
|
|
|
|
namesInOrder: namesInOrder,
|
|
|
|
namesToIndex: nameToIndex,
|
|
|
|
less: less,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// componentsToNames maps from the slice of components to a slice of their names.
|
|
|
|
func componentsToNames(components sortableComponents) []string {
|
|
|
|
names := make([]string, len(components))
|
|
|
|
for i, c := range components {
|
|
|
|
names[i] = c.componentName()
|
|
|
|
}
|
|
|
|
return names
|
|
|
|
}
|
|
|
|
|
|
|
|
// enforceOrdering enforces the supplied components are in the same order as is defined in this
|
|
|
|
// object.
|
|
|
|
//
|
|
|
|
// If the supplied components contains any components that are not registered at runtime, i.e. test
|
|
|
|
// specific components, then it is impossible to sort them into an order that both matches the
|
|
|
|
// runtime and also preserves the implicit ordering defined in the test. In that case it will not
|
|
|
|
// sort the components, instead it will just check that the components are in the correct order.
|
|
|
|
//
|
|
|
|
// Otherwise, this will sort the supplied components in place.
|
|
|
|
func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
|
|
|
|
// Check to see if the list of components contains any components that are
|
|
|
|
// not registered at runtime.
|
|
|
|
var unknownComponents []string
|
|
|
|
testOrder := componentsToNames(components)
|
|
|
|
for _, name := range testOrder {
|
|
|
|
if _, ok := o.namesToIndex[name]; !ok {
|
|
|
|
unknownComponents = append(unknownComponents, name)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the slice contains some unknown components then it is not possible to
|
|
|
|
// sort them into an order that matches the runtime while also preserving the
|
|
|
|
// order expected from the test, so in that case don't sort just check that
|
|
|
|
// the order of the known mutators does match.
|
|
|
|
if len(unknownComponents) > 0 {
|
|
|
|
// Check order.
|
|
|
|
o.checkTestOrder(testOrder, unknownComponents)
|
|
|
|
} else {
|
|
|
|
// Sort the components.
|
|
|
|
sort.Slice(components, func(i, j int) bool {
|
|
|
|
n1 := components[i].componentName()
|
|
|
|
n2 := components[j].componentName()
|
|
|
|
return o.less(n1, n2)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
|
|
|
|
// panicking if it does not.
|
|
|
|
func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
|
|
|
|
lastMatchingTest := -1
|
|
|
|
matchCount := 0
|
|
|
|
// Take a copy of the runtime order as it is modified during the comparison.
|
|
|
|
runtimeOrder := append([]string(nil), o.namesInOrder...)
|
|
|
|
componentType := o.componentType
|
|
|
|
for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
|
|
|
|
test := testOrder[i]
|
|
|
|
runtime := runtimeOrder[j]
|
|
|
|
|
|
|
|
if test == runtime {
|
|
|
|
testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
|
|
|
|
runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
|
|
|
|
lastMatchingTest = i
|
|
|
|
i += 1
|
|
|
|
j += 1
|
|
|
|
matchCount += 1
|
|
|
|
} else if _, ok := o.namesToIndex[test]; !ok {
|
|
|
|
// The test component is not registered globally so assume it is the correct place, treat it
|
|
|
|
// as having matched and skip it.
|
|
|
|
i += 1
|
|
|
|
matchCount += 1
|
|
|
|
} else {
|
|
|
|
// Assume that the test list is in the same order as the runtime list but the runtime list
|
|
|
|
// contains some components that are not present in the tests. So, skip the runtime component
|
|
|
|
// to try and find the next one that matches the current test component.
|
|
|
|
j += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If every item in the test order was either test specific or matched one in the runtime then
|
|
|
|
// it is in the correct order. Otherwise, it was not so fail.
|
|
|
|
if matchCount != len(testOrder) {
|
|
|
|
// The test component names were not all matched with a runtime component name so there must
|
|
|
|
// either be a component present in the test that is not present in the runtime or they must be
|
|
|
|
// in the wrong order.
|
|
|
|
testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
|
|
|
|
panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
|
|
|
|
" Unfortunately it uses %s components in the wrong order.\n"+
|
|
|
|
"test order:\n %s\n"+
|
|
|
|
"runtime order\n %s\n",
|
|
|
|
SortedUniqueStrings(unknownComponents),
|
|
|
|
componentType,
|
|
|
|
strings.Join(testOrder, "\n "),
|
|
|
|
strings.Join(runtimeOrder, "\n ")))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// registrationSorter encapsulates the information needed to ensure that the test mutators are
|
|
|
|
// registered, and thereby executed, in the same order as they are at runtime.
|
|
|
|
//
|
|
|
|
// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
|
|
|
|
// only define the order for a subset of all the registered build components that are available for
|
|
|
|
// the packages being tested.
|
|
|
|
//
|
|
|
|
// e.g if this is initialized during say the cc package initialization then any tests run in the
|
|
|
|
// java package will not sort build components registered by the java package's init() functions.
|
|
|
|
type registrationSorter struct {
|
|
|
|
// Used to ensure that this is only created once.
|
|
|
|
once sync.Once
|
|
|
|
|
2021-03-07 20:23:48 +08:00
|
|
|
// The order of pre-singletons
|
|
|
|
preSingletonOrder registeredComponentOrder
|
|
|
|
|
2021-03-07 04:29:19 +08:00
|
|
|
// The order of mutators
|
|
|
|
mutatorOrder registeredComponentOrder
|
2021-03-07 20:23:48 +08:00
|
|
|
|
|
|
|
// The order of singletons
|
|
|
|
singletonOrder registeredComponentOrder
|
2021-03-07 04:29:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// populate initializes this structure from globally registered build components.
|
|
|
|
//
|
|
|
|
// Only the first call has any effect.
|
|
|
|
func (s *registrationSorter) populate() {
|
|
|
|
s.once.Do(func() {
|
2021-03-07 20:23:48 +08:00
|
|
|
// Create an ordering from the globally registered pre-singletons.
|
|
|
|
s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
|
|
|
|
|
2021-03-07 04:29:19 +08:00
|
|
|
// Created an ordering from the globally registered mutators.
|
|
|
|
globallyRegisteredMutators := collateGloballyRegisteredMutators()
|
|
|
|
s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
|
2021-03-07 20:23:48 +08:00
|
|
|
|
|
|
|
// Create an ordering from the globally registered singletons.
|
|
|
|
globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
|
|
|
|
s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
|
2021-03-07 04:29:19 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Provides support for enforcing the same order in which build components are registered globally
|
|
|
|
// to the order in which they are registered during tests.
|
|
|
|
//
|
|
|
|
// MUST only be accessed via the globallyRegisteredComponentsOrder func.
|
|
|
|
var globalRegistrationSorter registrationSorter
|
|
|
|
|
|
|
|
// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
|
|
|
|
// correctly populated.
|
|
|
|
func globallyRegisteredComponentsOrder() *registrationSorter {
|
|
|
|
globalRegistrationSorter.populate()
|
|
|
|
return &globalRegistrationSorter
|
|
|
|
}
|
|
|
|
|
2020-10-30 08:09:13 +08:00
|
|
|
func (ctx *TestContext) Register() {
|
2021-03-07 04:29:19 +08:00
|
|
|
globalOrder := globallyRegisteredComponentsOrder()
|
|
|
|
|
2021-03-07 20:23:48 +08:00
|
|
|
// Ensure that the pre-singletons used in the test are in the same order as they are used at
|
|
|
|
// runtime.
|
|
|
|
globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
|
2021-03-07 20:24:44 +08:00
|
|
|
ctx.preSingletons.registerAll(ctx.Context)
|
|
|
|
|
2021-03-06 21:28:13 +08:00
|
|
|
mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
|
2021-03-07 04:29:19 +08:00
|
|
|
// Ensure that the mutators used in the test are in the same order as they are used at runtime.
|
|
|
|
globalOrder.mutatorOrder.enforceOrdering(mutators)
|
2021-03-06 21:28:13 +08:00
|
|
|
mutators.registerAll(ctx.Context)
|
2017-07-14 05:43:27 +08:00
|
|
|
|
2021-03-07 20:24:44 +08:00
|
|
|
// Register the env singleton with this context before sorting.
|
2019-11-23 07:25:03 +08:00
|
|
|
ctx.RegisterSingletonType("env", EnvSingleton)
|
2021-03-07 04:29:19 +08:00
|
|
|
|
2021-03-07 20:23:48 +08:00
|
|
|
// Ensure that the singletons used in the test are in the same order as they are used at runtime.
|
|
|
|
globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
|
2021-03-07 20:24:44 +08:00
|
|
|
ctx.singletons.registerAll(ctx.Context)
|
|
|
|
|
2021-03-07 20:23:48 +08:00
|
|
|
// Save the sorted components order away to make them easy to access while debugging.
|
2021-03-09 07:42:10 +08:00
|
|
|
ctx.preSingletonOrder = componentsToNames(preSingletons)
|
|
|
|
ctx.mutatorOrder = componentsToNames(mutators)
|
|
|
|
ctx.singletonOrder = componentsToNames(singletons)
|
2019-12-31 10:45:15 +08:00
|
|
|
}
|
|
|
|
|
2020-12-14 21:25:34 +08:00
|
|
|
// RegisterForBazelConversion prepares a test context for bp2build conversion.
|
|
|
|
func (ctx *TestContext) RegisterForBazelConversion() {
|
2021-03-07 04:08:12 +08:00
|
|
|
RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
|
2020-12-14 21:25:34 +08:00
|
|
|
}
|
|
|
|
|
2019-12-31 10:45:15 +08:00
|
|
|
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
|
|
|
|
// This function adapts the old style ParseFileList calls that are spread throughout the tests
|
|
|
|
// to the new style that takes a config.
|
|
|
|
return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) {
|
|
|
|
// This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the
|
|
|
|
// tests to the new style that takes a config.
|
|
|
|
return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config)
|
2019-11-23 07:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
|
|
|
|
ctx.Context.RegisterModuleType(name, ModuleFactoryAdaptor(factory))
|
|
|
|
}
|
|
|
|
|
2020-12-29 07:15:34 +08:00
|
|
|
func (ctx *TestContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
|
|
|
|
s, m := SingletonModuleFactoryAdaptor(name, factory)
|
|
|
|
ctx.RegisterSingletonType(name, s)
|
|
|
|
ctx.RegisterModuleType(name, m)
|
|
|
|
}
|
|
|
|
|
2019-11-23 07:25:03 +08:00
|
|
|
func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
|
2021-03-07 20:24:44 +08:00
|
|
|
ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
2021-02-24 09:43:18 +08:00
|
|
|
func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
|
2021-03-07 20:24:44 +08:00
|
|
|
ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
|
2021-02-24 09:43:18 +08:00
|
|
|
}
|
|
|
|
|
2017-07-14 05:43:27 +08:00
|
|
|
func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
|
|
|
|
var module Module
|
|
|
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
|
|
|
if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
|
|
|
|
module = m.(Module)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if module == nil {
|
2017-09-28 08:05:30 +08:00
|
|
|
// find all the modules that do exist
|
2020-08-12 03:02:11 +08:00
|
|
|
var allModuleNames []string
|
|
|
|
var allVariants []string
|
2017-09-28 08:05:30 +08:00
|
|
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
2020-08-12 03:02:11 +08:00
|
|
|
allModuleNames = append(allModuleNames, ctx.ModuleName(m))
|
|
|
|
if ctx.ModuleName(m) == name {
|
|
|
|
allVariants = append(allVariants, ctx.ModuleSubDir(m))
|
|
|
|
}
|
2017-09-28 08:05:30 +08:00
|
|
|
})
|
2020-05-13 08:13:50 +08:00
|
|
|
sort.Strings(allModuleNames)
|
2020-08-12 03:02:11 +08:00
|
|
|
sort.Strings(allVariants)
|
|
|
|
|
|
|
|
if len(allVariants) == 0 {
|
|
|
|
panic(fmt.Errorf("failed to find module %q. All modules:\n %s",
|
|
|
|
name, strings.Join(allModuleNames, "\n ")))
|
|
|
|
} else {
|
|
|
|
panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n %s",
|
|
|
|
name, variant, strings.Join(allVariants, "\n ")))
|
|
|
|
}
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return TestingModule{module}
|
|
|
|
}
|
|
|
|
|
2018-07-11 09:49:27 +08:00
|
|
|
func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
|
|
|
|
var variants []string
|
|
|
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
|
|
|
if ctx.ModuleName(m) == name {
|
|
|
|
variants = append(variants, ctx.ModuleSubDir(m))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return variants
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
// SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
|
|
|
|
func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
|
|
|
|
allSingletonNames := []string{}
|
|
|
|
for _, s := range ctx.Singletons() {
|
|
|
|
n := ctx.SingletonName(s)
|
|
|
|
if n == name {
|
|
|
|
return TestingSingleton{
|
|
|
|
singleton: s.(*singletonAdaptor).Singleton,
|
|
|
|
provider: s.(testBuildProvider),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allSingletonNames = append(allSingletonNames, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
panic(fmt.Errorf("failed to find singleton %q."+
|
|
|
|
"\nall singletons: %v", name, allSingletonNames))
|
|
|
|
}
|
|
|
|
|
2020-07-04 04:18:24 +08:00
|
|
|
func (ctx *TestContext) Config() Config {
|
|
|
|
return ctx.config
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
type testBuildProvider interface {
|
|
|
|
BuildParamsForTests() []BuildParams
|
|
|
|
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
type TestingBuildParams struct {
|
|
|
|
BuildParams
|
|
|
|
RuleParams blueprint.RuleParams
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func newTestingBuildParams(provider testBuildProvider, bparams BuildParams) TestingBuildParams {
|
|
|
|
return TestingBuildParams{
|
|
|
|
BuildParams: bparams,
|
|
|
|
RuleParams: provider.RuleParamsForTests()[bparams.Rule],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-27 21:50:24 +08:00
|
|
|
func maybeBuildParamsFromRule(provider testBuildProvider, rule string) (TestingBuildParams, []string) {
|
|
|
|
var searchedRules []string
|
2019-02-26 06:54:28 +08:00
|
|
|
for _, p := range provider.BuildParamsForTests() {
|
2020-08-27 21:50:24 +08:00
|
|
|
searchedRules = append(searchedRules, p.Rule.String())
|
2017-07-14 05:43:27 +08:00
|
|
|
if strings.Contains(p.Rule.String(), rule) {
|
2020-08-27 21:50:24 +08:00
|
|
|
return newTestingBuildParams(provider, p), searchedRules
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
}
|
2020-08-27 21:50:24 +08:00
|
|
|
return TestingBuildParams{}, searchedRules
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
|
2020-08-27 21:50:24 +08:00
|
|
|
p, searchRules := maybeBuildParamsFromRule(provider, rule)
|
2019-01-06 14:09:19 +08:00
|
|
|
if p.Rule == nil {
|
2020-08-27 21:50:24 +08:00
|
|
|
panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
|
2019-01-06 14:09:19 +08:00
|
|
|
}
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func maybeBuildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
|
|
|
|
for _, p := range provider.BuildParamsForTests() {
|
2019-06-11 06:15:17 +08:00
|
|
|
if strings.Contains(p.Description, desc) {
|
2019-02-26 06:54:28 +08:00
|
|
|
return newTestingBuildParams(provider, p)
|
2017-10-20 04:06:22 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-26 06:54:28 +08:00
|
|
|
return TestingBuildParams{}
|
2017-10-20 04:06:22 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func buildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
|
|
|
|
p := maybeBuildParamsFromDescription(provider, desc)
|
2019-01-06 14:09:19 +08:00
|
|
|
if p.Rule == nil {
|
|
|
|
panic(fmt.Errorf("couldn't find description %q", desc))
|
|
|
|
}
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func maybeBuildParamsFromOutput(provider testBuildProvider, file string) (TestingBuildParams, []string) {
|
2017-12-06 01:26:15 +08:00
|
|
|
var searchedOutputs []string
|
2019-02-26 06:54:28 +08:00
|
|
|
for _, p := range provider.BuildParamsForTests() {
|
2017-07-14 05:43:27 +08:00
|
|
|
outputs := append(WritablePaths(nil), p.Outputs...)
|
2019-03-30 06:33:06 +08:00
|
|
|
outputs = append(outputs, p.ImplicitOutputs...)
|
2017-07-14 05:43:27 +08:00
|
|
|
if p.Output != nil {
|
|
|
|
outputs = append(outputs, p.Output)
|
|
|
|
}
|
|
|
|
for _, f := range outputs {
|
2017-12-01 12:13:19 +08:00
|
|
|
if f.String() == file || f.Rel() == file {
|
2019-02-26 06:54:28 +08:00
|
|
|
return newTestingBuildParams(provider, p), nil
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
2017-12-06 01:26:15 +08:00
|
|
|
searchedOutputs = append(searchedOutputs, f.Rel())
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-26 06:54:28 +08:00
|
|
|
return TestingBuildParams{}, searchedOutputs
|
2019-01-06 14:09:19 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func buildParamsFromOutput(provider testBuildProvider, file string) TestingBuildParams {
|
|
|
|
p, searchedOutputs := maybeBuildParamsFromOutput(provider, file)
|
2019-01-06 14:09:19 +08:00
|
|
|
if p.Rule == nil {
|
|
|
|
panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
|
|
|
|
file, searchedOutputs))
|
|
|
|
}
|
|
|
|
return p
|
2017-07-14 05:43:27 +08:00
|
|
|
}
|
2018-03-12 16:29:17 +08:00
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
func allOutputs(provider testBuildProvider) []string {
|
2019-01-24 08:27:47 +08:00
|
|
|
var outputFullPaths []string
|
2019-02-26 06:54:28 +08:00
|
|
|
for _, p := range provider.BuildParamsForTests() {
|
2019-01-24 08:27:47 +08:00
|
|
|
outputs := append(WritablePaths(nil), p.Outputs...)
|
2019-03-30 06:33:06 +08:00
|
|
|
outputs = append(outputs, p.ImplicitOutputs...)
|
2019-01-24 08:27:47 +08:00
|
|
|
if p.Output != nil {
|
|
|
|
outputs = append(outputs, p.Output)
|
|
|
|
}
|
|
|
|
outputFullPaths = append(outputFullPaths, outputs.Strings()...)
|
|
|
|
}
|
|
|
|
return outputFullPaths
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:54:28 +08:00
|
|
|
// TestingModule is wrapper around an android.Module that provides methods to find information about individual
|
|
|
|
// ctx.Build parameters for verification in tests.
|
|
|
|
type TestingModule struct {
|
|
|
|
module Module
|
|
|
|
}
|
|
|
|
|
|
|
|
// Module returns the Module wrapped by the TestingModule.
|
|
|
|
func (m TestingModule) Module() Module {
|
|
|
|
return m.module
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
|
|
|
|
// BuildParams if no rule is found.
|
|
|
|
func (m TestingModule) MaybeRule(rule string) TestingBuildParams {
|
2020-08-27 21:50:24 +08:00
|
|
|
r, _ := maybeBuildParamsFromRule(m.module, rule)
|
|
|
|
return r
|
2019-02-26 06:54:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
|
|
|
|
func (m TestingModule) Rule(rule string) TestingBuildParams {
|
|
|
|
return buildParamsFromRule(m.module, rule)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
|
|
|
|
// BuildParams if no rule is found.
|
|
|
|
func (m TestingModule) MaybeDescription(desc string) TestingBuildParams {
|
|
|
|
return maybeBuildParamsFromDescription(m.module, desc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
|
|
|
|
// found.
|
|
|
|
func (m TestingModule) Description(desc string) TestingBuildParams {
|
|
|
|
return buildParamsFromDescription(m.module, desc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
|
|
|
|
// value matches the provided string. Returns an empty BuildParams if no rule is found.
|
|
|
|
func (m TestingModule) MaybeOutput(file string) TestingBuildParams {
|
|
|
|
p, _ := maybeBuildParamsFromOutput(m.module, file)
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
|
|
|
|
// value matches the provided string. Panics if no rule is found.
|
|
|
|
func (m TestingModule) Output(file string) TestingBuildParams {
|
|
|
|
return buildParamsFromOutput(m.module, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
|
|
|
|
func (m TestingModule) AllOutputs() []string {
|
|
|
|
return allOutputs(m.module)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
|
|
|
|
// ctx.Build parameters for verification in tests.
|
|
|
|
type TestingSingleton struct {
|
|
|
|
singleton Singleton
|
|
|
|
provider testBuildProvider
|
|
|
|
}
|
|
|
|
|
|
|
|
// Singleton returns the Singleton wrapped by the TestingSingleton.
|
|
|
|
func (s TestingSingleton) Singleton() Singleton {
|
|
|
|
return s.singleton
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
|
|
|
|
// BuildParams if no rule is found.
|
|
|
|
func (s TestingSingleton) MaybeRule(rule string) TestingBuildParams {
|
2020-08-27 21:50:24 +08:00
|
|
|
r, _ := maybeBuildParamsFromRule(s.provider, rule)
|
|
|
|
return r
|
2019-02-26 06:54:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
|
|
|
|
func (s TestingSingleton) Rule(rule string) TestingBuildParams {
|
|
|
|
return buildParamsFromRule(s.provider, rule)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
|
|
|
|
// BuildParams if no rule is found.
|
|
|
|
func (s TestingSingleton) MaybeDescription(desc string) TestingBuildParams {
|
|
|
|
return maybeBuildParamsFromDescription(s.provider, desc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
|
|
|
|
// found.
|
|
|
|
func (s TestingSingleton) Description(desc string) TestingBuildParams {
|
|
|
|
return buildParamsFromDescription(s.provider, desc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
|
|
|
|
// value matches the provided string. Returns an empty BuildParams if no rule is found.
|
|
|
|
func (s TestingSingleton) MaybeOutput(file string) TestingBuildParams {
|
|
|
|
p, _ := maybeBuildParamsFromOutput(s.provider, file)
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
|
|
|
|
// value matches the provided string. Panics if no rule is found.
|
|
|
|
func (s TestingSingleton) Output(file string) TestingBuildParams {
|
|
|
|
return buildParamsFromOutput(s.provider, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
|
|
|
|
func (s TestingSingleton) AllOutputs() []string {
|
|
|
|
return allOutputs(s.provider)
|
|
|
|
}
|
|
|
|
|
2018-03-12 16:29:17 +08:00
|
|
|
func FailIfErrored(t *testing.T, errs []error) {
|
|
|
|
t.Helper()
|
|
|
|
if len(errs) > 0 {
|
|
|
|
for _, err := range errs {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
2018-03-12 16:34:26 +08:00
|
|
|
|
2021-03-05 01:58:33 +08:00
|
|
|
// Fail if no errors that matched the regular expression were found.
|
|
|
|
//
|
|
|
|
// Returns true if a matching error was found, false otherwise.
|
|
|
|
func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool {
|
2018-03-12 16:34:26 +08:00
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
matcher, err := regexp.Compile(pattern)
|
|
|
|
if err != nil {
|
2021-03-05 01:58:33 +08:00
|
|
|
t.Fatalf("failed to compile regular expression %q because %s", pattern, err)
|
2018-03-12 16:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
found := false
|
|
|
|
for _, err := range errs {
|
|
|
|
if matcher.FindStringIndex(err.Error()) != nil {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
|
|
|
|
for i, err := range errs {
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-12 03:17:01 +08:00
|
|
|
t.Errorf("errs[%d] = %q", i, err)
|
2018-03-12 16:34:26 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-05 01:58:33 +08:00
|
|
|
|
|
|
|
return found
|
2018-03-12 16:34:26 +08:00
|
|
|
}
|
2019-04-04 06:47:29 +08:00
|
|
|
|
2019-08-05 22:07:57 +08:00
|
|
|
func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
if expectedErrorPatterns == nil {
|
|
|
|
FailIfErrored(t, errs)
|
|
|
|
} else {
|
|
|
|
for _, expectedError := range expectedErrorPatterns {
|
|
|
|
FailIfNoMatchingErrors(t, expectedError, errs)
|
|
|
|
}
|
|
|
|
if len(errs) > len(expectedErrorPatterns) {
|
|
|
|
t.Errorf("additional errors found, expected %d, found %d",
|
|
|
|
len(expectedErrorPatterns), len(errs))
|
|
|
|
for i, expectedError := range expectedErrorPatterns {
|
|
|
|
t.Errorf("expectedErrors[%d] = %s", i, expectedError)
|
|
|
|
}
|
|
|
|
for i, err := range errs {
|
|
|
|
t.Errorf("errs[%d] = %s", i, err)
|
|
|
|
}
|
2021-03-05 01:58:33 +08:00
|
|
|
t.FailNow()
|
2019-08-05 22:07:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-23 13:22:30 +08:00
|
|
|
func SetKatiEnabledForTests(config Config) {
|
|
|
|
config.katiEnabled = true
|
2020-03-05 04:15:08 +08:00
|
|
|
}
|
|
|
|
|
2020-07-04 04:18:24 +08:00
|
|
|
func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
|
2019-04-04 06:47:29 +08:00
|
|
|
var p AndroidMkEntriesProvider
|
|
|
|
var ok bool
|
|
|
|
if p, ok = mod.(AndroidMkEntriesProvider); !ok {
|
2019-07-23 23:53:32 +08:00
|
|
|
t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
|
2019-04-04 06:47:29 +08:00
|
|
|
}
|
2019-12-03 12:24:29 +08:00
|
|
|
|
|
|
|
entriesList := p.AndroidMkEntries()
|
|
|
|
for i, _ := range entriesList {
|
2020-07-04 04:18:24 +08:00
|
|
|
entriesList[i].fillInEntries(ctx, mod)
|
2019-12-03 12:24:29 +08:00
|
|
|
}
|
|
|
|
return entriesList
|
2019-04-04 06:47:29 +08:00
|
|
|
}
|
2019-07-11 15:18:47 +08:00
|
|
|
|
2020-07-04 04:18:24 +08:00
|
|
|
func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
|
2019-07-11 15:18:47 +08:00
|
|
|
var p AndroidMkDataProvider
|
|
|
|
var ok bool
|
|
|
|
if p, ok = mod.(AndroidMkDataProvider); !ok {
|
2019-07-23 23:53:32 +08:00
|
|
|
t.Errorf("module does not implement AndroidMkDataProvider: " + mod.Name())
|
2019-07-11 15:18:47 +08:00
|
|
|
}
|
|
|
|
data := p.AndroidMk()
|
2020-07-04 04:18:24 +08:00
|
|
|
data.fillInData(ctx, mod)
|
2019-07-11 15:18:47 +08:00
|
|
|
return data
|
|
|
|
}
|
2019-12-10 21:41:51 +08:00
|
|
|
|
|
|
|
// Normalize the path for testing.
|
|
|
|
//
|
|
|
|
// If the path is relative to the build directory then return the relative path
|
|
|
|
// to avoid tests having to deal with the dynamically generated build directory.
|
|
|
|
//
|
|
|
|
// Otherwise, return the supplied path as it is almost certainly a source path
|
|
|
|
// that is relative to the root of the source tree.
|
|
|
|
//
|
|
|
|
// The build and source paths should be distinguishable based on their contents.
|
|
|
|
func NormalizePathForTesting(path Path) string {
|
2020-11-03 01:32:38 +08:00
|
|
|
if path == nil {
|
|
|
|
return "<nil path>"
|
|
|
|
}
|
2019-12-10 21:41:51 +08:00
|
|
|
p := path.String()
|
|
|
|
if w, ok := path.(WritablePath); ok {
|
|
|
|
rel, err := filepath.Rel(w.buildDir(), p)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return rel
|
|
|
|
}
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
func NormalizePathsForTesting(paths Paths) []string {
|
|
|
|
var result []string
|
|
|
|
for _, path := range paths {
|
|
|
|
relative := NormalizePathForTesting(path)
|
|
|
|
result = append(result, relative)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|