1a6e7c032a
This pairs with `test_module_config` but also works on the base is a `java_test_host` module. e.g. test_module_config_host { name: "CtsOsHostTestCases_DERIVED_2566", base: "CtsOsHostTestCases", test_suites: ["general-tests"], include_filters: [ "android.os.cts.StaticSharedLibsHostTests" ], exclude_annotations: [ "androidx.test.filters.FlakyTest","org.junit.Ignore" ], } The new module is composed of the previous and shares much of the same code. With respect to build size, Without this change, if you build CtsAppSecurityHostTestCases, there will be several copies of the jar (and related apks) : *) 1 in framework out/host/linux-x86/framework/CtsAppSecurityHostTestCases.jar *) 1 in testcases for the test out/host/linux-x86/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar *) 1 per compatibility suite testcases out/host/linux-x86/mts-documentsui/android-mts-documentsui/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar out/host/linux-x86/mts-mediaprovider/android-mts-mediaprovider/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar out/host/linux-x86/mts/android-mts/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar out/host/linux-x86/cts/android-cts/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar out/host/linux-x86/mts-mainline-infra/android-mts-mainline-infra/testcases/CtsAppSecurityHostTestCases/CtsAppSecurityHostTestCases.jar A dervived test using CtsAppSecurityHostTestCases as base adds one more to its testcases dir: *) derived testcase. out/host/linux-x86/testcases/CtsAppSecurityHostTestCases_presubmit_ExternalStorageApp/CtsAppSecurityHostTestCases.jar Fixes: b/327280990 Test: m clean && m CtsOsHostTestCases_DERIVED_2566# as above Test: atest CtsOsHostTestCases_DERIVED_2566 --collect-tests-only Test: migrated the 71 TestMapping instances to Android.bp and build them. Ran tests on some of them. Ran some original `test_module_config` tests derived from `android_test` as well TODO: Add actions to validate the given filters are valid for the given test apks/jars. Change-Id: I115eedb6ff6ba8e72bb49e71867daf49d25ca0f1
361 lines
14 KiB
Go
361 lines
14 KiB
Go
// Copyright 2024 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
package tradefed_modules
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"android/soong/java"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
const bp = `
|
|
android_app {
|
|
name: "foo",
|
|
srcs: ["a.java"],
|
|
sdk_version: "current",
|
|
}
|
|
|
|
android_test_helper_app {
|
|
name: "HelperApp",
|
|
srcs: ["helper.java"],
|
|
}
|
|
|
|
android_test {
|
|
name: "base",
|
|
sdk_version: "current",
|
|
data: [":HelperApp", "data/testfile"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}
|
|
|
|
`
|
|
|
|
// Ensure we create files needed and set the AndroidMkEntries needed
|
|
func TestModuleConfigAndroidTest(t *testing.T) {
|
|
|
|
ctx := android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
derived := ctx.ModuleForTests("derived_test", "android_common")
|
|
// Assert there are rules to create these files.
|
|
derived.Output("test_module_config.manifest")
|
|
derived.Output("test_config_fixer/derived_test.config")
|
|
|
|
// Ensure some basic rules exist.
|
|
ctx.ModuleForTests("base", "android_common").Output("package-res.apk")
|
|
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
|
|
|
|
// Ensure some entries from base are there, specifically support files for data and helper apps.
|
|
assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
|
|
|
|
// And some new derived entries are there.
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"})
|
|
|
|
// And ones we override
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
|
|
|
|
android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
|
|
}
|
|
|
|
// Make sure we call test-config-fixer with the right args.
|
|
func TestModuleConfigOptions(t *testing.T) {
|
|
|
|
ctx := android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
// Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
|
|
derived := ctx.ModuleForTests("derived_test", "android_common")
|
|
rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
|
|
android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
|
|
`--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"}]'`)
|
|
}
|
|
|
|
// Ensure we error for a base we don't support.
|
|
func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
|
|
badBp := `
|
|
java_test_host {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) {
|
|
badBp := `
|
|
java_library {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsOneErrorPattern("'base' module used as base but it is not a 'android_test' module.")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
func TestModuleConfigNoBaseShouldFail(t *testing.T) {
|
|
badBp := `
|
|
java_library {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
// Ensure we error for a base we don't support.
|
|
func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) {
|
|
badBp := `
|
|
android_test {
|
|
name: "base",
|
|
sdk_version: "current",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
base: "base",
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
ctx := android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
|
|
RunTestWithBp(t, badBp)
|
|
|
|
ctx.ModuleForTests("derived_test", "android_common")
|
|
}
|
|
|
|
func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
|
|
multiBp := `
|
|
android_test {
|
|
name: "base",
|
|
sdk_version: "current",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "derived_test",
|
|
base: "base",
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}
|
|
|
|
test_module_config {
|
|
name: "another_derived_test",
|
|
base: "base",
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
ctx := android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).RunTestWithBp(t, multiBp)
|
|
|
|
{
|
|
derived := ctx.ModuleForTests("derived_test", "android_common")
|
|
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
|
|
// All these should be the same in both derived tests
|
|
assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
|
|
// Except this one, which points to the updated tradefed xml file.
|
|
android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
|
|
// And this one, the module name.
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
|
|
}
|
|
|
|
{
|
|
derived := ctx.ModuleForTests("another_derived_test", "android_common")
|
|
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
|
|
// All these should be the same in both derived tests
|
|
assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
|
|
// Except this one, which points to the updated tradefed xml file.
|
|
android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config")
|
|
// And this one, the module name.
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"})
|
|
}
|
|
}
|
|
|
|
// Test_module_config_host rule is allowed to depend on java_test_host
|
|
func TestModuleConfigHostBasics(t *testing.T) {
|
|
bp := `
|
|
java_test_host {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
test_suites: ["suiteA", "general-tests", "suiteB"],
|
|
}
|
|
|
|
test_module_config_host {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests"],
|
|
}`
|
|
|
|
ctx := android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).RunTestWithBp(t, bp)
|
|
|
|
variant := ctx.Config.BuildOS.String() + "_common"
|
|
derived := ctx.ModuleForTests("derived_test", variant)
|
|
mod := derived.Module().(*testModuleConfigHostModule)
|
|
allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
|
|
entries := allEntries[0]
|
|
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
|
|
|
|
if !mod.Host() {
|
|
t.Errorf("host bit is not set for a java_test_host module.")
|
|
}
|
|
actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0])
|
|
android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData)
|
|
|
|
}
|
|
|
|
// When you pass an 'android_test' as base, the warning message is a bit obscure,
|
|
// talking about variants, but it is something. Ideally we could do better.
|
|
func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) {
|
|
badBp := `
|
|
android_test {
|
|
name: "base",
|
|
sdk_version: "current",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config_host {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
func TestModuleConfigHostNeedsATestSuite(t *testing.T) {
|
|
badBp := `
|
|
java_test_host {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
}
|
|
|
|
test_module_config_host {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) {
|
|
badBp := `
|
|
java_test_host {
|
|
name: "base",
|
|
srcs: ["a.java"],
|
|
test_suites: ["general-tests", "some-compat"],
|
|
}
|
|
|
|
test_module_config_host {
|
|
name: "derived_test",
|
|
base: "base",
|
|
exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
|
|
include_annotations: ["android.platform.test.annotations.LargeTest"],
|
|
test_suites: ["general-tests", "some-compat"],
|
|
}`
|
|
|
|
android.GroupFixturePreparers(
|
|
java.PrepareForTestWithJavaDefaultModules,
|
|
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
|
|
).ExtendWithErrorHandler(
|
|
android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")).
|
|
RunTestWithBp(t, badBp)
|
|
}
|
|
|
|
// Use for situations where the entries map contains pairs: [srcPath:installedPath1, srcPath2:installedPath2]
|
|
// and we want to compare the RHS of the pairs, i.e. installedPath1, installedPath2
|
|
func assertEntryPairValues(t *testing.T, actual []string, expected []string) {
|
|
for i, e := range actual {
|
|
parts := strings.Split(e, ":")
|
|
if len(parts) != 2 {
|
|
t.Errorf("Expected entry to have a value delimited by :, received: %s", e)
|
|
return
|
|
}
|
|
android.AssertStringEquals(t, "", parts[1], expected[i])
|
|
}
|
|
}
|