| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 1 | // 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. | 
|  | 14 | package tradefed_modules | 
|  | 15 |  | 
|  | 16 | import ( | 
|  | 17 | "android/soong/android" | 
|  | 18 | "android/soong/java" | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 19 | "strconv" | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 20 | "strings" | 
|  | 21 | "testing" | 
|  | 22 | ) | 
|  | 23 |  | 
|  | 24 | const bp = ` | 
|  | 25 | android_app { | 
|  | 26 | name: "foo", | 
|  | 27 | srcs: ["a.java"], | 
|  | 28 | sdk_version: "current", | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | android_test_helper_app { | 
|  | 32 | name: "HelperApp", | 
|  | 33 | srcs: ["helper.java"], | 
|  | 34 | } | 
|  | 35 |  | 
|  | 36 | android_test { | 
|  | 37 | name: "base", | 
|  | 38 | sdk_version: "current", | 
|  | 39 | data: [":HelperApp", "data/testfile"], | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | test_module_config { | 
|  | 43 | name: "derived_test", | 
|  | 44 | base: "base", | 
|  | 45 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 46 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 47 | test_suites: ["general-tests"], | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 48 | } | 
|  | 49 |  | 
|  | 50 | ` | 
|  | 51 |  | 
|  | 52 | // Ensure we create files needed and set the AndroidMkEntries needed | 
|  | 53 | func TestModuleConfigAndroidTest(t *testing.T) { | 
|  | 54 |  | 
|  | 55 | ctx := android.GroupFixturePreparers( | 
|  | 56 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 57 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 58 | ).RunTestWithBp(t, bp) | 
|  | 59 |  | 
|  | 60 | derived := ctx.ModuleForTests("derived_test", "android_common") | 
|  | 61 | // Assert there are rules to create these files. | 
|  | 62 | derived.Output("test_module_config.manifest") | 
|  | 63 | derived.Output("test_config_fixer/derived_test.config") | 
|  | 64 |  | 
|  | 65 | // Ensure some basic rules exist. | 
|  | 66 | ctx.ModuleForTests("base", "android_common").Output("package-res.apk") | 
|  | 67 | entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0] | 
|  | 68 |  | 
|  | 69 | // Ensure some entries from base are there, specifically support files for data and helper apps. | 
|  | 70 | assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"}) | 
|  | 71 |  | 
|  | 72 | // And some new derived entries are there. | 
|  | 73 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"}) | 
|  | 74 |  | 
|  | 75 | // And ones we override | 
|  | 76 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""}) | 
|  | 77 |  | 
|  | 78 | android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config") | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | // Make sure we call test-config-fixer with the right args. | 
|  | 82 | func TestModuleConfigOptions(t *testing.T) { | 
|  | 83 |  | 
|  | 84 | ctx := android.GroupFixturePreparers( | 
|  | 85 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 86 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 87 | ).RunTestWithBp(t, bp) | 
|  | 88 |  | 
|  | 89 | // Check that we generate a rule to make a new AndroidTest.xml/Module.config file. | 
|  | 90 | derived := ctx.ModuleForTests("derived_test", "android_common") | 
|  | 91 | rule_cmd := derived.Rule("fix_test_config").RuleParams.Command | 
|  | 92 | android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd, | 
|  | 93 | `--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"}]'`) | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | // Ensure we error for a base we don't support. | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 97 | func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) { | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 98 | badBp := ` | 
|  | 99 | java_test_host { | 
|  | 100 | name: "base", | 
|  | 101 | srcs: ["a.java"], | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | test_module_config { | 
|  | 105 | name: "derived_test", | 
|  | 106 | base: "base", | 
|  | 107 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 108 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 109 | test_suites: ["general-tests"], | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 110 | }` | 
|  | 111 |  | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 112 | android.GroupFixturePreparers( | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 113 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 114 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 115 | ).ExtendWithErrorHandler( | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 116 | android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")). | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 117 | RunTestWithBp(t, badBp) | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 118 | } | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 119 |  | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 120 | func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) { | 
|  | 121 | badBp := ` | 
|  | 122 | java_library { | 
|  | 123 | name: "base", | 
|  | 124 | srcs: ["a.java"], | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | test_module_config { | 
|  | 128 | name: "derived_test", | 
|  | 129 | base: "base", | 
|  | 130 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 131 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 132 | test_suites: ["general-tests"], | 
|  | 133 | }` | 
|  | 134 |  | 
|  | 135 | android.GroupFixturePreparers( | 
|  | 136 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 137 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 138 | ).ExtendWithErrorHandler( | 
|  | 139 | android.FixtureExpectsOneErrorPattern("'base' module used as base but it is not a 'android_test' module.")). | 
|  | 140 | RunTestWithBp(t, badBp) | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | func TestModuleConfigNoBaseShouldFail(t *testing.T) { | 
|  | 144 | badBp := ` | 
|  | 145 | java_library { | 
|  | 146 | name: "base", | 
|  | 147 | srcs: ["a.java"], | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | test_module_config { | 
|  | 151 | name: "derived_test", | 
|  | 152 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 153 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 154 | test_suites: ["general-tests"], | 
|  | 155 | }` | 
|  | 156 |  | 
|  | 157 | android.GroupFixturePreparers( | 
|  | 158 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 159 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 160 | ).ExtendWithErrorHandler( | 
|  | 161 | android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")). | 
|  | 162 | RunTestWithBp(t, badBp) | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 163 | } | 
|  | 164 |  | 
|  | 165 | // Ensure we error for a base we don't support. | 
|  | 166 | func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) { | 
|  | 167 | badBp := ` | 
|  | 168 | android_test { | 
|  | 169 | name: "base", | 
|  | 170 | sdk_version: "current", | 
|  | 171 | srcs: ["a.java"], | 
|  | 172 | } | 
|  | 173 |  | 
|  | 174 | test_module_config { | 
|  | 175 | name: "derived_test", | 
|  | 176 | base: "base", | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 177 | test_suites: ["general-tests"], | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 178 | }` | 
|  | 179 |  | 
|  | 180 | ctx := android.GroupFixturePreparers( | 
|  | 181 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 182 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 183 | ).ExtendWithErrorHandler( | 
|  | 184 | android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")). | 
|  | 185 | RunTestWithBp(t, badBp) | 
|  | 186 |  | 
|  | 187 | ctx.ModuleForTests("derived_test", "android_common") | 
|  | 188 | } | 
|  | 189 |  | 
|  | 190 | func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) { | 
|  | 191 | multiBp := ` | 
|  | 192 | android_test { | 
|  | 193 | name: "base", | 
|  | 194 | sdk_version: "current", | 
|  | 195 | srcs: ["a.java"], | 
|  | 196 | } | 
|  | 197 |  | 
|  | 198 | test_module_config { | 
|  | 199 | name: "derived_test", | 
|  | 200 | base: "base", | 
|  | 201 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 202 | test_suites: ["general-tests"], | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 203 | } | 
|  | 204 |  | 
|  | 205 | test_module_config { | 
|  | 206 | name: "another_derived_test", | 
|  | 207 | base: "base", | 
|  | 208 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 209 | test_suites: ["general-tests"], | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 210 | }` | 
|  | 211 |  | 
|  | 212 | ctx := android.GroupFixturePreparers( | 
|  | 213 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 214 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 215 | ).RunTestWithBp(t, multiBp) | 
|  | 216 |  | 
|  | 217 | { | 
|  | 218 | derived := ctx.ModuleForTests("derived_test", "android_common") | 
|  | 219 | entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0] | 
|  | 220 | // All these should be the same in both derived tests | 
|  | 221 | assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"}) | 
|  | 222 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""}) | 
|  | 223 | // Except this one, which points to the updated tradefed xml file. | 
|  | 224 | android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config") | 
|  | 225 | // And this one, the module name. | 
|  | 226 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"}) | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | { | 
|  | 230 | derived := ctx.ModuleForTests("another_derived_test", "android_common") | 
|  | 231 | entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0] | 
|  | 232 | // All these should be the same in both derived tests | 
|  | 233 | assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"}) | 
|  | 234 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""}) | 
|  | 235 | // Except this one, which points to the updated tradefed xml file. | 
|  | 236 | android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config") | 
|  | 237 | // And this one, the module name. | 
|  | 238 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"}) | 
|  | 239 | } | 
|  | 240 | } | 
|  | 241 |  | 
| Ronald Braunstein | 1a6e7c0 | 2024-03-14 21:14:39 +0000 | [diff] [blame] | 242 | // Test_module_config_host rule is allowed to depend on java_test_host | 
|  | 243 | func TestModuleConfigHostBasics(t *testing.T) { | 
|  | 244 | bp := ` | 
|  | 245 | java_test_host { | 
|  | 246 | name: "base", | 
|  | 247 | srcs: ["a.java"], | 
|  | 248 | test_suites: ["suiteA", "general-tests",  "suiteB"], | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | test_module_config_host { | 
|  | 252 | name: "derived_test", | 
|  | 253 | base: "base", | 
|  | 254 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 255 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 256 | test_suites: ["general-tests"], | 
|  | 257 | }` | 
|  | 258 |  | 
|  | 259 | ctx := android.GroupFixturePreparers( | 
|  | 260 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 261 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 262 | ).RunTestWithBp(t, bp) | 
|  | 263 |  | 
|  | 264 | variant := ctx.Config.BuildOS.String() + "_common" | 
|  | 265 | derived := ctx.ModuleForTests("derived_test", variant) | 
|  | 266 | mod := derived.Module().(*testModuleConfigHostModule) | 
|  | 267 | allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod) | 
|  | 268 | entries := allEntries[0] | 
|  | 269 | android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"}) | 
|  | 270 |  | 
|  | 271 | if !mod.Host() { | 
|  | 272 | t.Errorf("host bit is not set for a java_test_host module.") | 
|  | 273 | } | 
|  | 274 | actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0]) | 
|  | 275 | android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData) | 
|  | 276 |  | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | // When you pass an 'android_test' as base, the warning message is a bit obscure, | 
|  | 280 | // talking about variants, but it is something.  Ideally we could do better. | 
|  | 281 | func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) { | 
|  | 282 | badBp := ` | 
|  | 283 | android_test { | 
|  | 284 | name: "base", | 
|  | 285 | sdk_version: "current", | 
|  | 286 | srcs: ["a.java"], | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | test_module_config_host { | 
|  | 290 | name: "derived_test", | 
|  | 291 | base: "base", | 
|  | 292 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 293 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 294 | }` | 
|  | 295 |  | 
|  | 296 | android.GroupFixturePreparers( | 
|  | 297 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 298 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 299 | ).ExtendWithErrorHandler( | 
|  | 300 | android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")). | 
|  | 301 | RunTestWithBp(t, badBp) | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | func TestModuleConfigHostNeedsATestSuite(t *testing.T) { | 
|  | 305 | badBp := ` | 
|  | 306 | java_test_host { | 
|  | 307 | name: "base", | 
|  | 308 | srcs: ["a.java"], | 
|  | 309 | } | 
|  | 310 |  | 
|  | 311 | test_module_config_host { | 
|  | 312 | name: "derived_test", | 
|  | 313 | base: "base", | 
|  | 314 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 315 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 316 | }` | 
|  | 317 |  | 
|  | 318 | android.GroupFixturePreparers( | 
|  | 319 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 320 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 321 | ).ExtendWithErrorHandler( | 
|  | 322 | android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")). | 
|  | 323 | RunTestWithBp(t, badBp) | 
|  | 324 | } | 
|  | 325 |  | 
|  | 326 | func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) { | 
|  | 327 | badBp := ` | 
|  | 328 | java_test_host { | 
|  | 329 | name: "base", | 
|  | 330 | srcs: ["a.java"], | 
|  | 331 | test_suites: ["general-tests", "some-compat"], | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | test_module_config_host { | 
|  | 335 | name: "derived_test", | 
|  | 336 | base: "base", | 
|  | 337 | exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], | 
|  | 338 | include_annotations: ["android.platform.test.annotations.LargeTest"], | 
|  | 339 | test_suites: ["general-tests", "some-compat"], | 
|  | 340 | }` | 
|  | 341 |  | 
|  | 342 | android.GroupFixturePreparers( | 
|  | 343 | java.PrepareForTestWithJavaDefaultModules, | 
|  | 344 | android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), | 
|  | 345 | ).ExtendWithErrorHandler( | 
|  | 346 | android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")). | 
|  | 347 | RunTestWithBp(t, badBp) | 
|  | 348 | } | 
|  | 349 |  | 
| Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 350 | // Use for situations where the entries map contains pairs:  [srcPath:installedPath1, srcPath2:installedPath2] | 
|  | 351 | // and we want to compare the RHS of the pairs, i.e. installedPath1, installedPath2 | 
|  | 352 | func assertEntryPairValues(t *testing.T, actual []string, expected []string) { | 
|  | 353 | for i, e := range actual { | 
|  | 354 | parts := strings.Split(e, ":") | 
|  | 355 | if len(parts) != 2 { | 
|  | 356 | t.Errorf("Expected entry to have a value delimited by :, received: %s", e) | 
|  | 357 | return | 
|  | 358 | } | 
|  | 359 | android.AssertStringEquals(t, "", parts[1], expected[i]) | 
|  | 360 | } | 
|  | 361 | } |