blob: f76a152eb06604052aabb5fcfeaef6262edfc0ea [file] [log] [blame]
Ronald Braunsteinfce43162024-02-02 12:37:20 -08001// Copyright 2024 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package tradefed_modules
15
16import (
17 "android/soong/android"
18 "android/soong/java"
Ronald Braunstein01d31bd2024-06-02 07:07:02 -070019 "fmt"
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +000020 "strconv"
Ronald Braunsteinfce43162024-02-02 12:37:20 -080021 "strings"
22 "testing"
Ronald Braunsteind2453462024-04-18 09:18:29 -070023
24 "github.com/google/blueprint"
Ronald Braunsteinfce43162024-02-02 12:37:20 -080025)
26
27const bp = `
28 android_app {
29 name: "foo",
30 srcs: ["a.java"],
31 sdk_version: "current",
32 }
33
34 android_test_helper_app {
35 name: "HelperApp",
36 srcs: ["helper.java"],
37 }
38
39 android_test {
40 name: "base",
41 sdk_version: "current",
42 data: [":HelperApp", "data/testfile"],
Ronald Braunstein5c647d82024-09-19 23:14:34 +000043 host_required: ["other-module"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -070044 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -080045 }
46
47 test_module_config {
48 name: "derived_test",
49 base: "base",
50 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
51 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +000052 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -080053 }
54
55`
56
57// Ensure we create files needed and set the AndroidMkEntries needed
58func TestModuleConfigAndroidTest(t *testing.T) {
59
60 ctx := android.GroupFixturePreparers(
61 java.PrepareForTestWithJavaDefaultModules,
62 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
63 ).RunTestWithBp(t, bp)
64
65 derived := ctx.ModuleForTests("derived_test", "android_common")
66 // Assert there are rules to create these files.
67 derived.Output("test_module_config.manifest")
68 derived.Output("test_config_fixer/derived_test.config")
69
70 // Ensure some basic rules exist.
71 ctx.ModuleForTests("base", "android_common").Output("package-res.apk")
72 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
73
74 // Ensure some entries from base are there, specifically support files for data and helper apps.
Ronald Braunstein01d31bd2024-06-02 07:07:02 -070075 // Do not use LOCAL_COMPATIBILITY_SUPPORT_FILES, but instead use LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES
76 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
77 []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
78 "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
79 "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
80 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
81 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
82
83 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_REQUIRED_MODULES"], []string{"base"})
Ronald Braunstein5c647d82024-09-19 23:14:34 +000084 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_HOST_REQUIRED_MODULES"], []string{"other-module"})
Ronald Braunstein01d31bd2024-06-02 07:07:02 -070085 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_CERTIFICATE"], []string{"build/make/target/product/security/testkey.x509.pem"})
86 android.AssertStringEquals(t, "", entries.Class, "APPS")
Ronald Braunsteinfce43162024-02-02 12:37:20 -080087
88 // And some new derived entries are there.
89 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"})
90
Priyanka Advanic6a321e2024-05-31 23:31:13 +000091 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
Ronald Braunstein01d31bd2024-06-02 07:07:02 -070092
93 // Check the footer lines. Our support files should depend on base's support files.
94 convertedActual := make([]string, 5)
95 for i, e := range entries.FooterLinesForTests() {
96 // AssertStringPathsRelativeToTop doesn't replace both instances
97 convertedActual[i] = strings.Replace(e, ctx.Config.SoongOutDir(), "", 2)
98 }
99 android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.SoongOutDir()), convertedActual, []string{
100 "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk",
101 "/target/product/test_device/testcases/derived_test/arm64/base.apk: /target/product/test_device/testcases/base/arm64/base.apk",
102 "/target/product/test_device/testcases/derived_test/HelperApp.apk: /target/product/test_device/testcases/base/HelperApp.apk",
103 "/target/product/test_device/testcases/derived_test/data/testfile: /target/product/test_device/testcases/base/data/testfile",
104 "",
105 })
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800106}
107
108// Make sure we call test-config-fixer with the right args.
109func TestModuleConfigOptions(t *testing.T) {
110
111 ctx := android.GroupFixturePreparers(
112 java.PrepareForTestWithJavaDefaultModules,
113 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
114 ).RunTestWithBp(t, bp)
115
116 // Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
117 derived := ctx.ModuleForTests("derived_test", "android_common")
118 rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
119 android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700120 `--test-runner-options='[{"Name":"exclude-filter","Key":"","Value":"android.test.example.devcodelab.DevCodelabTest#testHelloFail"},{"Name":"include-annotation","Key":"","Value":"android.platform.test.annotations.LargeTest"}]'`)
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800121}
122
123// Ensure we error for a base we don't support.
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000124func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800125 badBp := `
126 java_test_host {
127 name: "base",
128 srcs: ["a.java"],
129 }
130
131 test_module_config {
132 name: "derived_test",
133 base: "base",
134 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
135 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000136 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800137 }`
138
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000139 android.GroupFixturePreparers(
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800140 java.PrepareForTestWithJavaDefaultModules,
141 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
142 ).ExtendWithErrorHandler(
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000143 android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800144 RunTestWithBp(t, badBp)
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000145}
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800146
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000147func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) {
148 badBp := `
149 java_library {
150 name: "base",
151 srcs: ["a.java"],
152 }
153
154 test_module_config {
155 name: "derived_test",
156 base: "base",
157 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
158 include_annotations: ["android.platform.test.annotations.LargeTest"],
159 test_suites: ["general-tests"],
160 }`
161
162 android.GroupFixturePreparers(
163 java.PrepareForTestWithJavaDefaultModules,
164 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
165 ).ExtendWithErrorHandler(
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700166 android.FixtureExpectsAtLeastOneErrorMatchingPattern("'base' module used as base but it is not a 'android_test' module.")).
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000167 RunTestWithBp(t, badBp)
168}
169
170func TestModuleConfigNoBaseShouldFail(t *testing.T) {
171 badBp := `
172 java_library {
173 name: "base",
174 srcs: ["a.java"],
175 }
176
177 test_module_config {
178 name: "derived_test",
179 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
180 include_annotations: ["android.platform.test.annotations.LargeTest"],
181 test_suites: ["general-tests"],
182 }`
183
184 android.GroupFixturePreparers(
185 java.PrepareForTestWithJavaDefaultModules,
186 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
187 ).ExtendWithErrorHandler(
188 android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")).
189 RunTestWithBp(t, badBp)
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800190}
191
192// Ensure we error for a base we don't support.
193func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) {
194 badBp := `
195 android_test {
196 name: "base",
197 sdk_version: "current",
198 srcs: ["a.java"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700199 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800200 }
201
202 test_module_config {
203 name: "derived_test",
204 base: "base",
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000205 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800206 }`
207
208 ctx := android.GroupFixturePreparers(
209 java.PrepareForTestWithJavaDefaultModules,
210 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
211 ).ExtendWithErrorHandler(
212 android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
213 RunTestWithBp(t, badBp)
214
215 ctx.ModuleForTests("derived_test", "android_common")
216}
217
218func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
219 multiBp := `
220 android_test {
221 name: "base",
222 sdk_version: "current",
223 srcs: ["a.java"],
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700224 data: [":HelperApp", "data/testfile"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700225 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800226 }
227
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700228 android_test_helper_app {
229 name: "HelperApp",
230 srcs: ["helper.java"],
231 }
232
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800233 test_module_config {
234 name: "derived_test",
235 base: "base",
236 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000237 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800238 }
239
240 test_module_config {
241 name: "another_derived_test",
242 base: "base",
243 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000244 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800245 }`
246
247 ctx := android.GroupFixturePreparers(
248 java.PrepareForTestWithJavaDefaultModules,
249 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
250 ).RunTestWithBp(t, multiBp)
251
252 {
253 derived := ctx.ModuleForTests("derived_test", "android_common")
254 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
255 // All these should be the same in both derived tests
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700256 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
257 []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
258 "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
259 "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
260 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
261
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800262 // Except this one, which points to the updated tradefed xml file.
263 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
264 // And this one, the module name.
265 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
266 }
267
268 {
269 derived := ctx.ModuleForTests("another_derived_test", "android_common")
270 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
271 // All these should be the same in both derived tests
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700272 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
273 []string{"out/soong/target/product/test_device/testcases/another_derived_test/arm64/base.apk",
274 "out/soong/target/product/test_device/testcases/another_derived_test/HelperApp.apk",
275 "out/soong/target/product/test_device/testcases/another_derived_test/data/testfile"},
276 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800277 // Except this one, which points to the updated tradefed xml file.
278 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config")
279 // And this one, the module name.
280 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"})
281 }
282}
283
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000284// Test_module_config_host rule is allowed to depend on java_test_host
285func TestModuleConfigHostBasics(t *testing.T) {
286 bp := `
287 java_test_host {
288 name: "base",
289 srcs: ["a.java"],
290 test_suites: ["suiteA", "general-tests", "suiteB"],
291 }
292
293 test_module_config_host {
294 name: "derived_test",
295 base: "base",
296 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
297 include_annotations: ["android.platform.test.annotations.LargeTest"],
298 test_suites: ["general-tests"],
299 }`
300
301 ctx := android.GroupFixturePreparers(
302 java.PrepareForTestWithJavaDefaultModules,
303 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
304 ).RunTestWithBp(t, bp)
305
306 variant := ctx.Config.BuildOS.String() + "_common"
307 derived := ctx.ModuleForTests("derived_test", variant)
308 mod := derived.Module().(*testModuleConfigHostModule)
309 allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
310 entries := allEntries[0]
311 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700312 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SDK_VERSION"], []string{"private_current"})
313 android.AssertStringEquals(t, "", entries.Class, "JAVA_LIBRARIES")
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000314
315 if !mod.Host() {
316 t.Errorf("host bit is not set for a java_test_host module.")
317 }
318 actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0])
319 android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData)
320
321}
322
323// When you pass an 'android_test' as base, the warning message is a bit obscure,
324// talking about variants, but it is something. Ideally we could do better.
325func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) {
326 badBp := `
327 android_test {
328 name: "base",
329 sdk_version: "current",
330 srcs: ["a.java"],
331 }
332
333 test_module_config_host {
334 name: "derived_test",
335 base: "base",
336 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
337 include_annotations: ["android.platform.test.annotations.LargeTest"],
338 }`
339
340 android.GroupFixturePreparers(
341 java.PrepareForTestWithJavaDefaultModules,
342 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
343 ).ExtendWithErrorHandler(
344 android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")).
345 RunTestWithBp(t, badBp)
346}
347
348func TestModuleConfigHostNeedsATestSuite(t *testing.T) {
349 badBp := `
350 java_test_host {
351 name: "base",
352 srcs: ["a.java"],
353 }
354
355 test_module_config_host {
356 name: "derived_test",
357 base: "base",
358 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
359 include_annotations: ["android.platform.test.annotations.LargeTest"],
360 }`
361
362 android.GroupFixturePreparers(
363 java.PrepareForTestWithJavaDefaultModules,
364 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
365 ).ExtendWithErrorHandler(
366 android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")).
367 RunTestWithBp(t, badBp)
368}
369
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700370func TestModuleConfigNonMatchingTestSuitesGiveErrors(t *testing.T) {
371 badBp := `
372 java_test_host {
373 name: "base",
374 srcs: ["a.java"],
375 test_suites: ["general-tests", "some-compat"],
376 }
377
378 test_module_config_host {
379 name: "derived_test",
380 base: "base",
381 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
382 include_annotations: ["android.platform.test.annotations.LargeTest"],
383 test_suites: ["device-tests", "random-suite"],
384 }`
385
386 android.GroupFixturePreparers(
387 java.PrepareForTestWithJavaDefaultModules,
388 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
389 ).ExtendWithErrorHandler(
390 // Use \\ to escape bracket so it isn't used as [] set for regex.
391 android.FixtureExpectsAtLeastOneErrorMatchingPattern("Suites: \\[device-tests, random-suite] listed but do not exist in base module")).
392 RunTestWithBp(t, badBp)
393}
394
Ronald Braunsteind2453462024-04-18 09:18:29 -0700395func TestTestOnlyProvider(t *testing.T) {
396 t.Parallel()
397 ctx := android.GroupFixturePreparers(
398 java.PrepareForTestWithJavaDefaultModules,
399 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
400 ).RunTestWithBp(t, `
401 // These should be test-only
402 test_module_config_host {
403 name: "host-derived-test",
404 base: "host-base",
405 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
406 include_annotations: ["android.platform.test.annotations.LargeTest"],
407 test_suites: ["general-tests"],
408 }
409
410 test_module_config {
411 name: "derived-test",
412 base: "base",
413 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
414 include_annotations: ["android.platform.test.annotations.LargeTest"],
415 test_suites: ["general-tests"],
416 }
417
418 android_test {
419 name: "base",
420 sdk_version: "current",
421 data: ["data/testfile"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700422 test_suites: ["general-tests"],
Ronald Braunsteind2453462024-04-18 09:18:29 -0700423 }
424
425 java_test_host {
426 name: "host-base",
427 srcs: ["a.java"],
428 test_suites: ["general-tests"],
429 }`,
430 )
431
432 // Visit all modules and ensure only the ones that should
433 // marked as test-only are marked as test-only.
434
435 actualTestOnly := []string{}
436 ctx.VisitAllModules(func(m blueprint.Module) {
437 if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
438 if provider.TestOnly {
439 actualTestOnly = append(actualTestOnly, m.Name())
440 }
441 }
442 })
443 expectedTestOnlyModules := []string{
444 "host-derived-test",
445 "derived-test",
446 // android_test and java_test_host are tests too.
447 "host-base",
448 "base",
449 }
450
451 notEqual, left, right := android.ListSetDifference(expectedTestOnlyModules, actualTestOnly)
452 if notEqual {
453 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
454 }
455}