1package sh 2 3import ( 4 "os" 5 "path/filepath" 6 "strconv" 7 "strings" 8 "testing" 9 10 "android/soong/android" 11 "android/soong/cc" 12) 13 14func TestMain(m *testing.M) { 15 os.Exit(m.Run()) 16} 17 18var prepareForShTest = android.GroupFixturePreparers( 19 cc.PrepareForTestWithCcBuildComponents, 20 PrepareForTestWithShBuildComponents, 21 android.FixtureMergeMockFs(android.MockFS{ 22 "test.sh": nil, 23 "testdata/data1": nil, 24 "testdata/sub/data2": nil, 25 }), 26) 27 28// testShBinary runs tests using the prepareForShTest 29// 30// Do not add any new usages of this, instead use the prepareForShTest directly as it makes it much 31// easier to customize the test behavior. 32// 33// If it is necessary to customize the behavior of an existing test that uses this then please first 34// convert the test to using prepareForShTest first and then in a following change add the 35// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify 36// that it did not change the test behavior unexpectedly. 37// 38// deprecated 39func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) { 40 bp = bp + cc.GatherRequiredDepsForTest(android.Android) 41 42 result := prepareForShTest.RunTestWithBp(t, bp) 43 44 return result.TestContext, result.Config 45} 46 47func TestShTestSubDir(t *testing.T) { 48 result := android.GroupFixturePreparers( 49 prepareForShTest, 50 android.FixtureModifyConfig(android.SetKatiEnabledForTests), 51 ).RunTestWithBp(t, ` 52 sh_test { 53 name: "foo", 54 src: "test.sh", 55 sub_dir: "foo_test" 56 } 57 `) 58 59 mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) 60 61 entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] 62 63 expectedPath := "out/target/product/test_device/data/nativetest64/foo_test" 64 actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] 65 android.AssertStringPathRelativeToTopEquals(t, "LOCAL_MODULE_PATH[0]", result.Config, expectedPath, actualPath) 66} 67 68func TestShTest(t *testing.T) { 69 result := android.GroupFixturePreparers( 70 prepareForShTest, 71 android.FixtureModifyConfig(android.SetKatiEnabledForTests), 72 ).RunTestWithBp(t, ` 73 sh_test { 74 name: "foo", 75 src: "test.sh", 76 filename: "test.sh", 77 data: [ 78 "testdata/data1", 79 "testdata/sub/data2", 80 ], 81 } 82 `) 83 84 mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) 85 86 entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] 87 88 expectedPath := "out/target/product/test_device/data/nativetest64/foo" 89 actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] 90 android.AssertStringPathRelativeToTopEquals(t, "LOCAL_MODULE_PATH[0]", result.Config, expectedPath, actualPath) 91 92 expectedData := []string{":testdata/data1", ":testdata/sub/data2"} 93 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 94 android.AssertDeepEquals(t, "LOCAL_TEST_DATA", expectedData, actualData) 95} 96 97func TestShTest_dataModules(t *testing.T) { 98 ctx, config := testShBinary(t, ` 99 sh_test { 100 name: "foo", 101 src: "test.sh", 102 host_supported: true, 103 data_bins: ["bar"], 104 data_libs: ["libbar"], 105 } 106 107 cc_binary { 108 name: "bar", 109 host_supported: true, 110 shared_libs: ["libbar"], 111 no_libcrt: true, 112 nocrt: true, 113 system_shared_libs: [], 114 stl: "none", 115 } 116 117 cc_library { 118 name: "libbar", 119 host_supported: true, 120 no_libcrt: true, 121 nocrt: true, 122 system_shared_libs: [], 123 stl: "none", 124 } 125 `) 126 127 buildOS := config.BuildOS.String() 128 arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"} 129 for _, arch := range arches { 130 variant := ctx.ModuleForTests("foo", arch) 131 132 libExt := ".so" 133 if arch == "darwin_x86_64" { 134 libExt = ".dylib" 135 } 136 relocated := variant.Output("relocated/lib64/libbar" + libExt) 137 expectedInput := "out/soong/.intermediates/libbar/" + arch + "_shared/libbar" + libExt 138 android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) 139 140 mod := variant.Module().(*ShTest) 141 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 142 expectedData := []string{ 143 filepath.Join("out/soong/.intermediates/bar", arch, ":bar"), 144 filepath.Join("out/soong/.intermediates/foo", arch, "relocated/:lib64/libbar"+libExt), 145 } 146 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 147 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 148 } 149} 150 151func TestShTestHost(t *testing.T) { 152 ctx, _ := testShBinary(t, ` 153 sh_test_host { 154 name: "foo", 155 src: "test.sh", 156 filename: "test.sh", 157 data: [ 158 "testdata/data1", 159 "testdata/sub/data2", 160 ], 161 test_options: { 162 unit_test: true, 163 }, 164 } 165 `) 166 167 buildOS := ctx.Config().BuildOS.String() 168 mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest) 169 if !mod.Host() { 170 t.Errorf("host bit is not set for a sh_test_host module.") 171 } 172 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 173 actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0]) 174 android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData) 175} 176 177func TestShTestHost_dataDeviceModules(t *testing.T) { 178 ctx, config := testShBinary(t, ` 179 sh_test_host { 180 name: "foo", 181 src: "test.sh", 182 data_device_bins: ["bar"], 183 data_device_libs: ["libbar"], 184 } 185 186 cc_binary { 187 name: "bar", 188 shared_libs: ["libbar"], 189 no_libcrt: true, 190 nocrt: true, 191 system_shared_libs: [], 192 stl: "none", 193 } 194 195 cc_library { 196 name: "libbar", 197 no_libcrt: true, 198 nocrt: true, 199 system_shared_libs: [], 200 stl: "none", 201 } 202 `) 203 204 buildOS := config.BuildOS.String() 205 variant := ctx.ModuleForTests("foo", buildOS+"_x86_64") 206 207 relocated := variant.Output("relocated/lib64/libbar.so") 208 expectedInput := "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so" 209 android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) 210 211 mod := variant.Module().(*ShTest) 212 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 213 expectedData := []string{ 214 "out/soong/.intermediates/bar/android_arm64_armv8-a/:bar", 215 // libbar has been relocated, and so has a variant that matches the host arch. 216 "out/soong/.intermediates/foo/" + buildOS + "_x86_64/relocated/:lib64/libbar.so", 217 } 218 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 219 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 220} 221 222func TestShTestHost_dataDeviceModulesAutogenTradefedConfig(t *testing.T) { 223 ctx, config := testShBinary(t, ` 224 sh_test_host { 225 name: "foo", 226 src: "test.sh", 227 data_device_bins: ["bar"], 228 data_device_libs: ["libbar"], 229 } 230 231 cc_binary { 232 name: "bar", 233 shared_libs: ["libbar"], 234 no_libcrt: true, 235 nocrt: true, 236 system_shared_libs: [], 237 stl: "none", 238 } 239 240 cc_library { 241 name: "libbar", 242 no_libcrt: true, 243 nocrt: true, 244 system_shared_libs: [], 245 stl: "none", 246 } 247 `) 248 249 buildOS := config.BuildOS.String() 250 fooModule := ctx.ModuleForTests("foo", buildOS+"_x86_64") 251 252 expectedBinAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />` 253 autogen := fooModule.Rule("autogen") 254 if !strings.Contains(autogen.Args["extraConfigs"], expectedBinAutogenConfig) { 255 t.Errorf("foo extraConfings %v does not contain %q", autogen.Args["extraConfigs"], expectedBinAutogenConfig) 256 } 257} 258