aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-07-18 00:03:59 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-07-18 00:03:59 +0000
commitdddf50039a70eaefeec95bde0ed1ca6d528a1eb9 (patch)
tree21afdd78e48089b287fde603b588af82999e78b9
parent71771078f6666d3bffc758a5ccbf4f13dd143fca (diff)
parentcec8171420763a7a33f210be7bd45e22d3b38831 (diff)
downloadbuild_soong-dddf50039a70eaefeec95bde0ed1ca6d528a1eb9.tar.gz
build_soong-dddf50039a70eaefeec95bde0ed1ca6d528a1eb9.tar.bz2
build_soong-dddf50039a70eaefeec95bde0ed1ca6d528a1eb9.zip
Merge "Add integration testing infrastructure"
-rw-r--r--Android.bp1
-rw-r--r--android/config.go5
-rw-r--r--android/defaults.go5
-rw-r--r--android/module.go18
-rw-r--r--android/mutator.go86
-rw-r--r--android/prebuilt.go9
-rw-r--r--android/prebuilt_test.go22
-rw-r--r--android/register.go14
-rw-r--r--android/testing.go98
-rw-r--r--cc/test_data_test.go23
-rw-r--r--cmd/soong_build/main.go3
-rw-r--r--python/python_test.go31
12 files changed, 193 insertions, 122 deletions
diff --git a/Android.bp b/Android.bp
index 496dcd28..250c969e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,6 +51,7 @@ bootstrap_go_package {
"android/paths.go",
"android/prebuilt.go",
"android/register.go",
+ "android/testing.go",
"android/util.go",
"android/variable.go",
diff --git a/android/config.go b/android/config.go
index 3de1ef1f..661e333d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -84,6 +84,8 @@ type config struct {
inMake bool
+ captureBuild bool // true for tests, saves build parameters for each module
+
OncePer
}
@@ -171,7 +173,8 @@ func TestConfig(buildDir string) Config {
DeviceName: stringPtr("test_device"),
},
- buildDir: buildDir,
+ buildDir: buildDir,
+ captureBuild: true,
}
config.deviceConfig = &deviceConfig{
config: config,
diff --git a/android/defaults.go b/android/defaults.go
index 0776405f..84f0a3db 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -113,6 +113,11 @@ func (defaultable *DefaultableModule) applyDefaults(ctx TopDownMutatorContext,
}
}
+func registerDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
+ ctx.TopDown("defaults", defaultsMutator).Parallel()
+}
+
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
if defaultable, ok := ctx.Module().(Defaultable); ok {
ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
diff --git a/android/module.go b/android/module.go
index 7f541be2..fcb5aeef 100644
--- a/android/module.go
+++ b/android/module.go
@@ -111,6 +111,8 @@ type Module interface {
AddProperties(props ...interface{})
GetProperties() []interface{}
+
+ BuildParamsForTests() []ModuleBuildParams
}
type nameProperties struct {
@@ -291,6 +293,9 @@ type ModuleBase struct {
hooks hooks
registerProps []interface{}
+
+ // For tests
+ buildParams []ModuleBuildParams
}
func (a *ModuleBase) AddProperties(props ...interface{}) {
@@ -301,6 +306,10 @@ func (a *ModuleBase) GetProperties() []interface{} {
return a.registerProps
}
+func (a *ModuleBase) BuildParamsForTests() []ModuleBuildParams {
+ return a.buildParams
+}
+
// Name returns the name of the module. It may be overridden by individual module types, for
// example prebuilts will prepend prebuilt_ to the name.
func (a *ModuleBase) Name() string {
@@ -520,6 +529,8 @@ func (a *ModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
return
}
}
+
+ a.buildParams = androidCtx.buildParams
}
type androidBaseContextImpl struct {
@@ -538,6 +549,9 @@ type androidModuleContext struct {
checkbuildFiles Paths
missingDeps []string
module Module
+
+ // For tests
+ buildParams []ModuleBuildParams
}
func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
@@ -566,6 +580,10 @@ func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params bluep
}
func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
+ if a.config.captureBuild {
+ a.buildParams = append(a.buildParams, params)
+ }
+
bparams := blueprint.BuildParams{
Rule: params.Rule,
Deps: params.Deps,
diff --git a/android/mutator.go b/android/mutator.go
index bb494878..86a5b852 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,8 +15,6 @@
package android
import (
- "sync"
-
"github.com/google/blueprint"
)
@@ -27,9 +25,6 @@ import (
// Deps
// PostDeps
-var registerMutatorsOnce sync.Once
-var registeredMutators []*mutator
-
func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
for _, t := range mutators {
var handle blueprint.MutatorHandle
@@ -44,56 +39,24 @@ func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
}
}
-func registerMutators(ctx *blueprint.Context) {
-
- registerMutatorsOnce.Do(func() {
- ctx := &registerMutatorsContext{}
-
- register := func(funcs []RegisterMutatorFunc) {
- for _, f := range funcs {
- f(ctx)
- }
- }
-
- ctx.TopDown("load_hooks", loadHookMutator).Parallel()
- ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
- ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
- ctx.TopDown("defaults", defaultsMutator).Parallel()
-
- register(preArch)
-
- ctx.BottomUp("arch", archMutator).Parallel()
- ctx.TopDown("arch_hooks", archHookMutator).Parallel()
-
- register(preDeps)
-
- ctx.BottomUp("deps", depsMutator).Parallel()
-
- ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
- ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
-
- register(postDeps)
-
- registeredMutators = ctx.mutators
- })
-
- registerMutatorsToContext(ctx, registeredMutators)
-}
-
-func RegisterTestMutators(ctx *blueprint.Context) {
- mutators := &registerMutatorsContext{}
+func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps []RegisterMutatorFunc) {
+ mctx := &registerMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
for _, f := range funcs {
- f(mutators)
+ f(mctx)
}
}
- register(testPreDeps)
- mutators.BottomUp("deps", depsMutator).Parallel()
- register(testPostDeps)
+ register(preArch)
+
+ register(preDeps)
+
+ mctx.BottomUp("deps", depsMutator).Parallel()
+
+ register(postDeps)
- registerMutatorsToContext(ctx, mutators.mutators)
+ registerMutatorsToContext(ctx, mctx.mutators)
}
type registerMutatorsContext struct {
@@ -107,7 +70,24 @@ type RegisterMutatorsContext interface {
type RegisterMutatorFunc func(RegisterMutatorsContext)
-var preArch, preDeps, postDeps, testPreDeps, testPostDeps []RegisterMutatorFunc
+var preArch = []RegisterMutatorFunc{
+ func(ctx RegisterMutatorsContext) {
+ ctx.TopDown("load_hooks", loadHookMutator).Parallel()
+ },
+ registerPrebuiltsPreArchMutators,
+ registerDefaultsPreArchMutators,
+}
+
+var preDeps = []RegisterMutatorFunc{
+ func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("arch", archMutator).Parallel()
+ ctx.TopDown("arch_hooks", archHookMutator).Parallel()
+ },
+}
+
+var postDeps = []RegisterMutatorFunc{
+ registerPrebuiltsPostDepsMutators,
+}
func PreArchMutators(f RegisterMutatorFunc) {
preArch = append(preArch, f)
@@ -121,14 +101,6 @@ func PostDepsMutators(f RegisterMutatorFunc) {
postDeps = append(postDeps, f)
}
-func TestPreDepsMutators(f RegisterMutatorFunc) {
- testPreDeps = append(testPreDeps, f)
-}
-
-func TeststPostDepsMutators(f RegisterMutatorFunc) {
- testPostDeps = append(testPostDeps, f)
-}
-
type AndroidTopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 772df7af..080df919 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -61,6 +61,15 @@ type PrebuiltInterface interface {
Prebuilt() *Prebuilt
}
+func registerPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
+}
+
+func registerPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+ ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
+ ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
+}
+
// prebuiltMutator ensures that there is always a module with an undecorated name, and marks
// prebuilt modules that have both a prebuilt and a source module.
func prebuiltMutator(ctx BottomUpMutatorContext) {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 5fa20326..fe763edd 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -122,9 +122,12 @@ func TestPrebuilts(t *testing.T) {
for _, test := range prebuiltsTests {
t.Run(test.name, func(t *testing.T) {
- ctx := NewContext()
+ ctx := NewTestContext()
+ ctx.PreArchMutators(registerPrebuiltsPreArchMutators)
+ ctx.PostDepsMutators(registerPrebuiltsPostDepsMutators)
ctx.RegisterModuleType("prebuilt", ModuleFactoryAdaptor(newPrebuiltModule))
ctx.RegisterModuleType("source", ModuleFactoryAdaptor(newSourceModule))
+ ctx.Register()
ctx.MockFileSystem(map[string][]byte{
"Blueprints": []byte(`
source {
@@ -139,13 +142,10 @@ func TestPrebuilts(t *testing.T) {
_, errs = ctx.PrepareBuildActions(config)
fail(t, errs)
- foo := findModule(ctx, "foo")
- if foo == nil {
- t.Fatalf("failed to find module foo")
- }
+ foo := ctx.ModuleForTests("foo", "")
var dependsOnSourceModule, dependsOnPrebuiltModule bool
- ctx.VisitDirectDeps(foo, func(m blueprint.Module) {
+ ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
if _, ok := m.(*sourceModule); ok {
dependsOnSourceModule = true
}
@@ -228,16 +228,6 @@ func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
}
-func findModule(ctx *blueprint.Context, name string) blueprint.Module {
- var ret blueprint.Module
- ctx.VisitAllModules(func(m blueprint.Module) {
- if ctx.ModuleName(m) == name {
- ret = m
- }
- })
- return ret
-}
-
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
diff --git a/android/register.go b/android/register.go
index 76a1cc9f..226e790c 100644
--- a/android/register.go
+++ b/android/register.go
@@ -60,9 +60,15 @@ func RegisterSingletonType(name string, factory blueprint.SingletonFactory) {
singletons = append(singletons, singleton{name, factory})
}
-func NewContext() *blueprint.Context {
- ctx := blueprint.NewContext()
+type Context struct {
+ *blueprint.Context
+}
+
+func NewContext() *Context {
+ return &Context{blueprint.NewContext()}
+}
+func (ctx *Context) Register() {
for _, t := range moduleTypes {
ctx.RegisterModuleType(t.name, t.factory)
}
@@ -71,9 +77,7 @@ func NewContext() *blueprint.Context {
ctx.RegisterSingletonType(t.name, t.factory)
}
- registerMutators(ctx)
+ registerMutators(ctx.Context, preArch, preDeps, postDeps)
ctx.RegisterSingletonType("env", EnvSingleton)
-
- return ctx
}
diff --git a/android/testing.go b/android/testing.go
new file mode 100644
index 00000000..41447751
--- /dev/null
+++ b/android/testing.go
@@ -0,0 +1,98 @@
+// 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"
+ "strings"
+
+ "github.com/google/blueprint"
+)
+
+func NewTestContext() *TestContext {
+ return &TestContext{
+ Context: blueprint.NewContext(),
+ }
+}
+
+type TestContext struct {
+ *blueprint.Context
+ preArch, preDeps, postDeps []RegisterMutatorFunc
+}
+
+func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
+ ctx.preArch = append(ctx.preArch, f)
+}
+
+func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
+ ctx.preDeps = append(ctx.preDeps, f)
+}
+
+func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
+ ctx.postDeps = append(ctx.postDeps, f)
+}
+
+func (ctx *TestContext) Register() {
+ registerMutators(ctx.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
+
+ ctx.RegisterSingletonType("env", EnvSingleton)
+}
+
+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 {
+ panic(fmt.Errorf("failed to find module %q variant %q", name, variant))
+ }
+
+ return TestingModule{module}
+}
+
+type TestingModule struct {
+ module Module
+}
+
+func (m TestingModule) Module() Module {
+ return m.module
+}
+
+func (m TestingModule) Rule(rule string) ModuleBuildParams {
+ for _, p := range m.module.BuildParamsForTests() {
+ if strings.Contains(p.Rule.String(), rule) {
+ return p
+ }
+ }
+ panic(fmt.Errorf("couldn't find rule %q", rule))
+}
+
+func (m TestingModule) Output(file string) ModuleBuildParams {
+ for _, p := range m.module.BuildParamsForTests() {
+ outputs := append(WritablePaths(nil), p.Outputs...)
+ if p.Output != nil {
+ outputs = append(outputs, p.Output)
+ }
+ for _, f := range outputs {
+ if f.Base() == file {
+ return p
+ }
+ }
+ }
+ panic(fmt.Errorf("couldn't find output %q", file))
+}
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index a798919f..962bde5b 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -23,8 +23,6 @@ import (
"android/soong/android"
"android/soong/genrule"
-
- "github.com/google/blueprint"
)
type dataFile struct {
@@ -123,8 +121,7 @@ func TestDataTests(t *testing.T) {
for _, test := range testDataTests {
t.Run(test.name, func(t *testing.T) {
- ctx := blueprint.NewContext()
- android.RegisterTestMutators(ctx)
+ ctx := android.NewTestContext()
ctx.MockFileSystem(map[string][]byte{
"Blueprints": []byte(`subdirs = ["dir"]`),
"dir/Blueprints": []byte(test.modules),
@@ -135,18 +132,16 @@ func TestDataTests(t *testing.T) {
android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
ctx.RegisterModuleType("test",
android.ModuleFactoryAdaptor(newTest))
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Blueprints")
fail(t, errs)
_, errs = ctx.PrepareBuildActions(config)
fail(t, errs)
- foo := findModule(ctx, "foo")
- if foo == nil {
- t.Fatalf("failed to find module foo")
- }
+ foo := ctx.ModuleForTests("foo", "")
- got := foo.(*testDataTest).data
+ got := foo.Module().(*testDataTest).data
if len(got) != len(test.data) {
t.Errorf("expected %d data files, got %d",
len(test.data), len(got))
@@ -192,16 +187,6 @@ func (test *testDataTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
test.data = ctx.ExpandSources(test.Properties.Data, nil)
}
-func findModule(ctx *blueprint.Context, name string) blueprint.Module {
- var ret blueprint.Module
- ctx.VisitAllModules(func(m blueprint.Module) {
- if ctx.ModuleName(m) == name {
- ret = m
- }
- })
- return ret
-}
-
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index ed8f2fd5..e15a6bdd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -32,6 +32,7 @@ func main() {
srcDir := filepath.Dir(flag.Arg(0))
ctx := android.NewContext()
+ ctx.Register()
configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir)
if err != nil {
@@ -44,5 +45,5 @@ func main() {
ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
- bootstrap.Main(ctx, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
+ bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
}
diff --git a/python/python_test.go b/python/python_test.go
index 57aaa344..4c30d95b 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -26,8 +26,6 @@ import (
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
type pyBinary struct {
@@ -306,17 +304,17 @@ var (
func TestPythonModule(t *testing.T) {
config, buildDir := setupBuildEnv(t)
defer tearDownBuildEnv(buildDir)
- android.TestPreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
- })
for _, d := range data {
t.Run(d.desc, func(t *testing.T) {
- ctx := blueprint.NewContext()
- android.RegisterTestMutators(ctx)
+ ctx := android.NewTestContext()
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
+ })
ctx.RegisterModuleType("python_library_host",
android.ModuleFactoryAdaptor(PythonLibraryHostFactory))
ctx.RegisterModuleType("python_binary_host",
android.ModuleFactoryAdaptor(PythonBinaryHostFactory))
+ ctx.Register()
ctx.MockFileSystem(d.mockFiles)
_, testErrs := ctx.ParseBlueprintsFiles(bpFile)
fail(t, testErrs)
@@ -360,15 +358,12 @@ func expectErrors(t *testing.T, actErrs []error, expErrs []string) (testErrs []e
return
}
-func expectModule(t *testing.T, ctx *blueprint.Context, buildDir, name, variant string,
+func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string,
expPyRunfiles, expDepsPyRunfiles []string,
expParSpec string, expDepsParSpecs []string) (testErrs []error) {
- module := findModule(ctx, name, variant)
- if module == nil {
- t.Fatalf("failed to find module %s!", name)
- }
+ module := ctx.ModuleForTests(name, variant)
- base, baseOk := module.(*pythonBaseModule)
+ base, baseOk := module.Module().(*pythonBaseModule)
if !baseOk {
t.Fatalf("%s is not Python module!", name)
}
@@ -438,16 +433,6 @@ func tearDownBuildEnv(buildDir string) {
os.RemoveAll(buildDir)
}
-func findModule(ctx *blueprint.Context, name, variant string) blueprint.Module {
- var ret blueprint.Module
- ctx.VisitAllModules(func(m blueprint.Module) {
- if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
- ret = m
- }
- })
- return ret
-}
-
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {