diff --git a/android/sh_binary.go b/android/sh_binary.go index cf415c560..fb7446dcc 100644 --- a/android/sh_binary.go +++ b/android/sh_binary.go @@ -16,7 +16,6 @@ package android import ( "fmt" - "io" "strings" ) @@ -58,6 +57,10 @@ type TestProperties struct { // the name of the test configuration (for example "AndroidTest.xml") that should be // installed with the module. Test_config *string `android:"arch_variant"` + + // list of files or filegroup modules that provide data that should be installed alongside + // the test. + Data []string `android:"path,arch_variant"` } type ShBinary struct { @@ -73,6 +76,8 @@ type ShTest struct { ShBinary testProperties TestProperties + + data Paths } func (s *ShBinary) DepsMutator(ctx BottomUpMutatorContext) { @@ -122,30 +127,50 @@ func (s *ShBinary) GenerateAndroidBuildActions(ctx ModuleContext) { }) } -func (s *ShBinary) AndroidMk() AndroidMkData { - return AndroidMkData{ +func (s *ShBinary) AndroidMkEntries() AndroidMkEntries { + return AndroidMkEntries{ Class: "EXECUTABLES", OutputFile: OptionalPathForPath(s.outputFilePath), Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk", - Extra: []AndroidMkExtraFunc{ - func(w io.Writer, outputFile Path) { - fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", String(s.properties.Sub_dir)) - fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX :=") - fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", s.outputFilePath.Rel()) - }, + AddCustomEntries: func(name, prefix, moduleDir string, entries *AndroidMkEntries) { + s.customAndroidMkEntries(entries) }, } } -func (s *ShTest) AndroidMk() AndroidMkData { - data := s.ShBinary.AndroidMk() - data.Class = "NATIVE_TESTS" - data.Extra = append(data.Extra, func(w io.Writer, outputFile Path) { - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=", - strings.Join(s.testProperties.Test_suites, " ")) - fmt.Fprintln(w, "LOCAL_TEST_CONFIG :=", String(s.testProperties.Test_config)) - }) - return data +func (s *ShBinary) customAndroidMkEntries(entries *AndroidMkEntries) { + entries.SetString("LOCAL_MODULE_RELATIVE_PATH", String(s.properties.Sub_dir)) + entries.SetString("LOCAL_MODULE_SUFFIX", "") + entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel()) +} + +func (s *ShTest) GenerateAndroidBuildActions(ctx ModuleContext) { + s.ShBinary.GenerateAndroidBuildActions(ctx) + + s.data = PathsForModuleSrc(ctx, s.testProperties.Data) +} + +func (s *ShTest) AndroidMkEntries() AndroidMkEntries { + return AndroidMkEntries{ + Class: "NATIVE_TESTS", + OutputFile: OptionalPathForPath(s.outputFilePath), + Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk", + AddCustomEntries: func(name, prefix, moduleDir string, entries *AndroidMkEntries) { + s.customAndroidMkEntries(entries) + + entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...) + entries.SetString("LOCAL_TEST_CONFIG", String(s.testProperties.Test_config)) + for _, d := range s.data { + rel := d.Rel() + path := d.String() + if !strings.HasSuffix(path, rel) { + panic(fmt.Errorf("path %q does not end with %q", path, rel)) + } + path = strings.TrimSuffix(path, rel) + entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel) + } + }, + } } func InitShBinaryModule(s *ShBinary) { diff --git a/android/sh_binary_test.go b/android/sh_binary_test.go new file mode 100644 index 000000000..becb35a21 --- /dev/null +++ b/android/sh_binary_test.go @@ -0,0 +1,58 @@ +package android + +import ( + "io/ioutil" + "os" + "reflect" + "testing" +) + +func testShBinary(t *testing.T, bp string) (*TestContext, Config) { + buildDir, err := ioutil.TempDir("", "soong_sh_binary_test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(buildDir) + + config := TestArchConfig(buildDir, nil) + + ctx := NewTestArchContext() + ctx.RegisterModuleType("sh_test", ModuleFactoryAdaptor(ShTestFactory)) + ctx.Register() + mockFiles := map[string][]byte{ + "Android.bp": []byte(bp), + "test.sh": nil, + "testdata/data1": nil, + "testdata/sub/data2": nil, + } + ctx.MockFileSystem(mockFiles) + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + return ctx, config +} + +func TestShTestTestData(t *testing.T) { + ctx, config := testShBinary(t, ` + sh_test { + name: "foo", + src: "test.sh", + filename: "test.sh", + data: [ + "testdata/data1", + "testdata/sub/data2", + ], + } + `) + + mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) + + entries := AndroidMkEntriesForTest(t, config, "", mod) + expected := []string{":testdata/data1", ":testdata/sub/data2"} + actual := entries.EntryMap["LOCAL_TEST_DATA"] + if !reflect.DeepEqual(expected, actual) { + t.Errorf("Unexpected test data expected: %q, actual: %q", expected, actual) + } +}