blob: 6997228cee83260d6601b0b7c21ed66c3a3c9b6d [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 Braunstein1a6e7c02024-03-14 21:14:39 +000019 "strconv"
Ronald Braunsteinfce43162024-02-02 12:37:20 -080020 "strings"
21 "testing"
Ronald Braunsteind2453462024-04-18 09:18:29 -070022
23 "github.com/google/blueprint"
Ronald Braunsteinfce43162024-02-02 12:37:20 -080024)
25
26const bp = `
27 android_app {
28 name: "foo",
29 srcs: ["a.java"],
30 sdk_version: "current",
31 }
32
33 android_test_helper_app {
34 name: "HelperApp",
35 srcs: ["helper.java"],
36 }
37
38 android_test {
39 name: "base",
40 sdk_version: "current",
41 data: [":HelperApp", "data/testfile"],
42 }
43
44 test_module_config {
45 name: "derived_test",
46 base: "base",
47 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
48 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +000049 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -080050 }
51
52`
53
54// Ensure we create files needed and set the AndroidMkEntries needed
55func TestModuleConfigAndroidTest(t *testing.T) {
56
57 ctx := android.GroupFixturePreparers(
58 java.PrepareForTestWithJavaDefaultModules,
59 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
60 ).RunTestWithBp(t, bp)
61
62 derived := ctx.ModuleForTests("derived_test", "android_common")
63 // Assert there are rules to create these files.
64 derived.Output("test_module_config.manifest")
65 derived.Output("test_config_fixer/derived_test.config")
66
67 // Ensure some basic rules exist.
68 ctx.ModuleForTests("base", "android_common").Output("package-res.apk")
69 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
70
71 // Ensure some entries from base are there, specifically support files for data and helper apps.
72 assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
73
74 // And some new derived entries are there.
75 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"})
76
77 // And ones we override
78 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
79
80 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
81}
82
83// Make sure we call test-config-fixer with the right args.
84func TestModuleConfigOptions(t *testing.T) {
85
86 ctx := android.GroupFixturePreparers(
87 java.PrepareForTestWithJavaDefaultModules,
88 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
89 ).RunTestWithBp(t, bp)
90
91 // Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
92 derived := ctx.ModuleForTests("derived_test", "android_common")
93 rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
94 android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
95 `--test-file-name=derived_test.apk --orig-test-file-name=base.apk --test-runner-options='[{"Name":"exclude-filter","Key":"","Value":"android.test.example.devcodelab.DevCodelabTest#testHelloFail"},{"Name":"include-annotation","Key":"","Value":"android.platform.test.annotations.LargeTest"}]'`)
96}
97
98// Ensure we error for a base we don't support.
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +000099func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800100 badBp := `
101 java_test_host {
102 name: "base",
103 srcs: ["a.java"],
104 }
105
106 test_module_config {
107 name: "derived_test",
108 base: "base",
109 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
110 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000111 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800112 }`
113
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000114 android.GroupFixturePreparers(
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800115 java.PrepareForTestWithJavaDefaultModules,
116 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
117 ).ExtendWithErrorHandler(
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000118 android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800119 RunTestWithBp(t, badBp)
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000120}
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800121
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000122func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) {
123 badBp := `
124 java_library {
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"],
134 test_suites: ["general-tests"],
135 }`
136
137 android.GroupFixturePreparers(
138 java.PrepareForTestWithJavaDefaultModules,
139 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
140 ).ExtendWithErrorHandler(
141 android.FixtureExpectsOneErrorPattern("'base' module used as base but it is not a 'android_test' module.")).
142 RunTestWithBp(t, badBp)
143}
144
145func TestModuleConfigNoBaseShouldFail(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 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
155 include_annotations: ["android.platform.test.annotations.LargeTest"],
156 test_suites: ["general-tests"],
157 }`
158
159 android.GroupFixturePreparers(
160 java.PrepareForTestWithJavaDefaultModules,
161 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
162 ).ExtendWithErrorHandler(
163 android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")).
164 RunTestWithBp(t, badBp)
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800165}
166
167// Ensure we error for a base we don't support.
168func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) {
169 badBp := `
170 android_test {
171 name: "base",
172 sdk_version: "current",
173 srcs: ["a.java"],
174 }
175
176 test_module_config {
177 name: "derived_test",
178 base: "base",
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000179 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800180 }`
181
182 ctx := android.GroupFixturePreparers(
183 java.PrepareForTestWithJavaDefaultModules,
184 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
185 ).ExtendWithErrorHandler(
186 android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
187 RunTestWithBp(t, badBp)
188
189 ctx.ModuleForTests("derived_test", "android_common")
190}
191
192func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
193 multiBp := `
194 android_test {
195 name: "base",
196 sdk_version: "current",
197 srcs: ["a.java"],
198 }
199
200 test_module_config {
201 name: "derived_test",
202 base: "base",
203 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000204 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800205 }
206
207 test_module_config {
208 name: "another_derived_test",
209 base: "base",
210 include_annotations: ["android.platform.test.annotations.LargeTest"],
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000211 test_suites: ["general-tests"],
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800212 }`
213
214 ctx := android.GroupFixturePreparers(
215 java.PrepareForTestWithJavaDefaultModules,
216 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
217 ).RunTestWithBp(t, multiBp)
218
219 {
220 derived := ctx.ModuleForTests("derived_test", "android_common")
221 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
222 // All these should be the same in both derived tests
223 assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
224 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
225 // Except this one, which points to the updated tradefed xml file.
226 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
227 // And this one, the module name.
228 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
229 }
230
231 {
232 derived := ctx.ModuleForTests("another_derived_test", "android_common")
233 entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
234 // All these should be the same in both derived tests
235 assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
236 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
237 // Except this one, which points to the updated tradefed xml file.
238 android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config")
239 // And this one, the module name.
240 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"})
241 }
242}
243
Ronald Braunstein1a6e7c02024-03-14 21:14:39 +0000244// Test_module_config_host rule is allowed to depend on java_test_host
245func TestModuleConfigHostBasics(t *testing.T) {
246 bp := `
247 java_test_host {
248 name: "base",
249 srcs: ["a.java"],
250 test_suites: ["suiteA", "general-tests", "suiteB"],
251 }
252
253 test_module_config_host {
254 name: "derived_test",
255 base: "base",
256 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
257 include_annotations: ["android.platform.test.annotations.LargeTest"],
258 test_suites: ["general-tests"],
259 }`
260
261 ctx := android.GroupFixturePreparers(
262 java.PrepareForTestWithJavaDefaultModules,
263 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
264 ).RunTestWithBp(t, bp)
265
266 variant := ctx.Config.BuildOS.String() + "_common"
267 derived := ctx.ModuleForTests("derived_test", variant)
268 mod := derived.Module().(*testModuleConfigHostModule)
269 allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
270 entries := allEntries[0]
271 android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
272
273 if !mod.Host() {
274 t.Errorf("host bit is not set for a java_test_host module.")
275 }
276 actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0])
277 android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData)
278
279}
280
281// When you pass an 'android_test' as base, the warning message is a bit obscure,
282// talking about variants, but it is something. Ideally we could do better.
283func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) {
284 badBp := `
285 android_test {
286 name: "base",
287 sdk_version: "current",
288 srcs: ["a.java"],
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 }`
297
298 android.GroupFixturePreparers(
299 java.PrepareForTestWithJavaDefaultModules,
300 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
301 ).ExtendWithErrorHandler(
302 android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")).
303 RunTestWithBp(t, badBp)
304}
305
306func TestModuleConfigHostNeedsATestSuite(t *testing.T) {
307 badBp := `
308 java_test_host {
309 name: "base",
310 srcs: ["a.java"],
311 }
312
313 test_module_config_host {
314 name: "derived_test",
315 base: "base",
316 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
317 include_annotations: ["android.platform.test.annotations.LargeTest"],
318 }`
319
320 android.GroupFixturePreparers(
321 java.PrepareForTestWithJavaDefaultModules,
322 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
323 ).ExtendWithErrorHandler(
324 android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")).
325 RunTestWithBp(t, badBp)
326}
327
328func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) {
329 badBp := `
330 java_test_host {
331 name: "base",
332 srcs: ["a.java"],
333 test_suites: ["general-tests", "some-compat"],
334 }
335
336 test_module_config_host {
337 name: "derived_test",
338 base: "base",
339 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
340 include_annotations: ["android.platform.test.annotations.LargeTest"],
341 test_suites: ["general-tests", "some-compat"],
342 }`
343
344 android.GroupFixturePreparers(
345 java.PrepareForTestWithJavaDefaultModules,
346 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
347 ).ExtendWithErrorHandler(
348 android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")).
349 RunTestWithBp(t, badBp)
350}
351
Ronald Braunsteind2453462024-04-18 09:18:29 -0700352func TestTestOnlyProvider(t *testing.T) {
353 t.Parallel()
354 ctx := android.GroupFixturePreparers(
355 java.PrepareForTestWithJavaDefaultModules,
356 android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
357 ).RunTestWithBp(t, `
358 // These should be test-only
359 test_module_config_host {
360 name: "host-derived-test",
361 base: "host-base",
362 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
363 include_annotations: ["android.platform.test.annotations.LargeTest"],
364 test_suites: ["general-tests"],
365 }
366
367 test_module_config {
368 name: "derived-test",
369 base: "base",
370 exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
371 include_annotations: ["android.platform.test.annotations.LargeTest"],
372 test_suites: ["general-tests"],
373 }
374
375 android_test {
376 name: "base",
377 sdk_version: "current",
378 data: ["data/testfile"],
379 }
380
381 java_test_host {
382 name: "host-base",
383 srcs: ["a.java"],
384 test_suites: ["general-tests"],
385 }`,
386 )
387
388 // Visit all modules and ensure only the ones that should
389 // marked as test-only are marked as test-only.
390
391 actualTestOnly := []string{}
392 ctx.VisitAllModules(func(m blueprint.Module) {
393 if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
394 if provider.TestOnly {
395 actualTestOnly = append(actualTestOnly, m.Name())
396 }
397 }
398 })
399 expectedTestOnlyModules := []string{
400 "host-derived-test",
401 "derived-test",
402 // android_test and java_test_host are tests too.
403 "host-base",
404 "base",
405 }
406
407 notEqual, left, right := android.ListSetDifference(expectedTestOnlyModules, actualTestOnly)
408 if notEqual {
409 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
410 }
411}
412
Ronald Braunsteinfce43162024-02-02 12:37:20 -0800413// Use for situations where the entries map contains pairs: [srcPath:installedPath1, srcPath2:installedPath2]
414// and we want to compare the RHS of the pairs, i.e. installedPath1, installedPath2
415func assertEntryPairValues(t *testing.T, actual []string, expected []string) {
416 for i, e := range actual {
417 parts := strings.Split(e, ":")
418 if len(parts) != 2 {
419 t.Errorf("Expected entry to have a value delimited by :, received: %s", e)
420 return
421 }
422 android.AssertStringEquals(t, "", parts[1], expected[i])
423 }
424}