Loading android/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ bootstrap_go_package { "selects_test.go", "singleton_module_test.go", "soong_config_modules_test.go", "test_suites_test.go", "util_test.go", "variable_test.go", "visibility_test.go", Loading android/test_suites.go +74 −15 Original line number Diff line number Diff line Loading @@ -14,6 +14,11 @@ package android import ( "path/filepath" "strings" ) func init() { RegisterParallelSingletonType("testsuites", testSuiteFilesFactory) } Loading @@ -23,8 +28,8 @@ func testSuiteFilesFactory() Singleton { } type testSuiteFiles struct { robolectric WritablePath ravenwood WritablePath robolectric []Path ravenwood []Path } type TestSuiteModule interface { Loading @@ -48,53 +53,107 @@ func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) { }) t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"]) ctx.Phony("robolectric-tests", t.robolectric) ctx.Phony("robolectric-tests", t.robolectric...) t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"]) ctx.Phony("ravenwood-tests", t.ravenwood) ctx.Phony("ravenwood-tests", t.ravenwood...) } func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) { ctx.DistForGoal("robolectric-tests", t.robolectric) ctx.DistForGoal("ravenwood-tests", t.ravenwood) ctx.DistForGoal("robolectric-tests", t.robolectric...) ctx.DistForGoal("ravenwood-tests", t.ravenwood...) } func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath { func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip") outputFile := pathForPackaging(ctx, "robolectric-tests.zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). FlagWithArg("-P ", "host/testcases"). FlagWithArg("-C ", testCasesDir.String()). FlagWithArg("-C ", pathForTestCases(ctx).String()). FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time testList := buildTestList(ctx, "robolectric-tests_list", installedPaths) testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). FlagWithArg("-C ", pathForPackaging(ctx).String()). FlagWithInput("-f ", testList). Flag("-sha256") rule.Build("robolectric_tests_zip", "robolectric-tests.zip") return outputFile return []Path{outputFile, testListZipOutputFile} } func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath { func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") outputFile := PathForOutput(ctx, "packaging", "ravenwood-tests.zip") outputFile := pathForPackaging(ctx, "ravenwood-tests.zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). FlagWithArg("-P ", "host/testcases"). FlagWithArg("-C ", testCasesDir.String()). FlagWithArg("-C ", pathForTestCases(ctx).String()). FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths) testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). FlagWithArg("-C ", pathForPackaging(ctx).String()). FlagWithInput("-f ", testList). Flag("-sha256") rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip") return []Path{outputFile, testListZipOutputFile} } func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path { buf := &strings.Builder{} for _, p := range installedPaths { if p.Ext() != ".config" { continue } pc, err := toTestListPath(p.String(), pathForTestCases(ctx).String(), "host/testcases") if err != nil { ctx.Errorf("Failed to convert path: %s, %v", p.String(), err) continue } buf.WriteString(pc) buf.WriteString("\n") } outputFile := pathForPackaging(ctx, listFile) WriteFileRuleVerbatim(ctx, outputFile, buf.String()) return outputFile } func toTestListPath(path, relativeRoot, prefix string) (string, error) { dest, err := filepath.Rel(relativeRoot, path) if err != nil { return "", err } return filepath.Join(prefix, dest), nil } func pathForPackaging(ctx PathContext, pathComponents ...string) OutputPath { pathComponents = append([]string{"packaging"}, pathComponents...) return PathForOutput(ctx, pathComponents...) } func pathForTestCases(ctx PathContext) InstallPath { return pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") } android/test_suites_test.go 0 → 100644 +117 −0 Original line number Diff line number Diff line // Copyright 2024 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package android import ( "path/filepath" "testing" ) func TestBuildTestList(t *testing.T) { t.Parallel() ctx := GroupFixturePreparers( prepareForFakeTestSuite, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterParallelSingletonType("testsuites", testSuiteFilesFactory) }), ).RunTestWithBp(t, ` fake_module { name: "module1", outputs: [ "Test1/Test1.config", "Test1/Test1.apk", ], test_suites: ["ravenwood-tests"], } fake_module { name: "module2", outputs: [ "Test2/Test21/Test21.config", "Test2/Test21/Test21.apk", ], test_suites: ["ravenwood-tests", "robolectric-tests"], } fake_module { name: "module_without_config", outputs: [ "BadTest/BadTest.jar", ], test_suites: ["robolectric-tests"], } `) config := ctx.SingletonForTests("testsuites") allOutputs := config.AllOutputs() wantContents := map[string]string{ "robolectric-tests.zip": "", "robolectric-tests_list.zip": "", "robolectric-tests_list": `host/testcases/Test2/Test21/Test21.config `, "ravenwood-tests.zip": "", "ravenwood-tests_list.zip": "", "ravenwood-tests_list": `host/testcases/Test1/Test1.config host/testcases/Test2/Test21/Test21.config `, } for _, output := range allOutputs { want, ok := wantContents[filepath.Base(output)] if !ok { t.Errorf("unexpected output: %q", output) continue } got := "" if want != "" { got = ContentFromFileRuleForTests(t, ctx.TestContext, config.MaybeOutput(output)) } if want != got { t.Errorf("want %q, got %q", want, got) } } } type fake_module struct { ModuleBase props struct { Outputs []string Test_suites []string } } func fakeTestSuiteFactory() Module { module := &fake_module{} base := module.base() module.AddProperties(&base.nameProperties, &module.props) InitAndroidModule(module) return module } var prepareForFakeTestSuite = GroupFixturePreparers( FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("fake_module", fakeTestSuiteFactory) }), ) func (f *fake_module) GenerateAndroidBuildActions(ctx ModuleContext) { for _, output := range f.props.Outputs { ctx.InstallFile(pathForTestCases(ctx), output, nil) } } func (f *fake_module) TestSuites() []string { return f.props.Test_suites } Loading
android/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ bootstrap_go_package { "selects_test.go", "singleton_module_test.go", "soong_config_modules_test.go", "test_suites_test.go", "util_test.go", "variable_test.go", "visibility_test.go", Loading
android/test_suites.go +74 −15 Original line number Diff line number Diff line Loading @@ -14,6 +14,11 @@ package android import ( "path/filepath" "strings" ) func init() { RegisterParallelSingletonType("testsuites", testSuiteFilesFactory) } Loading @@ -23,8 +28,8 @@ func testSuiteFilesFactory() Singleton { } type testSuiteFiles struct { robolectric WritablePath ravenwood WritablePath robolectric []Path ravenwood []Path } type TestSuiteModule interface { Loading @@ -48,53 +53,107 @@ func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) { }) t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"]) ctx.Phony("robolectric-tests", t.robolectric) ctx.Phony("robolectric-tests", t.robolectric...) t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"]) ctx.Phony("ravenwood-tests", t.ravenwood) ctx.Phony("ravenwood-tests", t.ravenwood...) } func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) { ctx.DistForGoal("robolectric-tests", t.robolectric) ctx.DistForGoal("ravenwood-tests", t.ravenwood) ctx.DistForGoal("robolectric-tests", t.robolectric...) ctx.DistForGoal("ravenwood-tests", t.ravenwood...) } func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath { func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip") outputFile := pathForPackaging(ctx, "robolectric-tests.zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). FlagWithArg("-P ", "host/testcases"). FlagWithArg("-C ", testCasesDir.String()). FlagWithArg("-C ", pathForTestCases(ctx).String()). FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time testList := buildTestList(ctx, "robolectric-tests_list", installedPaths) testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). FlagWithArg("-C ", pathForPackaging(ctx).String()). FlagWithInput("-f ", testList). Flag("-sha256") rule.Build("robolectric_tests_zip", "robolectric-tests.zip") return outputFile return []Path{outputFile, testListZipOutputFile} } func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath { func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") outputFile := PathForOutput(ctx, "packaging", "ravenwood-tests.zip") outputFile := pathForPackaging(ctx, "ravenwood-tests.zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). FlagWithArg("-P ", "host/testcases"). FlagWithArg("-C ", testCasesDir.String()). FlagWithArg("-C ", pathForTestCases(ctx).String()). FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths) testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). FlagWithArg("-C ", pathForPackaging(ctx).String()). FlagWithInput("-f ", testList). Flag("-sha256") rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip") return []Path{outputFile, testListZipOutputFile} } func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path { buf := &strings.Builder{} for _, p := range installedPaths { if p.Ext() != ".config" { continue } pc, err := toTestListPath(p.String(), pathForTestCases(ctx).String(), "host/testcases") if err != nil { ctx.Errorf("Failed to convert path: %s, %v", p.String(), err) continue } buf.WriteString(pc) buf.WriteString("\n") } outputFile := pathForPackaging(ctx, listFile) WriteFileRuleVerbatim(ctx, outputFile, buf.String()) return outputFile } func toTestListPath(path, relativeRoot, prefix string) (string, error) { dest, err := filepath.Rel(relativeRoot, path) if err != nil { return "", err } return filepath.Join(prefix, dest), nil } func pathForPackaging(ctx PathContext, pathComponents ...string) OutputPath { pathComponents = append([]string{"packaging"}, pathComponents...) return PathForOutput(ctx, pathComponents...) } func pathForTestCases(ctx PathContext) InstallPath { return pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases") }
android/test_suites_test.go 0 → 100644 +117 −0 Original line number Diff line number Diff line // Copyright 2024 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package android import ( "path/filepath" "testing" ) func TestBuildTestList(t *testing.T) { t.Parallel() ctx := GroupFixturePreparers( prepareForFakeTestSuite, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterParallelSingletonType("testsuites", testSuiteFilesFactory) }), ).RunTestWithBp(t, ` fake_module { name: "module1", outputs: [ "Test1/Test1.config", "Test1/Test1.apk", ], test_suites: ["ravenwood-tests"], } fake_module { name: "module2", outputs: [ "Test2/Test21/Test21.config", "Test2/Test21/Test21.apk", ], test_suites: ["ravenwood-tests", "robolectric-tests"], } fake_module { name: "module_without_config", outputs: [ "BadTest/BadTest.jar", ], test_suites: ["robolectric-tests"], } `) config := ctx.SingletonForTests("testsuites") allOutputs := config.AllOutputs() wantContents := map[string]string{ "robolectric-tests.zip": "", "robolectric-tests_list.zip": "", "robolectric-tests_list": `host/testcases/Test2/Test21/Test21.config `, "ravenwood-tests.zip": "", "ravenwood-tests_list.zip": "", "ravenwood-tests_list": `host/testcases/Test1/Test1.config host/testcases/Test2/Test21/Test21.config `, } for _, output := range allOutputs { want, ok := wantContents[filepath.Base(output)] if !ok { t.Errorf("unexpected output: %q", output) continue } got := "" if want != "" { got = ContentFromFileRuleForTests(t, ctx.TestContext, config.MaybeOutput(output)) } if want != got { t.Errorf("want %q, got %q", want, got) } } } type fake_module struct { ModuleBase props struct { Outputs []string Test_suites []string } } func fakeTestSuiteFactory() Module { module := &fake_module{} base := module.base() module.AddProperties(&base.nameProperties, &module.props) InitAndroidModule(module) return module } var prepareForFakeTestSuite = GroupFixturePreparers( FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("fake_module", fakeTestSuiteFactory) }), ) func (f *fake_module) GenerateAndroidBuildActions(ctx ModuleContext) { for _, output := range f.props.Outputs { ctx.InstallFile(pathForTestCases(ctx), output, nil) } } func (f *fake_module) TestSuites() []string { return f.props.Test_suites }