diff options
author | 2024-11-06 19:57:25 +0000 | |
---|---|---|
committer | 2024-11-06 19:57:25 +0000 | |
commit | 0c79e26a9fe73bf6c99c21b6f3a308fcf50fdf43 (patch) | |
tree | e947289c5c5ab6e009f1069e00d78f62020d22b3 /tradefed_modules | |
parent | aa37c16b032d3c0e9c122089b32c7d51d9b87c23 (diff) |
Implement test_suite.
test_suite supports all test rules with InstallInTestCases set. For these modules, all files insstalled in InstallFilesInfo.InstallFiles
are:
1. Symlinked under out/soong/packaging/<test_suite>
2. The relative path under out/soong/packaging/<test_suite> are added into manifest
Change-Id: I540a19b0a269618783a90d85975df7c110d8be9f
Bug: 372945132
Diffstat (limited to 'tradefed_modules')
-rw-r--r-- | tradefed_modules/test_suite.go | 108 | ||||
-rw-r--r-- | tradefed_modules/test_suite_test.go | 46 |
2 files changed, 148 insertions, 6 deletions
diff --git a/tradefed_modules/test_suite.go b/tradefed_modules/test_suite.go index a6c27274b..cc35ce72c 100644 --- a/tradefed_modules/test_suite.go +++ b/tradefed_modules/test_suite.go @@ -15,11 +15,24 @@ package tradefed_modules import ( - "fmt" + "encoding/json" + "path" + "path/filepath" "android/soong/android" + "android/soong/tradefed" + "github.com/google/blueprint" ) +type testSuiteTag struct{ + blueprint.BaseDependencyTag +} + +type testSuiteManifest struct { + Name string `json:"name"` + Files []string `json:"files"` +} + func init() { RegisterTestSuiteBuildComponents(android.InitRegistrationContext) } @@ -43,10 +56,58 @@ type testSuiteModule struct { testSuiteProperties } +func (t *testSuiteModule) DepsMutator(ctx android.BottomUpMutatorContext) { + for _, test := range t.Tests { + if ctx.OtherModuleDependencyVariantExists(ctx.Config().BuildOSCommonTarget.Variations(), test) { + // Host tests. + ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), testSuiteTag{}, test) + } else { + // Target tests. + ctx.AddDependency(ctx.Module(), testSuiteTag{}, test) + } + } +} + func (t *testSuiteModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + modulesByName := make(map[string]android.Module) + ctx.WalkDeps(func(child, parent android.Module) bool { + // Only write out top level test suite dependencies here. + if _, ok := ctx.OtherModuleDependencyTag(child).(testSuiteTag); !ok { + return false + } + + if !child.InstallInTestcases() { + ctx.ModuleErrorf("test_suite only supports modules installed in testcases. %q is not installed in testcases.", child.Name()) + return false + } + + modulesByName[child.Name()] = child + return false + }) + suiteName := ctx.ModuleName() + var files []string + for name, module := range modulesByName { + // Get the test provider data from the child. + tp, ok := android.OtherModuleProvider(ctx, module, tradefed.BaseTestProviderKey) + if !ok { + // TODO: Consider printing out a list of all module types. + ctx.ModuleErrorf("%q is not a test module.", name) + continue + } + + files = append(files, packageModuleFiles(ctx, suiteName, module, tp)...) + ctx.Phony(suiteName, android.PathForPhony(ctx, name)) + } + manifestPath := android.PathForSuiteInstall(ctx, suiteName, suiteName+".json") - android.WriteFileRule(ctx, manifestPath, fmt.Sprintf(`{"name": %q}`, suiteName)) + b, err := json.Marshal(testSuiteManifest{Name: suiteName, Files: files}) + if err != nil { + ctx.ModuleErrorf("Failed to marshal manifest: %v", err) + return + } + android.WriteFileRule(ctx, manifestPath, string(b)) + ctx.Phony(suiteName, manifestPath) } @@ -59,3 +120,46 @@ func TestSuiteFactory() android.Module { return module } + +func packageModuleFiles(ctx android.ModuleContext, suiteName string, module android.Module, tp tradefed.BaseTestProviderData) []string { + + hostOrTarget := "target" + if tp.IsHost { + hostOrTarget = "host" + } + + // suiteRoot at out/soong/packaging/<suiteName>. + suiteRoot := android.PathForSuiteInstall(ctx, suiteName) + + var installed android.InstallPaths + // Install links to installed files from the module. + if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok { + for _, f := range installFilesInfo.InstallFiles { + // rel is anything under .../<partition>, normally under .../testcases. + rel := android.Rel(ctx, f.PartitionDir(), f.String()) + + // Install the file under <suiteRoot>/<host|target>/<partition>. + installDir := suiteRoot.Join(ctx, hostOrTarget, f.Partition(), path.Dir(rel)) + linkTo, err := filepath.Rel(installDir.String(), f.String()) + if err != nil { + ctx.ModuleErrorf("Failed to get relative path from %s to %s: %v", installDir.String(), f.String(), err) + continue + } + installed = append(installed, ctx.InstallAbsoluteSymlink(installDir, path.Base(rel), linkTo)) + } + } + + // Install config file. + if tp.TestConfig != nil { + moduleRoot := suiteRoot.Join(ctx, hostOrTarget, "testcases", module.Name()) + installed = append(installed, ctx.InstallFile(moduleRoot, module.Name() + ".config", tp.TestConfig)) + } + + // Add to phony and manifest, manifestpaths are relative to suiteRoot. + var manifestEntries []string + for _, f := range installed { + manifestEntries = append(manifestEntries, android.Rel(ctx, suiteRoot.String(), f.String())) + ctx.Phony(suiteName, f) + } + return manifestEntries +} diff --git a/tradefed_modules/test_suite_test.go b/tradefed_modules/test_suite_test.go index 647ba4d43..57e760e62 100644 --- a/tradefed_modules/test_suite_test.go +++ b/tradefed_modules/test_suite_test.go @@ -16,12 +16,15 @@ package tradefed_modules import ( "android/soong/android" "android/soong/java" + "encoding/json" + "slices" "testing" ) func TestTestSuites(t *testing.T) { t.Parallel() ctx := android.GroupFixturePreparers( + android.PrepareForTestWithArchMutator, java.PrepareForTestWithJavaDefaultModules, android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), ).RunTestWithBp(t, ` @@ -45,9 +48,44 @@ func TestTestSuites(t *testing.T) { } `) manifestPath := ctx.ModuleForTests("my-suite", "").Output("out/soong/test_suites/my-suite/my-suite.json") - got := android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath) - want := `{"name": "my-suite"}` + "\n" - if got != want { - t.Errorf("my-suite.json content was %q, want %q", got, want) + var actual testSuiteManifest + if err := json.Unmarshal([]byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath)), &actual); err != nil { + t.Errorf("failed to unmarshal manifest: %v", err) } + slices.Sort(actual.Files) + + expected := testSuiteManifest{ + Name: "my-suite", + Files: []string{ + "target/testcases/TestModule1/TestModule1.config", + "target/testcases/TestModule1/arm64/TestModule1.apk", + "target/testcases/TestModule2/TestModule2.config", + "target/testcases/TestModule2/arm64/TestModule2.apk", + }, + } + + android.AssertDeepEquals(t, "manifests differ", expected, actual) +} + +func TestTestSuitesNotInstalledInTestcases(t *testing.T) { + t.Parallel() + android.GroupFixturePreparers( + android.PrepareForTestWithArchMutator, + java.PrepareForTestWithJavaDefaultModules, + android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), + ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{ + `"SomeHostTest" is not installed in testcases`, + })).RunTestWithBp(t, ` + java_test_host { + name: "SomeHostTest", + srcs: ["a.java"], + } + test_suite { + name: "my-suite", + description: "a test suite", + tests: [ + "SomeHostTest", + ] + } + `) } |