1#!/usr/bin/env python3 2# 3# Copyright 2018, The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Unittests for module_info.""" 18 19# pylint: disable=invalid-name 20# pylint: disable=missing-function-docstring 21# pylint: disable=too-many-lines 22 23import os 24from pathlib import Path 25import shutil 26import tempfile 27import unittest 28from unittest import mock 29from atest import constants 30from atest import module_info 31from atest import unittest_constants as uc 32from atest import unittest_utils 33from pyfakefs import fake_filesystem_unittest 34 35JSON_FILE_PATH = os.path.join(uc.TEST_DATA_DIR, uc.JSON_FILE) 36CC_DEP_PATH = os.path.join(uc.TEST_DATA_DIR, uc.CC_DEP_FILE) 37JAVA_DEP_PATH = os.path.join(uc.TEST_DATA_DIR, uc.JAVA_DEP_FILE) 38EXPECTED_MOD_TARGET = 'tradefed' 39EXPECTED_MOD_TARGET_PATH = ['tf/core'] 40UNEXPECTED_MOD_TARGET = 'this_should_not_be_in_module-info.json' 41MOD_NO_PATH = 'module-no-path' 42PATH_TO_MULT_MODULES = 'shared/path/to/be/used' 43MULT_MOODULES_WITH_SHARED_PATH = ['module2', 'module1'] 44PATH_TO_MULT_MODULES_WITH_MULTI_ARCH = 'shared/path/to/be/used2' 45TESTABLE_MODULES_WITH_SHARED_PATH = [ 46 'multiarch1', 47 'multiarch2', 48 'multiarch3', 49 'multiarch3_32', 50] 51 52ROBO_MOD_PATH = ['/shared/robo/path'] 53ROBO_MODULE = 'FooTests' 54ASSOCIATED_ROBO_MODULE = 'RunFooTests' 55ROBO_MODULE_INFO = { 56 constants.MODULE_NAME: ROBO_MODULE, 57 constants.MODULE_PATH: ROBO_MOD_PATH, 58 constants.MODULE_CLASS: [constants.MODULE_CLASS_JAVA_LIBRARIES], 59} 60ASSOCIATED_ROBO_MODULE_INFO = { 61 constants.MODULE_NAME: ASSOCIATED_ROBO_MODULE, 62 constants.MODULE_PATH: ROBO_MOD_PATH, 63 constants.MODULE_CLASS: [constants.MODULE_CLASS_ROBOLECTRIC], 64} 65MOD_PATH_INFO_DICT = { 66 ROBO_MOD_PATH[0]: [ASSOCIATED_ROBO_MODULE_INFO, ROBO_MODULE_INFO] 67} 68MOD_NAME_INFO_DICT = { 69 ASSOCIATED_ROBO_MODULE: ASSOCIATED_ROBO_MODULE_INFO, 70 ROBO_MODULE: ROBO_MODULE_INFO, 71} 72MOD_NAME1 = 'mod1' 73MOD_NAME2 = 'mod2' 74MOD_NAME3 = 'mod3' 75MOD_NAME4 = 'mod4' 76MOD_INFO_DICT = {} 77MODULE_INFO = { 78 constants.MODULE_NAME: 'random_name', 79 constants.MODULE_PATH: 'a/b/c/path', 80 constants.MODULE_CLASS: ['random_class'], 81} 82NAME_TO_MODULE_INFO = {'random_name': MODULE_INFO} 83 84MOBLY_MODULE = 'mobly-test' 85MOBLY_MODULE_NO_TAG = 'mobly-test-no-tag' 86 87# Mocking path allows str only, use os.path instead of Path. 88with tempfile.TemporaryDirectory() as temp_dir: 89 BUILD_TOP_DIR = temp_dir 90SOONG_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/soong') 91PRODUCT_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/target/product/vsoc_x86_64') 92HOST_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/host/linux-x86') 93 94 95# TODO: (b/263199608) Suppress too-many-public-methods after refactoring. 96# pylint: disable=protected-access, too-many-public-methods 97class ModuleInfoUnittests(unittest.TestCase): 98 """Unit tests for module_info.py""" 99 100 def setUp(self) -> None: 101 for path in [BUILD_TOP_DIR, PRODUCT_OUT_DIR, SOONG_OUT_DIR, HOST_OUT_DIR]: 102 if not Path(path).is_dir(): 103 Path(path).mkdir(parents=True) 104 shutil.copy2(JSON_FILE_PATH, PRODUCT_OUT_DIR) 105 self.json_file_path = Path(PRODUCT_OUT_DIR).joinpath(uc.JSON_FILE) 106 shutil.copy2(CC_DEP_PATH, SOONG_OUT_DIR) 107 self.cc_dep_path = Path(SOONG_OUT_DIR).joinpath(uc.CC_DEP_FILE) 108 shutil.copy2(JAVA_DEP_PATH, SOONG_OUT_DIR) 109 self.java_dep_path = Path(SOONG_OUT_DIR).joinpath(uc.JAVA_DEP_FILE) 110 self.merged_dep_path = Path(PRODUCT_OUT_DIR).joinpath(uc.MERGED_DEP_FILE) 111 112 def tearDown(self) -> None: 113 if self.merged_dep_path.is_file(): 114 os.remove(self.merged_dep_path) 115 116 def test_target_name_is_relative_to_build_top(self): 117 build_top = '/src/build_top' 118 product_out = '/src/build_top/pout' 119 env_mock = { 120 constants.ANDROID_BUILD_TOP: build_top, 121 constants.ANDROID_PRODUCT_OUT: product_out, 122 } 123 expected_target = os.path.relpath( 124 os.path.join(product_out, 'module-info.json'), build_top 125 ) 126 127 with mock.patch.dict('os.environ', env_mock, clear=True): 128 actual_target = module_info.get_module_info_target() 129 130 self.assertEqual(actual_target, expected_target) 131 132 def test_target_name_is_in_absolute_path(self): 133 build_top = '/src/build_top' 134 product_out = '/somewhere/pout' 135 env_mock = { 136 constants.ANDROID_BUILD_TOP: build_top, 137 constants.ANDROID_PRODUCT_OUT: product_out, 138 } 139 expected_target = os.path.join(product_out, 'module-info.json') 140 141 with mock.patch.dict('os.environ', env_mock, clear=True): 142 actual_target = module_info.get_module_info_target() 143 144 self.assertEqual(actual_target, expected_target) 145 146 @mock.patch.object(module_info.Loader, 'load') 147 def test_get_path_to_module_info(self, mock_load_module): 148 """Test that we correctly create the path to module info dict.""" 149 mod_one = 'mod1' 150 mod_two = 'mod2' 151 mod_path_one = '/path/to/mod1' 152 mod_path_two = '/path/to/mod2' 153 mod_info_dict = { 154 mod_one: { 155 constants.MODULE_PATH: [mod_path_one], 156 constants.MODULE_NAME: mod_one, 157 }, 158 mod_two: { 159 constants.MODULE_PATH: [mod_path_two], 160 constants.MODULE_NAME: mod_two, 161 }, 162 } 163 mock_load_module.return_value = mod_info_dict 164 path_to_mod_info = { 165 mod_path_one: [{ 166 constants.MODULE_NAME: mod_one, 167 constants.MODULE_PATH: [mod_path_one], 168 }], 169 mod_path_two: [{ 170 constants.MODULE_NAME: mod_two, 171 constants.MODULE_PATH: [mod_path_two], 172 }], 173 } 174 self.assertDictEqual( 175 path_to_mod_info, module_info.get_path_to_module_info(mod_info_dict) 176 ) 177 178 def test_is_module(self): 179 """Test that we get the module when it's properly loaded.""" 180 # Load up the test json file and check that module is in it 181 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 182 self.assertTrue(mod_info.is_module(EXPECTED_MOD_TARGET)) 183 self.assertFalse(mod_info.is_module(UNEXPECTED_MOD_TARGET)) 184 185 def test_get_path(self): 186 """Test that we get the module path when it's properly loaded.""" 187 # Load up the test json file and check that module is in it 188 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 189 self.assertEqual( 190 mod_info.get_paths(EXPECTED_MOD_TARGET), EXPECTED_MOD_TARGET_PATH 191 ) 192 self.assertEqual(mod_info.get_paths(MOD_NO_PATH), []) 193 194 def test_get_module_names(self): 195 """test that we get the module name properly.""" 196 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 197 self.assertEqual( 198 mod_info.get_module_names(EXPECTED_MOD_TARGET_PATH[0]), 199 [EXPECTED_MOD_TARGET], 200 ) 201 unittest_utils.assert_strict_equal( 202 self, 203 mod_info.get_module_names(PATH_TO_MULT_MODULES), 204 MULT_MOODULES_WITH_SHARED_PATH, 205 ) 206 207 def test_path_to_mod_info(self): 208 """test that we get the module name properly.""" 209 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 210 module_list = [] 211 for path_to_mod_info in mod_info.path_to_module_info[ 212 PATH_TO_MULT_MODULES_WITH_MULTI_ARCH 213 ]: 214 module_list.append(path_to_mod_info.get(constants.MODULE_NAME)) 215 module_list.sort() 216 TESTABLE_MODULES_WITH_SHARED_PATH.sort() 217 self.assertEqual(module_list, TESTABLE_MODULES_WITH_SHARED_PATH) 218 219 def test_is_suite_in_compatibility_suites(self): 220 """Test is_suite_in_compatibility_suites.""" 221 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 222 info = {'compatibility_suites': []} 223 self.assertFalse(mod_info.is_suite_in_compatibility_suites('cts', info)) 224 info2 = {'compatibility_suites': ['cts']} 225 self.assertTrue(mod_info.is_suite_in_compatibility_suites('cts', info2)) 226 self.assertFalse(mod_info.is_suite_in_compatibility_suites('vts10', info2)) 227 info3 = {'compatibility_suites': ['cts', 'vts10']} 228 self.assertTrue(mod_info.is_suite_in_compatibility_suites('cts', info3)) 229 self.assertTrue(mod_info.is_suite_in_compatibility_suites('vts10', info3)) 230 self.assertFalse(mod_info.is_suite_in_compatibility_suites('ats', info3)) 231 232 def test_get_testable_modules(self): 233 """Test get_testable_modules.""" 234 expected_testable_modules = {'Module1', 'Module2', 'Module3'} 235 expected_test_suite_modules = {'Module1', 'Module2'} 236 expected_null_suite_modules = {'Module3'} 237 mod_info = create_module_info( 238 modules=[ 239 test_module(name='Module1', compatibility_suites=['test-suite']), 240 test_module(name='Module2', compatibility_suites=['test-suite']), 241 test_module(name='Module3'), 242 non_test_module(name='Dep1'), 243 ] 244 ) 245 246 actual_all_testable_modules = mod_info.get_testable_modules() 247 actual_test_suite_modules = mod_info.get_testable_modules('test-suite') 248 actual_null_suite_modules = mod_info.get_testable_modules('null-suite') 249 250 self.assertEqual(actual_all_testable_modules, expected_testable_modules) 251 self.assertEqual(actual_test_suite_modules, expected_test_suite_modules) 252 self.assertEqual(actual_null_suite_modules, expected_null_suite_modules) 253 254 @mock.patch.dict( 255 'os.environ', 256 { 257 constants.ANDROID_BUILD_TOP: '/', 258 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 259 }, 260 ) 261 def test_is_mobly_test(self): 262 """Test is_mobly_test.""" 263 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 264 self.assertTrue( 265 mod_info.is_mobly_module(mod_info.get_module_info(MOBLY_MODULE)) 266 ) 267 self.assertFalse( 268 mod_info.is_mobly_module(mod_info.get_module_info(MOBLY_MODULE_NO_TAG)) 269 ) 270 271 @mock.patch.dict( 272 'os.environ', 273 { 274 constants.ANDROID_BUILD_TOP: '/', 275 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 276 }, 277 ) 278 @mock.patch.object(module_info.ModuleInfo, 'get_robolectric_type') 279 def test_is_robolectric_test(self, mock_type): 280 """Test is_robolectric_test.""" 281 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 282 mock_type.return_value = constants.ROBOTYPE_MODERN 283 self.assertTrue(mod_info.is_robolectric_test(ROBO_MODULE)) 284 mock_type.return_value = constants.ROBOTYPE_LEGACY 285 self.assertTrue(mod_info.is_robolectric_test(ROBO_MODULE)) 286 mock_type.return_value = 0 287 self.assertFalse(mod_info.is_robolectric_test(ROBO_MODULE)) 288 289 @mock.patch.object(module_info.ModuleInfo, 'is_module') 290 def test_is_auto_gen_test_config(self, mock_is_module): 291 """Test is_auto_gen_test_config correctly detects the module.""" 292 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 293 mock_is_module.return_value = True 294 is_auto_test_config = {'auto_test_config': [True]} 295 is_not_auto_test_config = {'auto_test_config': [False]} 296 is_not_auto_test_config_again = {'auto_test_config': []} 297 MOD_INFO_DICT[MOD_NAME1] = is_auto_test_config 298 MOD_INFO_DICT[MOD_NAME2] = is_not_auto_test_config 299 MOD_INFO_DICT[MOD_NAME3] = is_not_auto_test_config_again 300 MOD_INFO_DICT[MOD_NAME4] = {} 301 mod_info.name_to_module_info = MOD_INFO_DICT 302 self.assertTrue(mod_info.is_auto_gen_test_config(MOD_NAME1)) 303 self.assertFalse(mod_info.is_auto_gen_test_config(MOD_NAME2)) 304 self.assertFalse(mod_info.is_auto_gen_test_config(MOD_NAME3)) 305 self.assertFalse(mod_info.is_auto_gen_test_config(MOD_NAME4)) 306 307 def test_merge_build_system_infos(self): 308 """Test _merge_build_system_infos.""" 309 loader = module_info.Loader( 310 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 311 ) 312 mod_info_1 = { 313 constants.MODULE_NAME: 'module_1', 314 constants.MODULE_DEPENDENCIES: [], 315 } 316 name_to_mod_info = {'module_1': mod_info_1} 317 expect_deps = ['test_dep_level_1_1', 'test_dep_level_1_2'] 318 name_to_mod_info = loader._merge_build_system_infos( 319 name_to_mod_info, java_bp_info_path=self.java_dep_path 320 ) 321 self.assertEqual( 322 name_to_mod_info['module_1'].get(constants.MODULE_DEPENDENCIES), 323 expect_deps, 324 ) 325 326 def test_merge_build_system_infos_missing_keys(self): 327 """Test _merge_build_system_infos for keys missing from module-info.json.""" 328 loader = module_info.Loader( 329 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 330 ) 331 name_to_mod_info = loader._merge_build_system_infos( 332 {}, java_bp_info_path=self.java_dep_path 333 ) 334 335 expect_deps = ['test_dep_level_1_1'] 336 self.assertEqual( 337 name_to_mod_info['not_in_module_info'].get( 338 constants.MODULE_DEPENDENCIES 339 ), 340 expect_deps, 341 ) 342 343 def test_merge_dependency_with_ori_dependency(self): 344 """Test _merge_dependency.""" 345 loader = module_info.Loader( 346 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 347 ) 348 mod_info_1 = { 349 constants.MODULE_NAME: 'module_1', 350 constants.MODULE_DEPENDENCIES: ['ori_dep_1'], 351 } 352 name_to_mod_info = {'module_1': mod_info_1} 353 expect_deps = ['ori_dep_1', 'test_dep_level_1_1', 'test_dep_level_1_2'] 354 name_to_mod_info = loader._merge_build_system_infos( 355 name_to_mod_info, java_bp_info_path=self.java_dep_path 356 ) 357 self.assertEqual( 358 name_to_mod_info['module_1'].get(constants.MODULE_DEPENDENCIES), 359 expect_deps, 360 ) 361 362 @mock.patch.dict( 363 'os.environ', 364 { 365 constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR, 366 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 367 }, 368 ) 369 def test_get_instrumentation_target_apps(self): 370 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 371 artifacts = { 372 'AmSlam': { 373 os.path.join( 374 uc.TEST_DATA_DIR, 375 'out/target/product/generic/data/app/AmSlam/AmSlam.apk', 376 ) 377 } 378 } 379 # 1. If Android.bp is available, use `manifest` to determine the actual 380 # manifest. 381 bp_context = """android_test { 382 name: "AmSlamTests", 383 manifest: 'AndroidManifest.xml', 384 instrumentation_for: "AmSlam" 385 }""" 386 bp_file = os.path.join(uc.TEST_DATA_DIR, 'foo/bar/AmSlam/test/Android.bp') 387 with open(bp_file, 'w', encoding='utf-8') as cache: 388 cache.write(bp_context) 389 self.assertEqual( 390 mod_info.get_instrumentation_target_apps('AmSlamTests'), artifacts 391 ) 392 os.remove(bp_file) 393 # 2. If Android.bp is unavailable, search `AndroidManifest.xml` 394 # arbitrarily. 395 self.assertEqual( 396 mod_info.get_instrumentation_target_apps('AmSlamTests'), artifacts 397 ) 398 399 @mock.patch.dict( 400 'os.environ', 401 { 402 constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR, 403 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 404 }, 405 ) 406 def test_get_target_module_by_pkg(self): 407 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 408 self.assertEqual( 409 'AmSlam', 410 mod_info.get_target_module_by_pkg( 411 package='c0m.andr0id.settingS', 412 search_from=Path(uc.TEST_DATA_DIR).joinpath('foo/bar/AmSlam/test'), 413 ), 414 ) 415 416 @mock.patch.dict( 417 'os.environ', 418 { 419 constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR, 420 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 421 }, 422 ) 423 def test_get_artifact_map(self): 424 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 425 artifacts = { 426 'AmSlam': { 427 os.path.join( 428 uc.TEST_DATA_DIR, 429 'out/target/product/generic/data/app/AmSlam/AmSlam.apk', 430 ) 431 } 432 } 433 self.assertEqual(mod_info.get_artifact_map('AmSlam'), artifacts) 434 435 @mock.patch.dict( 436 'os.environ', 437 { 438 constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR, 439 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 440 }, 441 ) 442 def test_get_filepath_from_module(self): 443 """Test for get_filepath_from_module.""" 444 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 445 446 expected_filepath = Path(uc.TEST_DATA_DIR).joinpath( 447 'foo/bar/AmSlam', 'AndroidManifest.xml' 448 ) 449 self.assertEqual( 450 mod_info.get_filepath_from_module('AmSlam', 'AndroidManifest.xml'), 451 expected_filepath, 452 ) 453 454 expected_filepath = Path(uc.TEST_DATA_DIR).joinpath( 455 'foo/bar/AmSlam/test', 'AndroidManifest.xml' 456 ) 457 self.assertEqual( 458 mod_info.get_filepath_from_module('AmSlamTests', 'AndroidManifest.xml'), 459 expected_filepath, 460 ) 461 462 def test_get_module_dependency(self): 463 """Test get_module_dependency.""" 464 loader = module_info.Loader( 465 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 466 ) 467 mod_info = loader.load() 468 expect_deps = { 469 'test_dep_level_1_1', 470 'module_1', 471 'test_dep_level_1_2', 472 'test_dep_level_2_2', 473 'test_dep_level_2_1', 474 'module_2', 475 } 476 loader._merge_build_system_infos( 477 loader.name_to_module_info, java_bp_info_path=self.java_dep_path 478 ) 479 self.assertEqual( 480 mod_info.get_module_dependency('dep_test_module'), expect_deps 481 ) 482 483 def test_get_module_dependency_w_loop(self): 484 """Test get_module_dependency with problem dep file.""" 485 loader = module_info.Loader( 486 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 487 ) 488 mod_info = loader.load() 489 # Java dependency file with a endless loop define. 490 java_dep_file = os.path.join( 491 uc.TEST_DATA_DIR, 'module_bp_java_loop_deps.json' 492 ) 493 expect_deps = { 494 'test_dep_level_1_1', 495 'module_1', 496 'test_dep_level_1_2', 497 'test_dep_level_2_2', 498 'test_dep_level_2_1', 499 'module_2', 500 } 501 loader._merge_build_system_infos( 502 loader.name_to_module_info, java_bp_info_path=java_dep_file 503 ) 504 self.assertEqual( 505 mod_info.get_module_dependency('dep_test_module'), expect_deps 506 ) 507 508 def test_get_install_module_dependency(self): 509 """Test get_install_module_dependency.""" 510 loader = module_info.Loader( 511 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 512 ) 513 mod_info = loader.load() 514 expect_deps = {'module_1', 'test_dep_level_2_1'} 515 loader._merge_build_system_infos( 516 loader.name_to_module_info, java_bp_info_path=self.java_dep_path 517 ) 518 self.assertEqual( 519 mod_info.get_install_module_dependency('dep_test_module'), expect_deps 520 ) 521 522 def test_cc_merge_build_system_infos(self): 523 """Test _merge_build_system_infos for cc.""" 524 loader = module_info.Loader( 525 module_file=JSON_FILE_PATH, need_merge_fn=lambda: True 526 ) 527 mod_info_1 = { 528 constants.MODULE_NAME: 'module_cc_1', 529 constants.MODULE_DEPENDENCIES: [], 530 } 531 name_to_mod_info = {'module_cc_1': mod_info_1} 532 expect_deps = ['test_cc_dep_level_1_1', 'test_cc_dep_level_1_2'] 533 name_to_mod_info = loader._merge_build_system_infos( 534 name_to_mod_info, cc_bp_info_path=self.cc_dep_path 535 ) 536 self.assertEqual( 537 name_to_mod_info['module_cc_1'].get(constants.MODULE_DEPENDENCIES), 538 expect_deps, 539 ) 540 541 def test_is_unit_test(self): 542 """Test is_unit_test.""" 543 module_name = 'myModule' 544 maininfo_with_unittest = { 545 constants.MODULE_NAME: module_name, 546 constants.MODULE_IS_UNIT_TEST: 'true', 547 } 548 549 self.assertTrue(module_info.ModuleInfo.is_unit_test(maininfo_with_unittest)) 550 551 def test_is_host_unit_test(self): 552 """Test is_host_unit_test.""" 553 module_name = 'myModule' 554 maininfo_with_host_unittest = { 555 constants.MODULE_NAME: module_name, 556 constants.MODULE_IS_UNIT_TEST: 'true', 557 'compatibility_suites': ['host-unit-tests'], 558 constants.MODULE_INSTALLED: uc.DEFAULT_INSTALL_PATH, 559 'auto_test_config': ['true'], 560 } 561 562 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 563 564 self.assertTrue(mod_info.is_host_unit_test(maininfo_with_host_unittest)) 565 566 def test_is_device_driven_test(self): 567 module_name = 'myModule' 568 maininfo_with_device_driven_test = { 569 constants.MODULE_NAME: module_name, 570 constants.MODULE_TEST_CONFIG: [ 571 os.path.join(uc.TEST_CONFIG_DATA_DIR, 'a.xml.data') 572 ], 573 constants.MODULE_INSTALLED: uc.DEFAULT_INSTALL_PATH, 574 'supported_variants': ['DEVICE'], 575 } 576 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 577 578 self.assertTrue( 579 mod_info.is_device_driven_test(maininfo_with_device_driven_test) 580 ) 581 582 def test_not_device_driven_test_when_suite_is_robolectric_test(self): 583 module_name = 'myModule' 584 maininfo_with_device_driven_test = { 585 constants.MODULE_NAME: module_name, 586 constants.MODULE_TEST_CONFIG: [ 587 os.path.join(uc.TEST_CONFIG_DATA_DIR, 'a.xml.data') 588 ], 589 constants.MODULE_INSTALLED: uc.DEFAULT_INSTALL_PATH, 590 'supported_variants': ['DEVICE'], 591 'compatibility_suites': ['robolectric-tests'], 592 } 593 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 594 595 self.assertFalse( 596 mod_info.is_device_driven_test(maininfo_with_device_driven_test) 597 ) 598 599 def test_is_host_driven_test(self): 600 """Test is_host_driven_test.""" 601 test_name = 'myModule' 602 expected_host_driven_info = { 603 constants.MODULE_NAME: test_name, 604 constants.MODULE_TEST_CONFIG: [ 605 os.path.join(uc.TEST_CONFIG_DATA_DIR, 'a.xml.data') 606 ], 607 constants.MODULE_INSTALLED: uc.DEFAULT_INSTALL_PATH, 608 'supported_variants': ['HOST'], 609 } 610 mod_info = create_module_info([ 611 module( 612 name=test_name, 613 test_config=[os.path.join(uc.TEST_CONFIG_DATA_DIR, 'a.xml.data')], 614 installed=uc.DEFAULT_INSTALL_PATH, 615 supported_variants=['HOST'], 616 ) 617 ]) 618 619 return_value = mod_info.is_host_driven_test(expected_host_driven_info) 620 621 self.assertTrue(return_value) 622 623 # TODO: (b/264015241) Stop mocking build variables. 624 # TODO: (b/263199608) Re-write the test after refactoring module-info.py 625 @mock.patch.dict( 626 'os.environ', 627 { 628 constants.ANDROID_BUILD_TOP: uc.ATEST_PKG_DIR, 629 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 630 }, 631 ) 632 def test_has_mainline_modules(self): 633 """Test has_mainline_modules.""" 634 name1 = 'MainModule1' 635 mainline_module1 = ['foo2.apk', 'foo3.apk'] 636 name2 = 'MainModule2' 637 mainline_module2 = ['foo1.apex'] 638 name3 = 'MainModule3' 639 640 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 641 # found in 'test_mainlne_modules' attribute. 642 self.assertTrue(mod_info.has_mainline_modules(name1, mainline_module1)) 643 # found in the value of 'mainline-param' in test_config. 644 self.assertTrue(mod_info.has_mainline_modules(name2, mainline_module2)) 645 # cannot be found in both 'test_mainline_modules' and 'test_config'. 646 self.assertFalse(mod_info.has_mainline_modules(name3, mainline_module2)) 647 648 # TODO: (b/264015241) Stop mocking build variables. 649 # TODO: (b/263199608) Re-write the test after refactoring module-info.py 650 @mock.patch.dict( 651 'os.environ', 652 { 653 constants.ANDROID_BUILD_TOP: os.path.dirname(__file__), 654 constants.ANDROID_PRODUCT_OUT: PRODUCT_OUT_DIR, 655 }, 656 ) 657 def test_get_module_info_for_multi_lib_module(self): 658 my_module_name = 'MyMultiArchTestModule' 659 multi_arch_json = os.path.join( 660 uc.TEST_DATA_DIR, 'multi_arch_module-info.json' 661 ) 662 mod_info = module_info.load_from_file(module_file=multi_arch_json) 663 664 self.assertIsNotNone(mod_info.get_module_info(my_module_name)) 665 666 def test_get_modules_by_include_deps_w_testable_module_only_false(self): 667 module_1 = module( 668 name='module_1', 669 dependencies=['dep1', 'dep2'], 670 ) 671 module_2 = module(name='module_2', dependencies=['dep1', 'dep3']) 672 mod_info = create_module_info([module_1, module_2]) 673 674 self.assertEqual( 675 {'module_1', 'module_2'}, 676 mod_info.get_modules_by_include_deps( 677 {'dep1'}, testable_module_only=False 678 ), 679 ) 680 self.assertEqual( 681 {'module_1'}, 682 mod_info.get_modules_by_include_deps( 683 {'dep2'}, testable_module_only=False 684 ), 685 ) 686 self.assertEqual( 687 {'module_2'}, 688 mod_info.get_modules_by_include_deps( 689 {'dep3'}, testable_module_only=False 690 ), 691 ) 692 693 @mock.patch.object(module_info.ModuleInfo, 'get_testable_modules') 694 def test_get_modules_by_include_deps_w_testable_module_only_true( 695 self, _testable_modules 696 ): 697 module_1 = module( 698 name='module_1', 699 dependencies=['dep1', 'dep2'], 700 ) 701 module_2 = module(name='module_2', dependencies=['dep1', 'dep3']) 702 mod_info = create_module_info([module_1, module_2]) 703 _testable_modules.return_value = [] 704 705 self.assertEqual( 706 set(), 707 mod_info.get_modules_by_include_deps( 708 {'dep1'}, testable_module_only=True 709 ), 710 ) 711 712 def test_get_modules_by_path_in_srcs_no_module_found(self): 713 module_1 = module( 714 name='module_1', 715 srcs=['path/src1', 'path/src2'], 716 ) 717 module_2 = module(name='module_2', srcs=['path/src2', 'path/src3']) 718 mod_info = create_module_info([module_1, module_2]) 719 720 self.assertEqual(set(), mod_info.get_modules_by_path_in_srcs('path/src4')) 721 722 def test_get_modules_by_path_in_srcs_one_module_found(self): 723 module_1 = module( 724 name='module_1', 725 srcs=['path/src1', 'path/src2'], 726 ) 727 module_2 = module(name='module_2', srcs=['path/src2', 'path/src3']) 728 mod_info = create_module_info([module_1, module_2]) 729 730 self.assertEqual( 731 {'module_1'}, mod_info.get_modules_by_path_in_srcs('path/src1') 732 ) 733 734 def test_get_modules_by_path_in_srcs_multiple_module_found(self): 735 module_1 = module( 736 name='module_1', 737 srcs=['path/src1', 'path/src2'], 738 ) 739 module_2 = module(name='module_2', srcs=['path/src2', 'path/src3']) 740 mod_info = create_module_info([module_1, module_2]) 741 742 self.assertEqual( 743 {'module_1', 'module_2'}, 744 mod_info.get_modules_by_path_in_srcs('path/src2'), 745 ) 746 747 def test_contains_same_mainline_modules(self): 748 mainline_modules = {'A.apex', 'B.apk'} 749 self.assertTrue( 750 module_info.contains_same_mainline_modules( 751 mainline_modules, {'B.apk+A.apex'} 752 ) 753 ) 754 self.assertFalse( 755 module_info.contains_same_mainline_modules( 756 mainline_modules, {'B.apk+C.apex'} 757 ) 758 ) 759 760 def test_get_installed_paths_have_abs_path(self): 761 mod_info = create_module_info( 762 [module(name='my_module', installed=[Path('/a/b/c/d')])] 763 ) 764 765 self.assertEqual( 766 mod_info.get_installed_paths('my_module'), [Path('/a/b/c/d')] 767 ) 768 769 @mock.patch.dict( 770 'os.environ', {constants.ANDROID_BUILD_TOP: '/mocked/build_top'} 771 ) 772 def test_get_installed_paths_have_relative_path(self): 773 mod_info = create_module_info( 774 [module(name='my_module', installed=['a/b/c/d'])] 775 ) 776 777 self.assertEqual( 778 mod_info.get_installed_paths('my_module'), 779 [Path('/mocked/build_top/a/b/c/d')], 780 ) 781 782 def test_get_code_under_test_module_name_is_not_found_in_module_info(self): 783 mod_info = create_module_info([ 784 module( 785 name='my_module', 786 code_under_test='code_under_test_module', 787 ) 788 ]) 789 790 # module_that_is_not_in_module_info is not found in mod_info. 791 self.assertEqual( 792 mod_info.get_code_under_test('module_that_is_not_in_module_info'), [], 793 ) 794 795 def test_get_code_under_test_code_under_test_is_not_defined_in_module_info(self): 796 mod_info = create_module_info([module(name='my_module')]) 797 798 # my_module is found in mod_info but code_under_test is not defined. 799 self.assertEqual( 800 mod_info.get_code_under_test('my_module'), [], 801 ) 802 803 def test_get_code_under_test_code_under_test_is_defined_in_module_info(self): 804 mod_info = create_module_info([ 805 module( 806 name='my_module', 807 code_under_test='code_under_test_module', 808 ) 809 ]) 810 811 self.assertEqual( 812 mod_info.get_code_under_test('my_module'), 813 'code_under_test_module', 814 ) 815 816 817class ModuleInfoTestFixture(fake_filesystem_unittest.TestCase): 818 """Fixture for ModuleInfo tests.""" 819 820 def setUp(self): 821 self.setUpPyfakefs() 822 823 # pylint: disable=protected-access 824 def create_empty_module_info(self): 825 fake_temp_file_name = next(tempfile._get_candidate_names()) 826 self.fs.create_file(fake_temp_file_name, contents='{}') 827 return module_info.load_from_file(module_file=fake_temp_file_name) 828 829 def create_module_info(self, modules=None): 830 mod_info = self.create_empty_module_info() 831 modules = modules or [] 832 833 for m in modules: 834 mod_info.name_to_module_info[m['module_name']] = m 835 for path in m['path']: 836 if path in mod_info.path_to_module_info: 837 mod_info.path_to_module_info[path].append(m) 838 else: 839 mod_info.path_to_module_info[path] = [m] 840 841 return mod_info 842 843 844class HasTestConfonfigTest(ModuleInfoTestFixture): 845 """Tests has_test_config in various conditions.""" 846 847 def test_return_true_if_test_config_is_not_empty(self): 848 test_module_info = module(test_config=['config_file']) 849 mod_info = self.create_module_info() 850 851 return_value = mod_info.has_test_config(test_module_info) 852 853 self.assertTrue(return_value) 854 855 def test_return_true_if_auto_test_config_is_not_empty(self): 856 test_module_info = module(auto_test_config=['no_empty']) 857 mod_info = self.create_module_info() 858 859 return_value = mod_info.has_test_config(test_module_info) 860 861 self.assertTrue(return_value) 862 863 def test_return_false_if_auto_test_config_and_test_config_empty(self): 864 test_module_info = module(test_config=[], auto_test_config=[]) 865 mod_info = self.create_module_info() 866 867 return_value = mod_info.has_test_config(test_module_info) 868 869 self.assertFalse(return_value) 870 871 872class ModuleInfoCompatibilitySuiteTest(ModuleInfoTestFixture): 873 """Tests the compatibility suite in the module info.""" 874 875 def test_return_true_if_suite_in_test(self): 876 test_module_info = module(compatibility_suites=['test_suite']) 877 mod_info = self.create_module_info() 878 879 return_value = mod_info.is_suite_in_compatibility_suites( 880 'test_suite', test_module_info 881 ) 882 883 self.assertTrue(return_value) 884 885 def test_return_false_if_suite_not_in_test(self): 886 test_module_info = module(compatibility_suites=['no_suite']) 887 mod_info = self.create_module_info() 888 889 return_value = mod_info.is_suite_in_compatibility_suites( 890 'test_suite', test_module_info 891 ) 892 893 self.assertFalse(return_value) 894 895 def test_return_false_when_mod_info_is_empty(self): 896 test_module_info = None 897 mod_info = self.create_module_info() 898 899 return_value = mod_info.is_suite_in_compatibility_suites( 900 'test_suite', test_module_info 901 ) 902 903 self.assertFalse(return_value) 904 905 def test_return_false_when_mod_info_is_not_a_dict(self): 906 test_module_info = ['no_a_dict'] 907 mod_info = self.create_module_info() 908 909 return_value = mod_info.is_suite_in_compatibility_suites( 910 'test_suite', test_module_info 911 ) 912 913 self.assertFalse(return_value) 914 915 916class RobolectricTestNameTest(ModuleInfoTestFixture): 917 """Tests the Robolectric test name in the module info.""" 918 919 def test_return_empty_for_a_modern_robolectric_test(self): 920 module_name = 'hello_world_test' 921 info = modern_robolectric_test_module(name=f'{module_name}') 922 mod_info = self.create_module_info(modules=[info]) 923 924 return_module = mod_info.get_robolectric_test_name(info) 925 926 self.assertEqual('', return_module) 927 928 def test_return_related_robolectric_run_module_name(self): 929 module_name = 'hello_world_test' 930 run_module_name = f'Run{module_name}' 931 module_path = 'robolectric_path' 932 info = non_test_module(name=f'{module_name}', path=module_path) 933 mod_info = self.create_module_info( 934 modules=[ 935 info, 936 robolectric_class_non_test_module( 937 name=f'{run_module_name}', path=module_path 938 ), 939 ] 940 ) 941 942 return_module = mod_info.get_robolectric_test_name(info) 943 944 self.assertEqual(run_module_name, return_module) 945 946 def test_return_empty_when_no_related_robolectic_class_module(self): 947 module_name = 'hello_world_test' 948 run_module_name = f'Run{module_name}' 949 module_path = 'robolectric_path' 950 info = non_test_module(name=f'{module_name}', path=module_path) 951 mod_info = self.create_module_info( 952 modules=[ 953 info, 954 non_test_module(name=f'{run_module_name}', path=module_path), 955 ] 956 ) 957 958 return_module = mod_info.get_robolectric_test_name(info) 959 960 self.assertEqual('', return_module) 961 962 def test_return_empty_if_related_module_name_not_start_with_Run(self): 963 module_name = 'hello_world_test' 964 run_module_name = f'Not_Run{module_name}' 965 module_path = 'robolectric_path' 966 info = robolectric_class_non_test_module( 967 name=f'{run_module_name}', path=module_path 968 ) 969 mod_info = self.create_module_info( 970 modules=[ 971 non_test_module(name=f'{module_name}', path=module_path), 972 info, 973 ] 974 ) 975 976 return_module = mod_info.get_robolectric_test_name(info) 977 978 self.assertEqual('', return_module) 979 980 def test_return_itself_for_a_robolectric_class_test_module(self): 981 module_name = 'Run_hello_world_test' 982 info = robolectric_class_non_test_module(name=f'{module_name}') 983 mod_info = self.create_module_info(modules=[info]) 984 985 return_module = mod_info.get_robolectric_test_name(info) 986 987 self.assertEqual(module_name, return_module) 988 989 def test_return_empty_if_robolectric_class_module_not_start_with_Run(self): 990 module_name = 'hello_world_test' 991 info = robolectric_class_non_test_module(name=f'{module_name}') 992 mod_info = self.create_module_info(modules=[info]) 993 994 return_module = mod_info.get_robolectric_test_name(info) 995 996 self.assertEqual('', return_module) 997 998 def test_return_0_when_no_mod_info(self): 999 module_name = 'hello_world_test' 1000 info = non_test_module(name=module_name) 1001 mod_info = self.create_module_info(modules=[info]) 1002 1003 return_module = mod_info.get_robolectric_test_name(info) 1004 1005 self.assertEqual('', return_module) 1006 1007 1008class RobolectricTestTypeTest(ModuleInfoTestFixture): 1009 """Tests the Robolectric test type in the module info.""" 1010 1011 def test_modern_robolectric_test_type(self): 1012 module_name = 'hello_world_test' 1013 mod_info = self.create_module_info( 1014 modules=[ 1015 modern_robolectric_test_module(name=f'{module_name}'), 1016 ] 1017 ) 1018 1019 return_value = mod_info.get_robolectric_type(module_name) 1020 1021 self.assertEqual(return_value, constants.ROBOTYPE_MODERN) 1022 1023 def test_return_modern_if_compliant_with_modern_and_legacy(self): 1024 module_name = 'hello_world_test' 1025 module_path = 'robolectric_path' 1026 run_module_name = f'Run{module_name}' 1027 mod_info = self.create_module_info( 1028 modules=[ 1029 modern_robolectric_test_module( 1030 name=f'{module_name}', path=module_path 1031 ), 1032 robolectric_class_non_test_module( 1033 name=f'{run_module_name}', path=module_path 1034 ), 1035 ] 1036 ) 1037 1038 return_value = mod_info.get_robolectric_type(module_name) 1039 1040 self.assertEqual(return_value, constants.ROBOTYPE_MODERN) 1041 1042 def test_not_modern_robolectric_test_if_suite_is_not_robolectric(self): 1043 module_name = 'hello_world_test' 1044 mod_info = self.create_module_info( 1045 modules=[ 1046 non_test_module( 1047 name=f'{module_name}', 1048 compatibility_suites='not_robolectric_tests', 1049 ), 1050 ] 1051 ) 1052 1053 return_value = mod_info.get_robolectric_type(module_name) 1054 1055 self.assertEqual(return_value, 0) 1056 1057 def test_legacy_robolectric_test_type_if_has_related_run_robolectric_class_module( 1058 self, 1059 ): 1060 module_name = 'hello_world_test' 1061 run_module_name = f'Run{module_name}' 1062 module_path = 'robolectric_path' 1063 mod_info = self.create_module_info( 1064 modules=[ 1065 non_test_module(name=f'{module_name}', path=module_path), 1066 robolectric_class_non_test_module( 1067 name=f'{run_module_name}', path=module_path 1068 ), 1069 ] 1070 ) 1071 1072 return_value = mod_info.get_robolectric_type(module_name) 1073 1074 self.assertEqual(return_value, constants.ROBOTYPE_LEGACY) 1075 1076 def test_not_legacy_robolectric_test_type_if_module_is_tradefed_testable( 1077 self, 1078 ): 1079 module_name = 'hello_world_test' 1080 run_module_name = f'Run{module_name}' 1081 module_path = 'robolectric_path' 1082 mod_info = self.create_module_info( 1083 modules=[ 1084 test_module(name=f'{module_name}', path=module_path), 1085 robolectric_class_test_module( 1086 name=f'{run_module_name}', path=module_path 1087 ), 1088 ] 1089 ) 1090 1091 return_value = mod_info.get_robolectric_type(module_name) 1092 1093 self.assertEqual(return_value, 0) 1094 1095 def test_robolectric_class_test_module(self): 1096 module_name = 'Run_hello_world_test' 1097 mod_info = self.create_module_info( 1098 modules=[ 1099 robolectric_class_non_test_module(name=f'{module_name}'), 1100 ] 1101 ) 1102 1103 return_value = mod_info.get_robolectric_type(module_name) 1104 1105 self.assertEqual(return_value, constants.ROBOTYPE_LEGACY) 1106 1107 def test_not_robolectric_test_if_module_name_not_start_with_Run(self): 1108 module_name = 'hello_world_test' 1109 mod_info = self.create_module_info( 1110 modules=[ 1111 robolectric_class_non_test_module(name=f'{module_name}'), 1112 ] 1113 ) 1114 1115 return_value = mod_info.get_robolectric_type(module_name) 1116 1117 self.assertEqual(return_value, 0) 1118 1119 def test_return_0_when_no_related_robolectic_class_module(self): 1120 module_name = 'hello_world_test' 1121 run_module_name = f'Run{module_name}' 1122 module_path = 'robolectric_path' 1123 mod_info = self.create_module_info( 1124 modules=[ 1125 non_test_module(name=f'{module_name}', path=module_path), 1126 non_test_module(name=f'{run_module_name}', path=module_path), 1127 ] 1128 ) 1129 1130 return_value = mod_info.get_robolectric_type(module_name) 1131 1132 self.assertEqual(return_value, 0) 1133 1134 def test_return_0_when_no_related_module_name_start_with_Run(self): 1135 module_name = 'hello_world_test' 1136 run_module_name = f'Not_Run{module_name}' 1137 module_path = 'robolectric_path' 1138 mod_info = self.create_module_info( 1139 modules=[ 1140 non_test_module(name=f'{module_name}', path=module_path), 1141 robolectric_class_non_test_module( 1142 name=f'{run_module_name}', path=module_path 1143 ), 1144 ] 1145 ) 1146 1147 return_value = mod_info.get_robolectric_type(module_name) 1148 1149 self.assertEqual(return_value, 0) 1150 1151 def test_return_0_when_no_mod_info(self): 1152 module_name = 'hello_world_test' 1153 mod_info = self.create_module_info() 1154 1155 return_value = mod_info.get_robolectric_type(module_name) 1156 1157 self.assertEqual(return_value, 0) 1158 1159 1160class IsLegacyRobolectricClassTest(ModuleInfoTestFixture): 1161 """Tests is_legacy_robolectric_class in various conditions.""" 1162 1163 def test_return_true_if_module_class_is_robolectric(self): 1164 test_module_info = module(classes=[constants.MODULE_CLASS_ROBOLECTRIC]) 1165 mod_info = self.create_module_info() 1166 1167 return_value = mod_info.is_legacy_robolectric_class(test_module_info) 1168 1169 self.assertTrue(return_value) 1170 1171 def test_return_false_if_module_class_is_not_robolectric(self): 1172 test_module_info = module(classes=['not_robolectric']) 1173 mod_info = self.create_module_info() 1174 1175 return_value = mod_info.is_legacy_robolectric_class(test_module_info) 1176 1177 self.assertFalse(return_value) 1178 1179 def test_return_false_if_module_class_is_empty(self): 1180 test_module_info = module(classes=[]) 1181 mod_info = self.create_module_info() 1182 1183 return_value = mod_info.is_legacy_robolectric_class(test_module_info) 1184 1185 self.assertFalse(return_value) 1186 1187 1188class IsTestableModuleTest(ModuleInfoTestFixture): 1189 """Tests is_testable_module in various conditions.""" 1190 1191 def test_return_true_for_tradefed_testable_module(self): 1192 info = test_module() 1193 mod_info = self.create_module_info() 1194 1195 return_value = mod_info.is_testable_module(info) 1196 1197 self.assertTrue(return_value) 1198 1199 def test_return_true_for_modern_robolectric_test_module(self): 1200 info = modern_robolectric_test_module() 1201 mod_info = self.create_module_info() 1202 1203 return_value = mod_info.is_testable_module(info) 1204 1205 self.assertTrue(return_value) 1206 1207 def test_return_true_for_legacy_robolectric_test_module(self): 1208 info = legacy_robolectric_test_module() 1209 mod_info = self.create_module_info(modules=[info]) 1210 1211 return_value = mod_info.is_testable_module(info) 1212 1213 self.assertTrue(return_value) 1214 1215 def test_return_false_for_non_tradefed_testable_module(self): 1216 info = module( 1217 auto_test_config=[], test_config=[], installed=['installed_path'] 1218 ) 1219 mod_info = self.create_module_info() 1220 1221 return_value = mod_info.is_testable_module(info) 1222 1223 self.assertFalse(return_value) 1224 1225 def test_return_false_for_no_installed_path_module(self): 1226 info = module(auto_test_config=['true'], installed=[]) 1227 mod_info = self.create_module_info() 1228 1229 return_value = mod_info.is_testable_module(info) 1230 1231 self.assertFalse(return_value) 1232 1233 def test_return_false_if_module_info_is_empty(self): 1234 info = {} 1235 mod_info = self.create_module_info() 1236 1237 return_value = mod_info.is_testable_module(info) 1238 1239 self.assertFalse(return_value) 1240 1241 1242def create_module_info(modules=None): 1243 name_to_module_info = {} 1244 modules = modules or [] 1245 1246 for m in modules: 1247 name_to_module_info[m['module_name']] = m 1248 1249 return module_info.load_from_dict(name_to_module_info) 1250 1251 1252def test_module(**kwargs): 1253 kwargs.setdefault('name', 'hello_world_test') 1254 return test(module(**kwargs)) 1255 1256 1257def non_test_module(**kwargs): 1258 kwargs.setdefault('name', 'not_a_test') 1259 return non_test(module(**kwargs)) 1260 1261 1262def modern_robolectric_test_module(**kwargs): 1263 kwargs.setdefault('name', 'hello_world_test') 1264 return test(robolectric_tests_suite(module(**kwargs))) 1265 1266 1267def legacy_robolectric_test_module(**kwargs): 1268 kwargs.setdefault('name', 'Run_hello_world_test') 1269 return robolectric_class_non_test_module(**kwargs) 1270 1271 1272def robolectric_class_test_module(**kwargs): 1273 kwargs.setdefault('name', 'hello_world_test') 1274 return test(robolectric_class(module(**kwargs))) 1275 1276 1277def robolectric_class_non_test_module(**kwargs): 1278 kwargs.setdefault('name', 'hello_world_test') 1279 return non_test(robolectric_class(module(**kwargs))) 1280 1281 1282# pylint: disable=too-many-arguments, too-many-locals 1283def module( 1284 name=None, 1285 path=None, 1286 installed=None, 1287 classes=None, 1288 auto_test_config=None, 1289 test_config=None, 1290 shared_libs=None, 1291 dependencies=None, 1292 runtime_dependencies=None, 1293 data=None, 1294 data_dependencies=None, 1295 compatibility_suites=None, 1296 host_dependencies=None, 1297 srcs=None, 1298 supported_variants=None, 1299 code_under_test=None, 1300): 1301 name = name or 'libhello' 1302 1303 m = {} 1304 1305 m['module_name'] = name 1306 m['class'] = classes or ['ETC'] 1307 m['path'] = [path or ''] 1308 m['installed'] = installed or [] 1309 m['is_unit_test'] = 'false' 1310 m['auto_test_config'] = auto_test_config or [] 1311 m['test_config'] = test_config or [] 1312 m['shared_libs'] = shared_libs or [] 1313 m['runtime_dependencies'] = runtime_dependencies or [] 1314 m['dependencies'] = dependencies or [] 1315 m['data'] = data or [] 1316 m['data_dependencies'] = data_dependencies or [] 1317 m['compatibility_suites'] = compatibility_suites or [] 1318 m['host_dependencies'] = host_dependencies or [] 1319 m['srcs'] = srcs or [] 1320 m['supported_variants'] = supported_variants or [] 1321 m['code_under_test'] = code_under_test or [] 1322 return m 1323 1324 1325def test(info): 1326 info['auto_test_config'] = ['true'] 1327 info['installed'] = ['installed_path'] 1328 return info 1329 1330 1331def non_test(info): 1332 info['auto_test_config'] = [] 1333 info['installed'] = [] 1334 return info 1335 1336 1337def robolectric_class(info): 1338 info['class'] = ['ROBOLECTRIC'] 1339 return info 1340 1341 1342def robolectric_tests_suite(info): 1343 info = test(info) 1344 info.setdefault('compatibility_suites', []).append('robolectric-tests') 1345 return info 1346 1347 1348if __name__ == '__main__': 1349 unittest.main() 1350