package sh import ( "io/ioutil" "os" "path/filepath" "reflect" "testing" "android/soong/android" "android/soong/cc" ) var buildDir string func setUp() { var err error buildDir, err = ioutil.TempDir("", "soong_sh_test") if err != nil { panic(err) } } func tearDown() { os.RemoveAll(buildDir) } func TestMain(m *testing.M) { run := func() int { setUp() defer tearDown() return m.Run() } os.Exit(run()) } func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) { fs := map[string][]byte{ "test.sh": nil, "testdata/data1": nil, "testdata/sub/data2": nil, } config := android.TestArchConfig(buildDir, nil, bp, fs) ctx := android.NewTestArchContext(config) ctx.RegisterModuleType("sh_test", ShTestFactory) ctx.RegisterModuleType("sh_test_host", ShTestHostFactory) cc.RegisterRequiredBuildComponentsForTest(ctx) ctx.Register() _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) android.FailIfErrored(t, errs) _, errs = ctx.PrepareBuildActions(config) android.FailIfErrored(t, errs) return ctx, config } func TestShTestSubDir(t *testing.T) { ctx, config := testShBinary(t, ` sh_test { name: "foo", src: "test.sh", sub_dir: "foo_test" } `) mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test" actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] if expectedPath != actualPath { t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath) } } func TestShTest(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 := android.AndroidMkEntriesForTest(t, config, "", mod)[0] expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo" actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] if expectedPath != actualPath { t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath) } expectedData := []string{":testdata/data1", ":testdata/sub/data2"} actualData := entries.EntryMap["LOCAL_TEST_DATA"] if !reflect.DeepEqual(expectedData, actualData) { t.Errorf("Unexpected test data expected: %q, actual: %q", expectedData, actualData) } } func TestShTest_dataModules(t *testing.T) { ctx, config := testShBinary(t, ` sh_test { name: "foo", src: "test.sh", host_supported: true, data_bins: ["bar"], data_libs: ["libbar"], } cc_binary { name: "bar", host_supported: true, shared_libs: ["libbar"], no_libcrt: true, nocrt: true, system_shared_libs: [], stl: "none", } cc_library { name: "libbar", host_supported: true, no_libcrt: true, nocrt: true, system_shared_libs: [], stl: "none", } `) buildOS := android.BuildOs.String() arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"} for _, arch := range arches { variant := ctx.ModuleForTests("foo", arch) libExt := ".so" if arch == "darwin_x86_64" { libExt = ".dylib" } relocated := variant.Output("relocated/lib64/libbar" + libExt) expectedInput := filepath.Join(buildDir, ".intermediates/libbar/"+arch+"_shared/libbar"+libExt) if relocated.Input.String() != expectedInput { t.Errorf("Unexpected relocation input, expected: %q, actual: %q", expectedInput, relocated.Input.String()) } mod := variant.Module().(*ShTest) entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] expectedData := []string{ filepath.Join(buildDir, ".intermediates/bar", arch, ":bar"), filepath.Join(buildDir, ".intermediates/foo", arch, "relocated/:lib64/libbar"+libExt), } actualData := entries.EntryMap["LOCAL_TEST_DATA"] if !reflect.DeepEqual(expectedData, actualData) { t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData) } } } func TestShTestHost(t *testing.T) { ctx, _ := testShBinary(t, ` sh_test_host { name: "foo", src: "test.sh", filename: "test.sh", data: [ "testdata/data1", "testdata/sub/data2", ], } `) buildOS := android.BuildOs.String() mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest) if !mod.Host() { t.Errorf("host bit is not set for a sh_test_host module.") } } func TestShTestHost_dataDeviceModules(t *testing.T) { ctx, config := testShBinary(t, ` sh_test_host { name: "foo", src: "test.sh", data_device_bins: ["bar"], data_device_libs: ["libbar"], } cc_binary { name: "bar", shared_libs: ["libbar"], no_libcrt: true, nocrt: true, system_shared_libs: [], stl: "none", } cc_library { name: "libbar", no_libcrt: true, nocrt: true, system_shared_libs: [], stl: "none", } `) buildOS := android.BuildOs.String() variant := ctx.ModuleForTests("foo", buildOS+"_x86_64") relocated := variant.Output("relocated/lib64/libbar.so") expectedInput := filepath.Join(buildDir, ".intermediates/libbar/android_arm64_armv8-a_shared/libbar.so") if relocated.Input.String() != expectedInput { t.Errorf("Unexpected relocation input, expected: %q, actual: %q", expectedInput, relocated.Input.String()) } mod := variant.Module().(*ShTest) entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] expectedData := []string{ filepath.Join(buildDir, ".intermediates/bar/android_arm64_armv8-a/:bar"), // libbar has been relocated, and so has a variant that matches the host arch. filepath.Join(buildDir, ".intermediates/foo/"+buildOS+"_x86_64/relocated/:lib64/libbar.so"), } actualData := entries.EntryMap["LOCAL_TEST_DATA"] if !reflect.DeepEqual(expectedData, actualData) { t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData) } }