Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43977e8d authored by Thiébaud Weksteen's avatar Thiébaud Weksteen Committed by Gerrit Code Review
Browse files

Merge "rust: refactor tests setup"

parents a80b480e 0a75e524
Loading
Loading
Loading
Loading
+11 −30
Original line number Diff line number Diff line
@@ -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{})
+81 −39
Original line number Diff line number Diff line
@@ -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)
}

// 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)
}

	fs := map[string][]byte{
// 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)
// 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.")
	}

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()
	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