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 "android/soong/java" 13) 14 15func TestMain(m *testing.M) { 16 os.Exit(m.Run()) 17} 18 19var prepareForShTest = android.GroupFixturePreparers( 20 cc.PrepareForTestWithCcBuildComponents, 21 java.PrepareForTestWithJavaDefaultModules, 22 PrepareForTestWithShBuildComponents, 23 android.FixtureMergeMockFs(android.MockFS{ 24 "test.sh": nil, 25 "testdata/data1": nil, 26 "testdata/sub/data2": nil, 27 }), 28) 29 30// testShBinary runs tests using the prepareForShTest 31// 32// Do not add any new usages of this, instead use the prepareForShTest directly as it makes it much 33// easier to customize the test behavior. 34// 35// If it is necessary to customize the behavior of an existing test that uses this then please first 36// convert the test to using prepareForShTest first and then in a following change add the 37// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify 38// that it did not change the test behavior unexpectedly. 39// 40// deprecated 41func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) { 42 bp = bp + cc.GatherRequiredDepsForTest(android.Android) 43 44 result := prepareForShTest.RunTestWithBp(t, bp) 45 46 return result.TestContext, result.Config 47} 48 49func TestShTestSubDir(t *testing.T) { 50 result := android.GroupFixturePreparers( 51 prepareForShTest, 52 android.FixtureModifyConfig(android.SetKatiEnabledForTests), 53 ).RunTestWithBp(t, ` 54 sh_test { 55 name: "foo", 56 src: "test.sh", 57 sub_dir: "foo_test" 58 } 59 `) 60 61 mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) 62 63 entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] 64 65 expectedPath := "out/target/product/test_device/data/nativetest64/foo_test" 66 actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] 67 android.AssertStringPathRelativeToTopEquals(t, "LOCAL_MODULE_PATH[0]", result.Config, expectedPath, actualPath) 68} 69 70func TestShTest(t *testing.T) { 71 result := android.GroupFixturePreparers( 72 prepareForShTest, 73 android.FixtureModifyConfig(android.SetKatiEnabledForTests), 74 ).RunTestWithBp(t, ` 75 sh_test { 76 name: "foo", 77 src: "test.sh", 78 filename: "test.sh", 79 data: [ 80 "testdata/data1", 81 "testdata/sub/data2", 82 ], 83 } 84 `) 85 86 mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) 87 88 entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] 89 90 expectedPath := "out/target/product/test_device/data/nativetest64/foo" 91 actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0] 92 android.AssertStringPathRelativeToTopEquals(t, "LOCAL_MODULE_PATH[0]", result.Config, expectedPath, actualPath) 93 94 expectedData := []string{":testdata/data1", ":testdata/sub/data2"} 95 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 96 android.AssertDeepEquals(t, "LOCAL_TEST_DATA", expectedData, actualData) 97} 98 99func TestShTest_dataModules(t *testing.T) { 100 ctx, config := testShBinary(t, ` 101 sh_test { 102 name: "foo", 103 src: "test.sh", 104 host_supported: true, 105 data_bins: ["bar"], 106 data_libs: ["libbar"], 107 } 108 109 cc_binary { 110 name: "bar", 111 host_supported: true, 112 shared_libs: ["libbar"], 113 no_libcrt: true, 114 nocrt: true, 115 system_shared_libs: [], 116 stl: "none", 117 } 118 119 cc_library { 120 name: "libbar", 121 host_supported: true, 122 no_libcrt: true, 123 nocrt: true, 124 system_shared_libs: [], 125 stl: "none", 126 } 127 `) 128 129 buildOS := config.BuildOS.String() 130 arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"} 131 for _, arch := range arches { 132 variant := ctx.ModuleForTests("foo", arch) 133 134 libExt := ".so" 135 if arch == "darwin_x86_64" { 136 libExt = ".dylib" 137 } 138 relocated := variant.Output(filepath.Join("out/soong/.intermediates/foo", arch, "relocated/lib64/libbar"+libExt)) 139 expectedInput := "out/soong/.intermediates/libbar/" + arch + "_shared/libbar" + libExt 140 android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) 141 142 mod := variant.Module().(*ShTest) 143 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 144 expectedData := []string{ 145 filepath.Join("out/soong/.intermediates/bar", arch, ":bar"), 146 filepath.Join("out/soong/.intermediates/foo", arch, "relocated/:lib64/libbar"+libExt), 147 } 148 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 149 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 150 } 151} 152 153func TestShTestHost(t *testing.T) { 154 ctx, _ := testShBinary(t, ` 155 sh_test_host { 156 name: "foo", 157 src: "test.sh", 158 filename: "test.sh", 159 data: [ 160 "testdata/data1", 161 "testdata/sub/data2", 162 ], 163 test_options: { 164 unit_test: true, 165 }, 166 } 167 `) 168 169 buildOS := ctx.Config().BuildOS.String() 170 mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest) 171 if !mod.Host() { 172 t.Errorf("host bit is not set for a sh_test_host module.") 173 } 174 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 175 actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0]) 176 android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData) 177} 178 179func TestShTestExtraTestConfig(t *testing.T) { 180 result, _ := testShBinary(t, ` 181 sh_test { 182 name: "foo", 183 src: "test.sh", 184 filename: "test.sh", 185 extra_test_configs: ["config1.xml", "config2.xml"], 186 } 187 `) 188 189 mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest) 190 entries := android.AndroidMkEntriesForTest(t, result, mod)[0] 191 actualData := entries.EntryMap["LOCAL_EXTRA_FULL_TEST_CONFIGS"] 192 android.AssertStringPathsRelativeToTopEquals(t, "extra_configs", result.Config(), []string{"config1.xml", "config2.xml"}, actualData) 193} 194 195func TestShTestHost_dataDeviceModules(t *testing.T) { 196 ctx, config := testShBinary(t, ` 197 sh_test_host { 198 name: "foo", 199 src: "test.sh", 200 data_device_bins: ["bar"], 201 data_device_libs: ["libbar"], 202 } 203 204 cc_binary { 205 name: "bar", 206 shared_libs: ["libbar"], 207 no_libcrt: true, 208 nocrt: true, 209 system_shared_libs: [], 210 stl: "none", 211 } 212 213 cc_library { 214 name: "libbar", 215 no_libcrt: true, 216 nocrt: true, 217 system_shared_libs: [], 218 stl: "none", 219 } 220 `) 221 222 buildOS := config.BuildOS.String() 223 variant := buildOS + "_x86_64" 224 foo := ctx.ModuleForTests("foo", variant) 225 226 relocated := foo.Output(filepath.Join("out/soong/.intermediates/foo", variant, "relocated/lib64/libbar.so")) 227 expectedInput := "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so" 228 android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) 229 230 mod := foo.Module().(*ShTest) 231 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 232 expectedData := []string{ 233 "out/soong/.intermediates/bar/android_arm64_armv8-a/:bar", 234 // libbar has been relocated, and so has a variant that matches the host arch. 235 "out/soong/.intermediates/foo/" + variant + "/relocated/:lib64/libbar.so", 236 } 237 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 238 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 239} 240 241func TestShTestHost_dataDeviceModulesAutogenTradefedConfig(t *testing.T) { 242 ctx, config := testShBinary(t, ` 243 sh_test_host { 244 name: "foo", 245 src: "test.sh", 246 data_device_bins: ["bar"], 247 data_device_libs: ["libbar"], 248 } 249 250 cc_binary { 251 name: "bar", 252 shared_libs: ["libbar"], 253 no_libcrt: true, 254 nocrt: true, 255 system_shared_libs: [], 256 stl: "none", 257 } 258 259 cc_library { 260 name: "libbar", 261 no_libcrt: true, 262 nocrt: true, 263 system_shared_libs: [], 264 stl: "none", 265 } 266 `) 267 268 buildOS := config.BuildOS.String() 269 fooModule := ctx.ModuleForTests("foo", buildOS+"_x86_64") 270 271 expectedBinAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />` 272 autogen := fooModule.Rule("autogen") 273 if !strings.Contains(autogen.Args["extraConfigs"], expectedBinAutogenConfig) { 274 t.Errorf("foo extraConfings %v does not contain %q", autogen.Args["extraConfigs"], expectedBinAutogenConfig) 275 } 276} 277 278func TestShTestHost_javaData(t *testing.T) { 279 ctx, config := testShBinary(t, ` 280 sh_test_host { 281 name: "foo", 282 src: "test.sh", 283 filename: "test.sh", 284 data: [ 285 "testdata/data1", 286 "testdata/sub/data2", 287 ], 288 java_data: [ 289 "javalib", 290 ], 291 } 292 293 java_library_host { 294 name: "javalib", 295 srcs: [], 296 } 297 `) 298 buildOS := ctx.Config().BuildOS.String() 299 mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest) 300 if !mod.Host() { 301 t.Errorf("host bit is not set for a sh_test_host module.") 302 } 303 expectedData := []string{ 304 ":testdata/data1", 305 ":testdata/sub/data2", 306 "out/soong/.intermediates/javalib/" + buildOS + "_common/combined/:javalib.jar", 307 } 308 309 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 310 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 311 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 312} 313 314func TestDefaultsForTests(t *testing.T) { 315 ctx, config := testShBinary(t, ` 316 sh_defaults { 317 name: "defaults", 318 src: "test.sh", 319 filename: "test.sh", 320 data: [ 321 "testdata/data1", 322 "testdata/sub/data2", 323 ], 324 } 325 sh_test_host { 326 name: "foo", 327 defaults: ["defaults"], 328 data: [ 329 "testdata/more_data", 330 ], 331 java_data: [ 332 "javalib", 333 ], 334 } 335 336 java_library_host { 337 name: "javalib", 338 srcs: [], 339 } 340 341 sh_test { 342 name: "sh-test", 343 defaults: ["defaults"], 344 } 345 346 `) 347 buildOS := ctx.Config().BuildOS.String() 348 mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest) 349 if !mod.Host() { 350 t.Errorf("host bit is not set for a sh_test_host module.") 351 } 352 expectedData := []string{ 353 ":testdata/data1", 354 ":testdata/sub/data2", 355 ":testdata/more_data", 356 "out/soong/.intermediates/javalib/" + buildOS + "_common/combined/:javalib.jar", 357 } 358 359 entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] 360 actualData := entries.EntryMap["LOCAL_TEST_DATA"] 361 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 362 363 // Just the defaults 364 expectedData = []string{ 365 ":testdata/data1", 366 ":testdata/sub/data2", 367 } 368 mod = ctx.ModuleForTests("sh-test", "android_arm64_armv8-a").Module().(*ShTest) 369 entries = android.AndroidMkEntriesForTest(t, ctx, mod)[0] 370 actualData = entries.EntryMap["LOCAL_TEST_DATA"] 371 android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData) 372} 373 374func TestDefaultsForBinaries(t *testing.T) { 375 ctx, _ := testShBinary(t, ` 376 sh_defaults { 377 name: "defaults", 378 src: "test.sh", 379 filename: "test.sh", 380 } 381 sh_binary_host { 382 name: "the-host-binary", 383 defaults: ["defaults"], 384 } 385 sh_binary{ 386 name: "the-binary", 387 defaults: ["defaults"], 388 } 389 `) 390 buildOS := ctx.Config().BuildOS.String() 391 mod := ctx.ModuleForTests("the-host-binary", buildOS+"_x86_64").Module().(*ShBinary) 392 if !mod.Host() { 393 t.Errorf("host bit is not set for a sh_binary_host module.") 394 } 395 396 expectedFilename := "test.sh" 397 android.AssertStringEquals(t, "Filename", expectedFilename, *mod.properties.Filename) 398 399 mod = ctx.ModuleForTests("the-binary", "android_arm64_armv8-a").Module().(*ShBinary) 400 android.AssertStringEquals(t, "Filename", expectedFilename, *mod.properties.Filename) 401} 402