diff --git a/rust/clippy_test.go b/rust/clippy_test.go index e24f666df..e90564f63 100644 --- a/rust/clippy_test.go +++ b/rust/clippy_test.go @@ -66,7 +66,7 @@ func TestClippy(t *testing.T) { for _, tc := range clippyLintTests { t.Run("path="+tc.modulePath, func(t *testing.T) { - config := android.TestArchConfig(buildDir, nil, bp, fs) + config := android.TestArchConfig(t.TempDir(), nil, bp, fs) ctx := CreateTestContext(config) ctx.Register() _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"}) diff --git a/rust/compiler_test.go b/rust/compiler_test.go index 2b40727e7..3ed086f20 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -153,7 +153,7 @@ func TestLints(t *testing.T) { for _, tc := range lintTests { t.Run("path="+tc.modulePath, func(t *testing.T) { - config := android.TestArchConfig(buildDir, nil, bp, fs) + config := android.TestArchConfig(t.TempDir(), nil, bp, fs) ctx := CreateTestContext(config) ctx.Register() _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"}) diff --git a/rust/project_json_test.go b/rust/project_json_test.go index 289bcb81d..8f64f56e2 100644 --- a/rust/project_json_test.go +++ b/rust/project_json_test.go @@ -27,15 +27,14 @@ import ( // testProjectJson run the generation of rust-project.json. It returns the raw // content of the generated file. 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) + result := prepareForRustTest. + Extend(android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"})). + RunTestWithBp(t, bp) // The JSON file is generated via WriteFileToOutputDir. Therefore, it // won't appear in the Output of the TestingSingleton. Manually verify // it exists. - content, err := ioutil.ReadFile(filepath.Join(buildDir, rustProjectJsonFileName)) + content, err := ioutil.ReadFile(filepath.Join(result.Config.BuildDir(), rustProjectJsonFileName)) if err != nil { t.Errorf("rust-project.json has not been generated") } diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go index 1ac66f388..f0f5ec0e9 100644 --- a/rust/protobuf_test.go +++ b/rust/protobuf_test.go @@ -101,7 +101,7 @@ func TestRustGrpc(t *testing.T) { } // Check that we're including the exported directory from libprotobuf-cpp-full - if w := "-Ilibprotobuf-cpp-full-includes"; !strings.Contains(cmd, w) { + if w := "-I" + rustDefaultsDir + "libprotobuf-cpp-full-includes"; !strings.Contains(cmd, w) { t.Errorf("expected %q in %q", w, cmd) } diff --git a/rust/rust_test.go b/rust/rust_test.go index a0ed5345f..bed28ec8f 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -15,7 +15,6 @@ package rust import ( - "io/ioutil" "os" "runtime" "strings" @@ -24,72 +23,94 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" - "android/soong/cc" + "android/soong/genrule" ) -var ( - buildDir string -) - -func setUp() { - var err error - buildDir, err = ioutil.TempDir("", "soong_rust_test") - if err != nil { - panic(err) - } -} - -func tearDown() { - os.RemoveAll(buildDir) -} - func TestMain(m *testing.M) { - run := func() int { - setUp() - defer tearDown() + os.Exit(m.Run()) +} - return m.Run() - } +var prepareForRustTest = android.GroupFixturePreparers( + android.PrepareForTestWithArchMutator, + android.PrepareForTestWithDefaults, + android.PrepareForTestWithPrebuilts, - os.Exit(run()) + genrule.PrepareForTestWithGenRuleBuildComponents, + + PrepareForIntegrationTestWithRust, +) + +var rustMockedFiles = android.MockFS{ + "foo.rs": nil, + "foo.c": nil, + "src/bar.rs": nil, + "src/any.h": nil, + "proto.proto": nil, + "proto/buf.proto": nil, + "buf.proto": nil, + "foo.proto": nil, + "liby.so": nil, + "libz.so": nil, + "data.txt": nil, } // 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. +// This environment contains a few mocked files. See rustMockedFiles 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) + skipTestIfOsNotSupported(t) + result := android.GroupFixturePreparers( + prepareForRustTest, + rustMockedFiles.AddToFixture(), + ). + RunTestWithBp(t, bp) + return result.TestContext } func testRustVndk(t *testing.T, bp string) *android.TestContext { - tctx := newTestRustCtx(t, bp) - tctx.useMockedFs() - tctx.generateConfig() - tctx.setVndk(t) - return tctx.parse(t) + skipTestIfOsNotSupported(t) + result := android.GroupFixturePreparers( + prepareForRustTest, + rustMockedFiles.AddToFixture(), + android.FixtureModifyProductVariables( + func(variables android.FixtureProductVariables) { + variables.DeviceVndkVersion = StringPtr("current") + variables.ProductVndkVersion = StringPtr("current") + variables.Platform_vndk_version = StringPtr("VER") + }, + ), + ).RunTestWithBp(t, bp) + return result.TestContext } // 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) + skipTestIfOsNotSupported(t) + result := android.GroupFixturePreparers( + prepareForRustTest, + rustMockedFiles.AddToFixture(), + android.FixtureModifyProductVariables( + func(variables android.FixtureProductVariables) { + variables.ClangCoverage = proptools.BoolPtr(true) + variables.Native_coverage = proptools.BoolPtr(true) + variables.NativeCoveragePaths = []string{"*"} + }, + ), + ).RunTestWithBp(t, bp) + return result.TestContext } // 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) + skipTestIfOsNotSupported(t) + android.GroupFixturePreparers( + prepareForRustTest, + rustMockedFiles.AddToFixture(), + ). + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). + RunTestWithBp(t, bp) } // testRustCtx is used to build a particular test environment. Unless your @@ -102,99 +123,11 @@ type testRustCtx struct { config *android.Config } -// newTestRustCtx returns a new testRustCtx for the Blueprint definition argument. -func newTestRustCtx(t *testing.T, bp string) *testRustCtx { +func skipTestIfOsNotSupported(t *testing.T) { // 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, - "src/any.h": nil, - "proto.proto": nil, - "proto/buf.proto": nil, - "buf.proto": nil, - "foo.proto": nil, - "liby.so": nil, - "libz.so": nil, - "data.txt": nil, - } -} - -// 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() - tctx.bp = tctx.bp + cc.GatherRequiredDepsForTest(android.NoOsType) - cc.GatherRequiredFilesForTest(tctx.fs) - config := android.TestArchConfig(buildDir, tctx.env, tctx.bp, tctx.fs) - tctx.config = &config -} - -// 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.ClangCoverage = proptools.BoolPtr(true) - tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true) - tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"} -} - -func (tctx *testRustCtx) setVndk(t *testing.T) { - if tctx.config == nil { - t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.") - } - tctx.config.TestProductVariables.DeviceVndkVersion = StringPtr("current") - tctx.config.TestProductVariables.ProductVndkVersion = StringPtr("current") - tctx.config.TestProductVariables.Platform_vndk_version = StringPtr("VER") -} - -// 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(*tctx.config) - ctx.Register() - _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) - android.FailIfErrored(t, errs) - _, errs = ctx.PrepareBuildActions(*tctx.config) - android.FailIfErrored(t, errs) - return ctx -} - -// 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.") - } - ctx := CreateTestContext(*tctx.config) - ctx.Register() - - _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) - if len(errs) > 0 { - android.FailIfNoMatchingErrors(t, pattern, errs) - return - } - - _, errs = ctx.PrepareBuildActions(*tctx.config) - if len(errs) > 0 { - android.FailIfNoMatchingErrors(t, pattern, errs) - return - } - - t.Fatalf("missing expected error %q (0 errors are returned)", pattern) } // Test that we can extract the link path from a lib path.