• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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