Merge "rust: refactor tests setup"

This commit is contained in:
Thiébaud Weksteen 2020-10-09 12:13:15 +00:00 committed by Gerrit Code Review
commit 43977e8d0e
2 changed files with 92 additions and 69 deletions

View File

@ -22,22 +22,15 @@ import (
"testing" "testing"
"android/soong/android" "android/soong/android"
"android/soong/cc"
) )
// testProjectJson run the generation of rust-project.json. It returns the raw // testProjectJson run the generation of rust-project.json. It returns the raw
// content of the generated file. // content of the generated file.
func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte { func testProjectJson(t *testing.T, bp string) []byte {
cc.GatherRequiredFilesForTest(fs) tctx := newTestRustCtx(t, bp)
tctx.env = map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"} tctx.generateConfig()
config := android.TestArchConfig(buildDir, env, bp, fs) tctx.parse(t)
ctx := CreateTestContext()
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
// The JSON file is generated via WriteFileToOutputDir. Therefore, it // The JSON file is generated via WriteFileToOutputDir. Therefore, it
// won't appear in the Output of the TestingSingleton. Manually verify // won't appear in the Output of the TestingSingleton. Manually verify
@ -87,12 +80,8 @@ func TestProjectJsonDep(t *testing.T) {
crate_name: "b", crate_name: "b",
rlibs: ["liba"], rlibs: ["liba"],
} }
` + GatherRequiredDepsForTest() `
fs := map[string][]byte{ jsonContent := testProjectJson(t, bp)
"a/src/lib.rs": nil,
"b/src/lib.rs": nil,
}
jsonContent := testProjectJson(t, bp, fs)
validateJsonCrates(t, jsonContent) validateJsonCrates(t, jsonContent)
} }
@ -123,11 +112,8 @@ func TestProjectJsonBindGen(t *testing.T) {
source_stem: "bindings2", source_stem: "bindings2",
wrapper_src: "src/any.h", wrapper_src: "src/any.h",
} }
` + GatherRequiredDepsForTest() `
fs := map[string][]byte{ jsonContent := testProjectJson(t, bp)
"src/lib.rs": nil,
}
jsonContent := testProjectJson(t, bp, fs)
crates := validateJsonCrates(t, jsonContent) crates := validateJsonCrates(t, jsonContent)
for _, c := range crates { for _, c := range crates {
crate, ok := c.(map[string]interface{}) crate, ok := c.(map[string]interface{})
@ -166,13 +152,8 @@ func TestProjectJsonMultiVersion(t *testing.T) {
crate_name: "b", crate_name: "b",
rustlibs: ["liba1", "liba2"], rustlibs: ["liba1", "liba2"],
} }
` + GatherRequiredDepsForTest() `
fs := map[string][]byte{ jsonContent := testProjectJson(t, bp)
"a1/src/lib.rs": nil,
"a2/src/lib.rs": nil,
"b/src/lib.rs": nil,
}
jsonContent := testProjectJson(t, bp, fs)
crates := validateJsonCrates(t, jsonContent) crates := validateJsonCrates(t, jsonContent)
for _, crate := range crates { for _, crate := range crates {
c := crate.(map[string]interface{}) c := crate.(map[string]interface{})

View File

@ -54,10 +54,58 @@ func TestMain(m *testing.M) {
os.Exit(run()) os.Exit(run())
} }
func testConfig(bp string) android.Config { // testRust returns a TestContext in which a basic environment has been setup.
bp = bp + GatherRequiredDepsForTest() // This environment contains a few mocked files. See testRustCtx.useMockedFs
// for the list of these files.
func testRust(t *testing.T, bp string) *android.TestContext {
tctx := newTestRustCtx(t, bp)
tctx.useMockedFs()
tctx.generateConfig()
return tctx.parse(t)
}
fs := map[string][]byte{ // testRustCov returns a TestContext in which a basic environment has been
// setup. This environment explicitly enables coverage.
func testRustCov(t *testing.T, bp string) *android.TestContext {
tctx := newTestRustCtx(t, bp)
tctx.useMockedFs()
tctx.generateConfig()
tctx.enableCoverage(t)
return tctx.parse(t)
}
// testRustError ensures that at least one error was raised and its value
// matches the pattern provided. The error can be either in the parsing of the
// Blueprint or when generating the build actions.
func testRustError(t *testing.T, pattern string, bp string) {
tctx := newTestRustCtx(t, bp)
tctx.useMockedFs()
tctx.generateConfig()
tctx.parseError(t, pattern)
}
// testRustCtx is used to build a particular test environment. Unless your
// tests requires a specific setup, prefer the wrapping functions: testRust,
// testRustCov or testRustError.
type testRustCtx struct {
bp string
fs map[string][]byte
env map[string]string
config *android.Config
}
// newTestRustCtx returns a new testRustCtx for the Blueprint definition argument.
func newTestRustCtx(t *testing.T, bp string) *testRustCtx {
// TODO (b/140435149)
if runtime.GOOS != "linux" {
t.Skip("Rust Soong tests can only be run on Linux hosts currently")
}
return &testRustCtx{bp: bp}
}
// useMockedFs setup a default mocked filesystem for the test environment.
func (tctx *testRustCtx) useMockedFs() {
tctx.fs = map[string][]byte{
"foo.rs": nil, "foo.rs": nil,
"foo.c": nil, "foo.c": nil,
"src/bar.rs": nil, "src/bar.rs": nil,
@ -66,57 +114,51 @@ func testConfig(bp string) android.Config {
"liby.so": nil, "liby.so": nil,
"libz.so": nil, "libz.so": nil,
} }
cc.GatherRequiredFilesForTest(fs)
return android.TestArchConfig(buildDir, nil, bp, fs)
} }
func testRust(t *testing.T, bp string) *android.TestContext { // generateConfig creates the android.Config based on the bp, fs and env
return testRustContext(t, bp, false) // attributes of the testRustCtx.
func (tctx *testRustCtx) generateConfig() {
tctx.bp = tctx.bp + GatherRequiredDepsForTest()
cc.GatherRequiredFilesForTest(tctx.fs)
config := android.TestArchConfig(buildDir, tctx.env, tctx.bp, tctx.fs)
tctx.config = &config
} }
func testRustCov(t *testing.T, bp string) *android.TestContext { // enableCoverage configures the test to enable coverage.
return testRustContext(t, bp, true) func (tctx *testRustCtx) enableCoverage(t *testing.T) {
} if tctx.config == nil {
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
func testRustContext(t *testing.T, bp string, coverage bool) *android.TestContext {
// TODO (b/140435149)
if runtime.GOOS != "linux" {
t.Skip("Only the Linux toolchain is supported for Rust")
} }
tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
}
t.Helper() // parse validates the configuration and parses the Blueprint file. It returns
config := testConfig(bp) // a TestContext which can be used to retrieve the generated modules via
// ModuleForTests.
if coverage { func (tctx testRustCtx) parse(t *testing.T) *android.TestContext {
config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true) if tctx.config == nil {
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true) t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
config.TestProductVariables.NativeCoveragePaths = []string{"*"}
} }
ctx := CreateTestContext() ctx := CreateTestContext()
ctx.Register(config) ctx.Register(*tctx.config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs) android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(*tctx.config)
android.FailIfErrored(t, errs) android.FailIfErrored(t, errs)
return ctx return ctx
} }
func testRustError(t *testing.T, pattern string, bp string) { // parseError parses the Blueprint file and ensure that at least one error
// TODO (b/140435149) // matching the provided pattern is observed.
if runtime.GOOS != "linux" { func (tctx testRustCtx) parseError(t *testing.T, pattern string) {
t.Skip("Only the Linux toolchain is supported for Rust") if tctx.config == nil {
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
} }
t.Helper()
config := testConfig(bp)
ctx := CreateTestContext() ctx := CreateTestContext()
ctx.Register(config) ctx.Register(*tctx.config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if len(errs) > 0 { if len(errs) > 0 {
@ -124,7 +166,7 @@ func testRustError(t *testing.T, pattern string, bp string) {
return return
} }
_, errs = ctx.PrepareBuildActions(config) _, errs = ctx.PrepareBuildActions(*tctx.config)
if len(errs) > 0 { if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs) android.FailIfNoMatchingErrors(t, pattern, errs)
return return