blob: 1510a033182915ce908de702722afd3e099e006b [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 Braunsteina186ac02024-08-07 13:03:05 -070043 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -080044 }
45
46 test_module_config {
47 name: "derived_test",
48 base: "base",
49 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
50 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +000051 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -080052 }
53
54`
55
56// Ensure we create files needed and set the AndroidMkEntries needed
57func TestModuleConfigAndroidTest(t *testing.T) {
58
59 ctx := android.GroupFixturePreparers(
60 java.PrepareForTestWithJavaDefaultModules,
61 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
62 ).RunTestWithBp(t, bp)
63
64 derived := ctx.ModuleForTests("derived_test", "android_common")
65 // Assert there are rules to create these files.
66 derived.Output("test_module_config.manifest")
67 derived.Output("test_config_fixer/derived_test.config")
68
69 // Ensure some basic rules exist.
70 ctx.ModuleForTests("base", "android_common").Output("package-res.apk")
71 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
72
73 // Ensure some entries from base are there, specifically support files for data and helper apps.
Ronald Braunstein01d31bd2024-06-02 07:07:02 -070074 // Do not use LOCAL_COMPATIBILITY_SUPPORT_FILES, but instead use LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES
75 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
76 []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
77 "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
78 "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
79 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
80 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
81
82 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_REQUIRED_MODULES"], []string{"base"})
83 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_CERTIFICATE"], []string{"build/make/target/product/security/testkey.x509.pem"})
84 android.AssertStringEquals(t, "", entries.Class, "APPS")
Ronald Braunsteinfce43162024-02-02 12:37:20 -080085
86 // And some new derived entries are there.
87 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"})
88
Priyanka Advanic6a321e2024-05-31 23:31:13 +000089 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 -070090
91 // Check the footer lines. Our support files should depend on base's support files.
92 convertedActual := make([]string, 5)
93 for i, e := range entries.FooterLinesForTests() {
94 // AssertStringPathsRelativeToTop doesn't replace both instances
95 convertedActual[i] = strings.Replace(e, ctx.Config.SoongOutDir(), "", 2)
96 }
97 android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.SoongOutDir()), convertedActual, []string{
98 "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk",
99 "/target/product/test_device/testcases/derived_test/arm64/base.apk: /target/product/test_device/testcases/base/arm64/base.apk",
100 "/target/product/test_device/testcases/derived_test/HelperApp.apk: /target/product/test_device/testcases/base/HelperApp.apk",
101 "/target/product/test_device/testcases/derived_test/data/testfile: /target/product/test_device/testcases/base/data/testfile",
102 "",
103 })
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800104}
105
106// Make sure we call test-config-fixer with the right args.
107func TestModuleConfigOptions(t *testing.T) {
108
109 ctx := android.GroupFixturePreparers(
110 java.PrepareForTestWithJavaDefaultModules,
111 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
112 ).RunTestWithBp(t, bp)
113
114 // Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
115 derived := ctx.ModuleForTests("derived_test", "android_common")
116 rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
117 android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700118 `--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 -0800119}
120
121// Ensure we error for a base we don't support.
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000122func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800123 badBp := `
124 java_test_host {
125 name: "base",
126 srcs: ["a.java"],
127 }
128
129 test_module_config {
130 name: "derived_test",
131 base: "base",
132 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
133 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000134 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800135 }`
136
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000137 android.GroupFixturePreparers(
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800138 java.PrepareForTestWithJavaDefaultModules,
139 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
140 ).ExtendWithErrorHandler(
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000141 android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800142 RunTestWithBp(t, badBp)
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000143}
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800144
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000145func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) {
146 badBp := `
147 java_library {
148 name: "base",
149 srcs: ["a.java"],
150 }
151
152 test_module_config {
153 name: "derived_test",
154 base: "base",
155 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
156 include_annotations: ["android.platform.test.annotations.LargeTest"],
157 test_suites: ["general-tests"],
158 }`
159
160 android.GroupFixturePreparers(
161 java.PrepareForTestWithJavaDefaultModules,
162 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
163 ).ExtendWithErrorHandler(
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700164 android.FixtureExpectsAtLeastOneErrorMatchingPattern("'base' module used as base but it is not a 'android_test' module.")).
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000165 RunTestWithBp(t, badBp)
166}
167
168func TestModuleConfigNoBaseShouldFail(t *testing.T) {
169 badBp := `
170 java_library {
171 name: "base",
172 srcs: ["a.java"],
173 }
174
175 test_module_config {
176 name: "derived_test",
177 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
178 include_annotations: ["android.platform.test.annotations.LargeTest"],
179 test_suites: ["general-tests"],
180 }`
181
182 android.GroupFixturePreparers(
183 java.PrepareForTestWithJavaDefaultModules,
184 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
185 ).ExtendWithErrorHandler(
186 android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")).
187 RunTestWithBp(t, badBp)
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800188}
189
190// Ensure we error for a base we don't support.
191func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) {
192 badBp := `
193 android_test {
194 name: "base",
195 sdk_version: "current",
196 srcs: ["a.java"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700197 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800198 }
199
200 test_module_config {
201 name: "derived_test",
202 base: "base",
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000203 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800204 }`
205
206 ctx := android.GroupFixturePreparers(
207 java.PrepareForTestWithJavaDefaultModules,
208 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
209 ).ExtendWithErrorHandler(
210 android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
211 RunTestWithBp(t, badBp)
212
213 ctx.ModuleForTests("derived_test", "android_common")
214}
215
216func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
217 multiBp := `
218 android_test {
219 name: "base",
220 sdk_version: "current",
221 srcs: ["a.java"],
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700222 data: [":HelperApp", "data/testfile"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700223 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800224 }
225
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700226 android_test_helper_app {
227 name: "HelperApp",
228 srcs: ["helper.java"],
229 }
230
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800231 test_module_config {
232 name: "derived_test",
233 base: "base",
234 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000235 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800236 }
237
238 test_module_config {
239 name: "another_derived_test",
240 base: "base",
241 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000242 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800243 }`
244
245 ctx := android.GroupFixturePreparers(
246 java.PrepareForTestWithJavaDefaultModules,
247 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
248 ).RunTestWithBp(t, multiBp)
249
250 {
251 derived := ctx.ModuleForTests("derived_test", "android_common")
252 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
253 // All these should be the same in both derived tests
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700254 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
255 []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
256 "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
257 "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
258 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
259
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800260 // Except this one, which points to the updated tradefed xml file.
261 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
262 // And this one, the module name.
263 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
264 }
265
266 {
267 derived := ctx.ModuleForTests("another_derived_test", "android_common")
268 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
269 // All these should be the same in both derived tests
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700270 android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
271 []string{"out/soong/target/product/test_device/testcases/another_derived_test/arm64/base.apk",
272 "out/soong/target/product/test_device/testcases/another_derived_test/HelperApp.apk",
273 "out/soong/target/product/test_device/testcases/another_derived_test/data/testfile"},
274 entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800275 // Except this one, which points to the updated tradefed xml file.
276 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config")
277 // And this one, the module name.
278 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"})
279 }
280}
281
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000282// Test_module_config_host rule is allowed to depend on java_test_host
283func TestModuleConfigHostBasics(t *testing.T) {
284 bp := `
285 java_test_host {
286 name: "base",
287 srcs: ["a.java"],
288 test_suites: ["suiteA", "general-tests", "suiteB"],
289 }
290
291 test_module_config_host {
292 name: "derived_test",
293 base: "base",
294 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
295 include_annotations: ["android.platform.test.annotations.LargeTest"],
296 test_suites: ["general-tests"],
297 }`
298
299 ctx := android.GroupFixturePreparers(
300 java.PrepareForTestWithJavaDefaultModules,
301 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
302 ).RunTestWithBp(t, bp)
303
304 variant := ctx.Config.BuildOS.String() + "_common"
305 derived := ctx.ModuleForTests("derived_test", variant)
306 mod := derived.Module().(*testModuleConfigHostModule)
307 allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
308 entries := allEntries[0]
309 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
Ronald Braunstein01d31bd2024-06-02 07:07:02 -0700310 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SDK_VERSION"], []string{"private_current"})
311 android.AssertStringEquals(t, "", entries.Class, "JAVA_LIBRARIES")
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000312
313 if !mod.Host() {
314 t.Errorf("host bit is not set for a java_test_host module.")
315 }
316 actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0])
317 android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData)
318
319}
320
321// When you pass an 'android_test' as base, the warning message is a bit obscure,
322// talking about variants, but it is something. Ideally we could do better.
323func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) {
324 badBp := `
325 android_test {
326 name: "base",
327 sdk_version: "current",
328 srcs: ["a.java"],
329 }
330
331 test_module_config_host {
332 name: "derived_test",
333 base: "base",
334 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
335 include_annotations: ["android.platform.test.annotations.LargeTest"],
336 }`
337
338 android.GroupFixturePreparers(
339 java.PrepareForTestWithJavaDefaultModules,
340 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
341 ).ExtendWithErrorHandler(
342 android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")).
343 RunTestWithBp(t, badBp)
344}
345
346func TestModuleConfigHostNeedsATestSuite(t *testing.T) {
347 badBp := `
348 java_test_host {
349 name: "base",
350 srcs: ["a.java"],
351 }
352
353 test_module_config_host {
354 name: "derived_test",
355 base: "base",
356 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
357 include_annotations: ["android.platform.test.annotations.LargeTest"],
358 }`
359
360 android.GroupFixturePreparers(
361 java.PrepareForTestWithJavaDefaultModules,
362 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
363 ).ExtendWithErrorHandler(
364 android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")).
365 RunTestWithBp(t, badBp)
366}
367
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700368func TestModuleConfigNonMatchingTestSuitesGiveErrors(t *testing.T) {
369 badBp := `
370 java_test_host {
371 name: "base",
372 srcs: ["a.java"],
373 test_suites: ["general-tests", "some-compat"],
374 }
375
376 test_module_config_host {
377 name: "derived_test",
378 base: "base",
379 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
380 include_annotations: ["android.platform.test.annotations.LargeTest"],
381 test_suites: ["device-tests", "random-suite"],
382 }`
383
384 android.GroupFixturePreparers(
385 java.PrepareForTestWithJavaDefaultModules,
386 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
387 ).ExtendWithErrorHandler(
388 // Use \\ to escape bracket so it isn't used as [] set for regex.
389 android.FixtureExpectsAtLeastOneErrorMatchingPattern("Suites: \\[device-tests, random-suite] listed but do not exist in base module")).
390 RunTestWithBp(t, badBp)
391}
392
Ronald Braunsteind2453462024-04-18 09:18:29 -0700393func TestTestOnlyProvider(t *testing.T) {
394 t.Parallel()
395 ctx := android.GroupFixturePreparers(
396 java.PrepareForTestWithJavaDefaultModules,
397 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
398 ).RunTestWithBp(t, `
399 // These should be test-only
400 test_module_config_host {
401 name: "host-derived-test",
402 base: "host-base",
403 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
404 include_annotations: ["android.platform.test.annotations.LargeTest"],
405 test_suites: ["general-tests"],
406 }
407
408 test_module_config {
409 name: "derived-test",
410 base: "base",
411 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
412 include_annotations: ["android.platform.test.annotations.LargeTest"],
413 test_suites: ["general-tests"],
414 }
415
416 android_test {
417 name: "base",
418 sdk_version: "current",
419 data: ["data/testfile"],
Ronald Braunsteina186ac02024-08-07 13:03:05 -0700420 test_suites: ["general-tests"],
Ronald Braunsteind2453462024-04-18 09:18:29 -0700421 }
422
423 java_test_host {
424 name: "host-base",
425 srcs: ["a.java"],
426 test_suites: ["general-tests"],
427 }`,
428 )
429
430 // Visit all modules and ensure only the ones that should
431 // marked as test-only are marked as test-only.
432
433 actualTestOnly := []string{}
434 ctx.VisitAllModules(func(m blueprint.Module) {
435 if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
436 if provider.TestOnly {
437 actualTestOnly = append(actualTestOnly, m.Name())
438 }
439 }
440 })
441 expectedTestOnlyModules := []string{
442 "host-derived-test",
443 "derived-test",
444 // android_test and java_test_host are tests too.
445 "host-base",
446 "base",
447 }
448
449 notEqual, left, right := android.ListSetDifference(expectedTestOnlyModules, actualTestOnly)
450 if notEqual {
451 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
452 }
453}