rust: refactor tests setup
Move to a builder pattern to increase flexibility when generating the test configuration. The testRust, testRustCov and testRustError are kept as main entry points for standard tests. Add documentation. Test: m nothing Change-Id: I891bec982ff2d65413f150d2395edf0fb0d68a43
This commit is contained in:
parent
36e4ad1f4d
commit
0a75e52460
|
@ -22,22 +22,15 @@ import (
|
|||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
// testProjectJson run the generation of rust-project.json. It returns the raw
|
||||
// content of the generated file.
|
||||
func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
|
||||
cc.GatherRequiredFilesForTest(fs)
|
||||
|
||||
env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
|
||||
config := android.TestArchConfig(buildDir, env, bp, fs)
|
||||
ctx := CreateTestContext()
|
||||
ctx.Register(config)
|
||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||
android.FailIfErrored(t, errs)
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
android.FailIfErrored(t, errs)
|
||||
func testProjectJson(t *testing.T, bp string) []byte {
|
||||
tctx := newTestRustCtx(t, bp)
|
||||
tctx.env = map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
|
||||
tctx.generateConfig()
|
||||
tctx.parse(t)
|
||||
|
||||
// The JSON file is generated via WriteFileToOutputDir. Therefore, it
|
||||
// won't appear in the Output of the TestingSingleton. Manually verify
|
||||
|
@ -87,12 +80,8 @@ func TestProjectJsonDep(t *testing.T) {
|
|||
crate_name: "b",
|
||||
rlibs: ["liba"],
|
||||
}
|
||||
` + GatherRequiredDepsForTest()
|
||||
fs := map[string][]byte{
|
||||
"a/src/lib.rs": nil,
|
||||
"b/src/lib.rs": nil,
|
||||
}
|
||||
jsonContent := testProjectJson(t, bp, fs)
|
||||
`
|
||||
jsonContent := testProjectJson(t, bp)
|
||||
validateJsonCrates(t, jsonContent)
|
||||
}
|
||||
|
||||
|
@ -123,11 +112,8 @@ func TestProjectJsonBindGen(t *testing.T) {
|
|||
source_stem: "bindings2",
|
||||
wrapper_src: "src/any.h",
|
||||
}
|
||||
` + GatherRequiredDepsForTest()
|
||||
fs := map[string][]byte{
|
||||
"src/lib.rs": nil,
|
||||
}
|
||||
jsonContent := testProjectJson(t, bp, fs)
|
||||
`
|
||||
jsonContent := testProjectJson(t, bp)
|
||||
crates := validateJsonCrates(t, jsonContent)
|
||||
for _, c := range crates {
|
||||
crate, ok := c.(map[string]interface{})
|
||||
|
@ -166,13 +152,8 @@ func TestProjectJsonMultiVersion(t *testing.T) {
|
|||
crate_name: "b",
|
||||
rustlibs: ["liba1", "liba2"],
|
||||
}
|
||||
` + GatherRequiredDepsForTest()
|
||||
fs := map[string][]byte{
|
||||
"a1/src/lib.rs": nil,
|
||||
"a2/src/lib.rs": nil,
|
||||
"b/src/lib.rs": nil,
|
||||
}
|
||||
jsonContent := testProjectJson(t, bp, fs)
|
||||
`
|
||||
jsonContent := testProjectJson(t, bp)
|
||||
crates := validateJsonCrates(t, jsonContent)
|
||||
for _, crate := range crates {
|
||||
c := crate.(map[string]interface{})
|
||||
|
|
|
@ -54,10 +54,58 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(run())
|
||||
}
|
||||
|
||||
func testConfig(bp string) android.Config {
|
||||
bp = bp + GatherRequiredDepsForTest()
|
||||
// testRust returns a TestContext in which a basic environment has been setup.
|
||||
// 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.c": nil,
|
||||
"src/bar.rs": nil,
|
||||
|
@ -66,57 +114,51 @@ func testConfig(bp string) android.Config {
|
|||
"liby.so": nil,
|
||||
"libz.so": nil,
|
||||
}
|
||||
|
||||
cc.GatherRequiredFilesForTest(fs)
|
||||
|
||||
return android.TestArchConfig(buildDir, nil, bp, fs)
|
||||
}
|
||||
|
||||
func testRust(t *testing.T, bp string) *android.TestContext {
|
||||
return testRustContext(t, bp, false)
|
||||
// generateConfig creates the android.Config based on the bp, fs and env
|
||||
// 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 {
|
||||
return testRustContext(t, bp, true)
|
||||
}
|
||||
|
||||
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")
|
||||
// enableCoverage configures the test to enable coverage.
|
||||
func (tctx *testRustCtx) enableCoverage(t *testing.T) {
|
||||
if tctx.config == nil {
|
||||
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
|
||||
}
|
||||
tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
|
||||
tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
|
||||
tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
|
||||
}
|
||||
|
||||
t.Helper()
|
||||
config := testConfig(bp)
|
||||
|
||||
if coverage {
|
||||
config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
|
||||
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
|
||||
config.TestProductVariables.NativeCoveragePaths = []string{"*"}
|
||||
// parse validates the configuration and parses the Blueprint file. It returns
|
||||
// a TestContext which can be used to retrieve the generated modules via
|
||||
// ModuleForTests.
|
||||
func (tctx testRustCtx) parse(t *testing.T) *android.TestContext {
|
||||
if tctx.config == nil {
|
||||
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
|
||||
}
|
||||
|
||||
ctx := CreateTestContext()
|
||||
ctx.Register(config)
|
||||
|
||||
ctx.Register(*tctx.config)
|
||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||
android.FailIfErrored(t, errs)
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
_, errs = ctx.PrepareBuildActions(*tctx.config)
|
||||
android.FailIfErrored(t, errs)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func testRustError(t *testing.T, pattern string, bp string) {
|
||||
// TODO (b/140435149)
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skip("Only the Linux toolchain is supported for Rust")
|
||||
// parseError parses the Blueprint file and ensure that at least one error
|
||||
// matching the provided pattern is observed.
|
||||
func (tctx testRustCtx) parseError(t *testing.T, pattern string) {
|
||||
if tctx.config == nil {
|
||||
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
|
||||
}
|
||||
|
||||
t.Helper()
|
||||
config := testConfig(bp)
|
||||
|
||||
ctx := CreateTestContext()
|
||||
ctx.Register(config)
|
||||
ctx.Register(*tctx.config)
|
||||
|
||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||
if len(errs) > 0 {
|
||||
|
@ -124,7 +166,7 @@ func testRustError(t *testing.T, pattern string, bp string) {
|
|||
return
|
||||
}
|
||||
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
_, errs = ctx.PrepareBuildActions(*tctx.config)
|
||||
if len(errs) > 0 {
|
||||
android.FailIfNoMatchingErrors(t, pattern, errs)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue