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 test_finder_utils.""" 18 19# pylint: disable=invalid-name 20# pylint: disable=missing-function-docstring 21 22import os 23from pathlib import Path 24import sys 25import tempfile 26import unittest 27from unittest import mock 28 29from atest import constants 30from atest import module_info 31from atest import unittest_constants as uc 32from atest import unittest_utils 33from atest.test_finders import test_finder_utils 34from atest.test_finders import test_info 35 36JSON_FILE_PATH = os.path.join(uc.TEST_DATA_DIR, uc.JSON_FILE) 37CLASS_DIR = 'foo/bar/jank/src/android/jank/cts/ui' 38OTHER_DIR = 'other/dir/' 39OTHER_CLASS_NAME = 'test.java' 40CLASS_NAME3 = 'test2' 41INT_DIR1 = os.path.join(uc.TEST_DATA_DIR, 'integration_dir_testing/int_dir1') 42INT_DIR2 = os.path.join(uc.TEST_DATA_DIR, 'integration_dir_testing/int_dir2') 43INT_FILE_NAME = 'int_dir_testing' 44FIND_TWO = uc.ROOT + 'other/dir/test.java\n' + uc.FIND_ONE 45FIND_THREE = '/a/b/c.java\n/d/e/f.java\n/g/h/i.java' 46FIND_THREE_LIST = ['/a/b/c.java', '/d/e/f.java', '/g/h/i.java'] 47VTS_XML = 'VtsAndroidTest.xml.data' 48VTS_BITNESS_XML = 'VtsBitnessAndroidTest.xml' 49VTS_PUSH_DIR = 'vts_push_files' 50VTS_PLAN_DIR = 'vts_plan_files' 51VTS_XML_TARGETS = { 52 'VtsTestName', 53 'DATA/nativetest/vts_treble_vintf_test/vts_treble_vintf_test', 54 'DATA/nativetest64/vts_treble_vintf_test/vts_treble_vintf_test', 55 'DATA/lib/libhidl-gen-hash.so', 56 'DATA/lib64/libhidl-gen-hash.so', 57 'hal-hidl-hash/frameworks/hardware/interfaces/current.txt', 58 'hal-hidl-hash/hardware/interfaces/current.txt', 59 'hal-hidl-hash/system/hardware/interfaces/current.txt', 60 'hal-hidl-hash/system/libhidl/transport/current.txt', 61 'target_with_delim', 62 'out/dir/target', 63 'push_file1_target1', 64 'push_file1_target2', 65 'push_file2_target1', 66 'push_file2_target2', 67 'CtsDeviceInfo.apk', 68 'DATA/app/sl4a/sl4a.apk', 69} 70VTS_PLAN_TARGETS = { 71 os.path.join( 72 uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-staging-default.xml.data' 73 ), 74 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-aa.xml.data'), 75 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-bb.xml.data'), 76 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-cc.xml.data'), 77 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-dd.xml.data'), 78} 79XML_TARGETS = { 80 'CtsJankDeviceTestCases', 81 'perf-setup', 82 'cts-tradefed', 83 'GtsEmptyTestApp', 84} 85PATH_TO_MODULE_INFO_WITH_AUTOGEN = { 86 'foo/bar/jank': [{'auto_test_config': True}] 87} 88PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN = { 89 'foo/bar/jank': [{'auto_test_config': True}, {'auto_test_config': True}] 90} 91PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN_AND_ROBO = { 92 'foo/bar': [{'auto_test_config': True}, {'auto_test_config': True}], 93 'foo/bar/jank': [ 94 {constants.MODULE_CLASS: [constants.MODULE_CLASS_ROBOLECTRIC]} 95 ], 96} 97UNIT_TEST_SEARCH_ROOT = 'my/unit/test/root' 98IT_TEST_MATCHED_1_PATH = os.path.join(UNIT_TEST_SEARCH_ROOT, 'sub1') 99UNIT_TEST_MATCHED_2_PATH = os.path.join(UNIT_TEST_SEARCH_ROOT, 'sub1', 'sub2') 100UNIT_TEST_NOT_MATCHED_1_PATH = os.path.join( 101 os.path.dirname(UNIT_TEST_SEARCH_ROOT), 'sub1' 102) 103UNIT_TEST_MODULE_1 = 'unit_test_module_1' 104UNIT_TEST_MODULE_2 = 'unit_test_module_2' 105UNIT_TEST_MODULE_3 = 'unit_test_module_3' 106DALVIK_TEST_CONFIG = 'AndroidDalvikTest.xml.data' 107LIBCORE_TEST_CONFIG = 'AndroidLibCoreTest.xml.data' 108DALVIK_XML_TARGETS = XML_TARGETS | test_finder_utils.DALVIK_TEST_DEPS 109BUILD_TOP_DIR = tempfile.TemporaryDirectory().name 110PRODUCT_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/target/product/vsoc_x86_64') 111HOST_OUT_DIR = tempfile.NamedTemporaryFile().name 112 113 114# pylint: disable=protected-access 115# pylint: disable=too-many-public-methods 116# pylint: disable=unnecessary-comprehension 117class TestFinderUtilsUnittests(unittest.TestCase): 118 """Unit tests for test_finder_utils.py""" 119 120 @mock.patch.object( 121 test_finder_utils, 'has_method_in_file', return_value=False 122 ) 123 @mock.patch('builtins.input', return_value='0') 124 def test_extract_test_path(self, _, has_method): 125 """Test extract_test_dir method.""" 126 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 127 unittest_utils.assert_strict_equal( 128 self, test_finder_utils.extract_test_path(uc.FIND_ONE), paths 129 ) 130 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 131 unittest_utils.assert_strict_equal( 132 self, test_finder_utils.extract_test_path(FIND_TWO), paths 133 ) 134 has_method.return_value = True 135 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 136 unittest_utils.assert_strict_equal( 137 self, test_finder_utils.extract_test_path(uc.FIND_ONE, 'method'), paths 138 ) 139 140 def test_has_method_in_file(self): 141 """Test has_method_in_file method.""" 142 test_path = os.path.join( 143 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.cc' 144 ) 145 self.assertTrue( 146 test_finder_utils.has_method_in_file( 147 test_path, frozenset(['PrintHelloWorld']) 148 ) 149 ) 150 self.assertFalse( 151 test_finder_utils.has_method_in_file( 152 test_path, frozenset(['PrintHelloWorld1']) 153 ) 154 ) 155 test_path = os.path.join( 156 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.java' 157 ) 158 self.assertTrue( 159 test_finder_utils.has_method_in_file( 160 test_path, frozenset(['testMethod1']) 161 ) 162 ) 163 test_path = os.path.join( 164 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.java' 165 ) 166 self.assertFalse( 167 test_finder_utils.has_method_in_file( 168 test_path, frozenset(['testMethod', 'testMethod2']) 169 ) 170 ) 171 test_path = os.path.join( 172 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.java' 173 ) 174 self.assertFalse( 175 test_finder_utils.has_method_in_file( 176 test_path, frozenset(['testMethod']) 177 ) 178 ) 179 180 # TODO: (b/263330492) Stop mocking build environment variables. 181 def test_has_method_in_kt_file(self): 182 """Test has_method_in_file method with kt class path.""" 183 test_path = os.path.join( 184 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.kt' 185 ) 186 os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR} 187 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 188 self.assertTrue( 189 test_finder_utils.has_method_in_file( 190 test_path, frozenset(['testMethod1']) 191 ) 192 ) 193 self.assertFalse( 194 test_finder_utils.has_method_in_file( 195 test_path, frozenset(['testMethod']) 196 ) 197 ) 198 self.assertTrue( 199 test_finder_utils.has_method_in_file( 200 test_path, frozenset(['testMethod1', 'testMethod2']) 201 ) 202 ) 203 self.assertFalse( 204 test_finder_utils.has_method_in_file( 205 test_path, frozenset(['testMethod', 'testMethod2']) 206 ) 207 ) 208 209 @mock.patch('builtins.input', return_value='1') 210 def test_extract_selected_tests(self, mock_input): 211 """Test method extract_selected_tests method.""" 212 tests = [] 213 self.assertEqual(test_finder_utils.extract_selected_tests(tests), None) 214 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 215 unittest_utils.assert_strict_equal( 216 self, test_finder_utils.extract_test_path(uc.FIND_ONE), paths 217 ) 218 paths = [os.path.join(uc.ROOT, OTHER_DIR, OTHER_CLASS_NAME)] 219 mock_input.return_value = '1' 220 unittest_utils.assert_strict_equal( 221 self, test_finder_utils.extract_test_path(FIND_TWO), paths 222 ) 223 # Test inputing out-of-range integer or a string 224 mock_input.return_value = '100' 225 self.assertEqual( 226 test_finder_utils.extract_selected_tests(uc.CLASS_NAME), [] 227 ) 228 mock_input.return_value = 'lOO' 229 self.assertEqual( 230 test_finder_utils.extract_selected_tests(uc.CLASS_NAME), [] 231 ) 232 233 @mock.patch('builtins.input') 234 def test_extract_test_from_multiselect(self, mock_input): 235 """Test method extract_selected_tests method.""" 236 # multi-select 237 paths = ['/a/b/c.java', '/g/h/i.java'] 238 mock_input.return_value = '0,2' 239 240 unittest_utils.assert_strict_equal( 241 self, 242 sorted(test_finder_utils.extract_selected_tests(FIND_THREE_LIST)), 243 sorted(paths), 244 ) 245 246 # selecting a range 247 paths = ['/d/e/f.java', '/g/h/i.java'] 248 mock_input.return_value = '1-2' 249 250 unittest_utils.assert_strict_equal( 251 self, test_finder_utils.extract_selected_tests(FIND_THREE_LIST), paths 252 ) 253 254 # mixed formats 255 paths = ['/a/b/c.java', '/d/e/f.java', '/g/h/i.java'] 256 mock_input.return_value = '0,1-2' 257 258 unittest_utils.assert_strict_equal( 259 self, 260 sorted(test_finder_utils.extract_selected_tests(FIND_THREE_LIST)), 261 sorted(paths), 262 ) 263 264 # input unsupported formats, return empty 265 paths = [] 266 mock_input.return_value = '?/#' 267 268 unittest_utils.assert_strict_equal( 269 self, test_finder_utils.extract_test_path(FIND_THREE), paths 270 ) 271 272 @mock.patch('builtins.input') 273 @mock.patch.object(test_finder_utils, 'get_selected_indices') 274 def test_multiselect_auxiliary_menu_all_returns_all_tests( 275 self, mock_get_selected_indices, mock_input): 276 paths = ['/a/b/c.java', '/d/e/f.java', '/g/h/i.java'] 277 mock_input.return_value = 'A' 278 279 unittest_utils.assert_strict_equal( 280 self, 281 sorted(test_finder_utils.extract_selected_tests(FIND_THREE_LIST)), 282 sorted(paths), 283 ) 284 mock_get_selected_indices.assert_not_called() 285 286 @mock.patch('builtins.input') 287 @mock.patch.object(sys, 'exit') 288 @mock.patch.object(test_finder_utils, 'get_selected_indices') 289 def test_multiselect_auxiliary_menu_lowercase_cancel_returns_empty_list( 290 self, mock_get_selected_indices, mock_exit, mock_input): 291 # Cancelling the command 292 mock_input.return_value = 'c' 293 294 test_finder_utils.extract_selected_tests(FIND_THREE_LIST) 295 296 mock_exit.assert_called_once_with(0) 297 mock_get_selected_indices.assert_not_called() 298 299 @mock.patch('os.path.isdir') 300 def test_is_equal_or_sub_dir(self, mock_isdir): 301 """Test is_equal_or_sub_dir method.""" 302 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', '/')) 303 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', '/a')) 304 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', '/a/b/c')) 305 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a/b', '/a/b/c')) 306 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a', '/f')) 307 mock_isdir.return_value = False 308 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a/b', '/a')) 309 310 @mock.patch('os.path.isdir', return_value=True) 311 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 312 def test_find_parent_module_dir(self, _isfile, _isdir): 313 """Test _find_parent_module_dir method.""" 314 abs_class_dir = '/%s' % CLASS_DIR 315 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 316 mock_module_info.path_to_module_info = {} 317 unittest_utils.assert_strict_equal( 318 self, 319 test_finder_utils.find_parent_module_dir( 320 uc.ROOT, abs_class_dir, mock_module_info 321 ), 322 uc.MODULE_DIR, 323 ) 324 325 @mock.patch('os.path.isdir', return_value=True) 326 @mock.patch('os.path.isfile', return_value=False) 327 def test_find_parent_module_dir_with_autogen_config(self, _isfile, _isdir): 328 """Test _find_parent_module_dir method.""" 329 abs_class_dir = '/%s' % CLASS_DIR 330 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 331 mock_module_info.path_to_module_info = PATH_TO_MODULE_INFO_WITH_AUTOGEN 332 unittest_utils.assert_strict_equal( 333 self, 334 test_finder_utils.find_parent_module_dir( 335 uc.ROOT, abs_class_dir, mock_module_info 336 ), 337 uc.MODULE_DIR, 338 ) 339 340 @mock.patch('os.path.isdir', return_value=True) 341 @mock.patch('os.path.isfile', side_effect=[False] * 5 + [True]) 342 def test_find_parent_module_dir_with_autogen_subconfig(self, _isfile, _isdir): 343 """Test _find_parent_module_dir method. 344 345 This case is testing when the auto generated config is in a 346 sub-directory of a larger test that contains a test config in a parent 347 directory. 348 """ 349 abs_class_dir = '/%s' % CLASS_DIR 350 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 351 mock_module_info.path_to_module_info = ( 352 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN 353 ) 354 unittest_utils.assert_strict_equal( 355 self, 356 test_finder_utils.find_parent_module_dir( 357 uc.ROOT, abs_class_dir, mock_module_info 358 ), 359 uc.MODULE_DIR, 360 ) 361 362 @mock.patch('os.path.isdir', return_value=True) 363 @mock.patch('os.path.isfile', return_value=False) 364 def test_find_parent_module_dir_with_multi_autogens(self, _isfile, _isdir): 365 """Test _find_parent_module_dir method. 366 367 This case returns folders with multiple autogenerated configs defined. 368 """ 369 abs_class_dir = '/%s' % CLASS_DIR 370 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 371 mock_module_info.path_to_module_info = ( 372 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN 373 ) 374 unittest_utils.assert_strict_equal( 375 self, 376 test_finder_utils.find_parent_module_dir( 377 uc.ROOT, abs_class_dir, mock_module_info 378 ), 379 uc.MODULE_DIR, 380 ) 381 382 @mock.patch('os.path.isdir', return_value=True) 383 @mock.patch('os.path.isfile', return_value=False) 384 def test_find_parent_module_dir_with_robo_and_autogens(self, _isfile, _isdir): 385 """Test _find_parent_module_dir method. 386 387 This case returns folders with multiple autogenerated configs defined 388 with a Robo test above them, which is the expected result. 389 """ 390 abs_class_dir = '/%s' % CLASS_DIR 391 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 392 mock_module_info.path_to_module_info = ( 393 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN_AND_ROBO 394 ) 395 unittest_utils.assert_strict_equal( 396 self, 397 test_finder_utils.find_parent_module_dir( 398 uc.ROOT, abs_class_dir, mock_module_info 399 ), 400 uc.MODULE_DIR, 401 ) 402 403 @mock.patch('os.path.isdir', return_value=True) 404 @mock.patch('os.path.isfile', return_value=False) 405 def test_find_parent_module_dir_robo(self, _isfile, _isdir): 406 """Test _find_parent_module_dir method. 407 408 Make sure we behave as expected when we encounter a robo module path. 409 """ 410 abs_class_dir = '/%s' % CLASS_DIR 411 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 412 mock_module_info.is_legacy_robolectric_class.return_value = True 413 rel_class_dir_path = os.path.relpath(abs_class_dir, uc.ROOT) 414 mock_module_info.path_to_module_info = {rel_class_dir_path: [{}]} 415 unittest_utils.assert_strict_equal( 416 self, 417 test_finder_utils.find_parent_module_dir( 418 uc.ROOT, abs_class_dir, mock_module_info 419 ), 420 rel_class_dir_path, 421 ) 422 423 def test_get_targets_from_xml(self): 424 """Test get_targets_from_xml method.""" 425 # Mocking Etree is near impossible, so use a real file, but mocking 426 # ModuleInfo is still fine. Just have it return False when it finds a 427 # module that states it's not a module. 428 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 429 mock_module_info.is_module.side_effect = lambda module: ( 430 not module == 'is_not_module' 431 ) 432 xml_file = os.path.join(uc.TEST_DATA_DIR, constants.MODULE_CONFIG + '.data') 433 unittest_utils.assert_strict_equal( 434 self, 435 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 436 XML_TARGETS, 437 ) 438 439 def test_get_targets_from_dalvik_xml(self): 440 """Test get_targets_from_xml method with dalvik class.""" 441 # Mocking Etree is near impossible, so use a real file, but mocking 442 # ModuleInfo is still fine. Just have it return False when it finds a 443 # module that states it's not a module. 444 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 445 mock_module_info.is_module.side_effect = lambda module: ( 446 not module == 'is_not_module' 447 ) 448 xml_file = os.path.join(uc.TEST_DATA_DIR, DALVIK_TEST_CONFIG) 449 unittest_utils.assert_strict_equal( 450 self, 451 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 452 DALVIK_XML_TARGETS, 453 ) 454 455 def test_get_targets_from_libcore_xml(self): 456 """Test get_targets_from_xml method with libcore class.""" 457 # Mocking Etree is near impossible, so use a real file, but mocking 458 # ModuleInfo is still fine. Just have it return False when it finds a 459 # module that states it's not a module. 460 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 461 mock_module_info.is_module.side_effect = lambda module: ( 462 not module == 'is_not_module' 463 ) 464 xml_file = os.path.join(uc.TEST_DATA_DIR, LIBCORE_TEST_CONFIG) 465 unittest_utils.assert_strict_equal( 466 self, 467 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 468 DALVIK_XML_TARGETS, 469 ) 470 471 @mock.patch.object( 472 test_finder_utils, 473 '_VTS_PUSH_DIR', 474 os.path.join(uc.TEST_DATA_DIR, VTS_PUSH_DIR), 475 ) 476 def test_get_targets_from_vts_xml(self): 477 """Test get_targets_from_vts_xml method.""" 478 # Mocking Etree is near impossible, so use a real file, but mock out 479 # ModuleInfo, 480 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 481 mock_module_info.is_module.return_value = True 482 xml_file = os.path.join(uc.TEST_DATA_DIR, VTS_XML) 483 unittest_utils.assert_strict_equal( 484 self, 485 test_finder_utils.get_targets_from_vts_xml( 486 xml_file, '', mock_module_info 487 ), 488 VTS_XML_TARGETS, 489 ) 490 491 @mock.patch('builtins.input', return_value='0') 492 def test_search_integration_dirs(self, mock_input): 493 """Test search_integration_dirs.""" 494 mock_input.return_value = '0' 495 paths = [os.path.join(uc.ROOT, INT_DIR1, INT_FILE_NAME + '.xml')] 496 int_dirs = [INT_DIR1] 497 test_result = test_finder_utils.search_integration_dirs( 498 INT_FILE_NAME, int_dirs 499 ) 500 unittest_utils.assert_strict_equal(self, test_result, paths) 501 int_dirs = [INT_DIR1, INT_DIR2] 502 test_result = test_finder_utils.search_integration_dirs( 503 INT_FILE_NAME, int_dirs 504 ) 505 unittest_utils.assert_strict_equal(self, test_result, paths) 506 507 @mock.patch('os.path.isfile', return_value=False) 508 @mock.patch('os.environ.get', return_value=uc.TEST_CONFIG_DATA_DIR) 509 @mock.patch('builtins.input', return_value='0') 510 # pylint: disable=too-many-statements 511 def test_find_class_file(self, mock_input, _mock_env, _mock_isfile): 512 """Test find_class_file.""" 513 # 1. Java class(find). 514 java_tmp_test_result = [] 515 mock_input.return_value = '0' 516 java_class = os.path.join( 517 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.java' 518 ) 519 java_tmp_test_result.extend( 520 test_finder_utils.find_class_file( 521 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA 522 ) 523 ) 524 mock_input.return_value = '1' 525 kt_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.kt') 526 java_tmp_test_result.extend( 527 test_finder_utils.find_class_file( 528 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA 529 ) 530 ) 531 self.assertTrue(java_class in java_tmp_test_result) 532 self.assertTrue(kt_class in java_tmp_test_result) 533 534 # 2. Java class(read index). 535 del java_tmp_test_result[:] 536 mock_input.return_value = '0' 537 _mock_isfile = True 538 java_class = os.path.join( 539 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.java' 540 ) 541 java_tmp_test_result.extend( 542 test_finder_utils.find_class_file( 543 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA 544 ) 545 ) 546 mock_input.return_value = '1' 547 kt_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.kt') 548 java_tmp_test_result.extend( 549 test_finder_utils.find_class_file( 550 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA 551 ) 552 ) 553 self.assertTrue(java_class in java_tmp_test_result) 554 self.assertTrue(kt_class in java_tmp_test_result) 555 556 # 3. Qualified Java class(find). 557 del java_tmp_test_result[:] 558 mock_input.return_value = '0' 559 _mock_isfile = False 560 java_qualified_class = '{0}.{1}'.format( 561 uc.FIND_PATH_FOLDER, uc.FIND_PATH_TESTCASE_JAVA 562 ) 563 java_tmp_test_result.extend( 564 test_finder_utils.find_class_file(uc.FIND_PATH, java_qualified_class) 565 ) 566 mock_input.return_value = '1' 567 java_tmp_test_result.extend( 568 test_finder_utils.find_class_file(uc.FIND_PATH, java_qualified_class) 569 ) 570 self.assertTrue(java_class in java_tmp_test_result) 571 self.assertTrue(kt_class in java_tmp_test_result) 572 573 # 4. Qualified Java class(read index). 574 del java_tmp_test_result[:] 575 mock_input.return_value = '0' 576 _mock_isfile = True 577 java_qualified_class = '{0}.{1}'.format( 578 uc.FIND_PATH_FOLDER, uc.FIND_PATH_TESTCASE_JAVA 579 ) 580 java_tmp_test_result.extend( 581 test_finder_utils.find_class_file(uc.FIND_PATH, java_qualified_class) 582 ) 583 mock_input.return_value = '1' 584 java_tmp_test_result.extend( 585 test_finder_utils.find_class_file(uc.FIND_PATH, java_qualified_class) 586 ) 587 self.assertTrue(java_class in java_tmp_test_result) 588 self.assertTrue(kt_class in java_tmp_test_result) 589 590 # 5. CC class(find). 591 cc_tmp_test_result = [] 592 _mock_isfile = False 593 mock_input.return_value = '0' 594 cpp_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cpp') 595 cc_tmp_test_result.extend( 596 test_finder_utils.find_class_file( 597 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_CC, True 598 ) 599 ) 600 mock_input.return_value = '1' 601 cc_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cc') 602 cc_tmp_test_result.extend( 603 test_finder_utils.find_class_file( 604 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_CC, True 605 ) 606 ) 607 self.assertTrue(cpp_class in cc_tmp_test_result) 608 self.assertTrue(cc_class in cc_tmp_test_result) 609 610 # 6. CC class(read index). 611 del cc_tmp_test_result[:] 612 mock_input.return_value = '0' 613 _mock_isfile = True 614 cpp_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cpp') 615 cc_tmp_test_result.extend( 616 test_finder_utils.find_class_file( 617 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_CC, True 618 ) 619 ) 620 mock_input.return_value = '1' 621 cc_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cc') 622 cc_tmp_test_result.extend( 623 test_finder_utils.find_class_file( 624 uc.FIND_PATH, uc.FIND_PATH_TESTCASE_CC, True 625 ) 626 ) 627 self.assertTrue(cpp_class in cc_tmp_test_result) 628 self.assertTrue(cc_class in cc_tmp_test_result) 629 630 @mock.patch('builtins.input', return_value='0') 631 @mock.patch.object(test_finder_utils, 'get_dir_path_and_filename') 632 @mock.patch('os.path.exists', return_value=True) 633 def test_get_int_dir_from_path(self, _exists, _find, mock_input): 634 """Test get_int_dir_from_path.""" 635 mock_input.return_value = '0' 636 int_dirs = [INT_DIR1] 637 path = os.path.join(uc.ROOT, INT_DIR1, INT_FILE_NAME + '.xml') 638 _find.return_value = (INT_DIR1, INT_FILE_NAME + '.xml') 639 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 640 unittest_utils.assert_strict_equal(self, test_result, INT_DIR1) 641 _find.return_value = (INT_DIR1, None) 642 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 643 unittest_utils.assert_strict_equal(self, test_result, None) 644 int_dirs = [INT_DIR1, INT_DIR2] 645 _find.return_value = (INT_DIR1, INT_FILE_NAME + '.xml') 646 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 647 unittest_utils.assert_strict_equal(self, test_result, INT_DIR1) 648 649 def test_get_install_locations(self): 650 """Test get_install_locations.""" 651 host_installed_paths = ['out/host/a/b'] 652 host_expect = set(['host']) 653 self.assertEqual( 654 test_finder_utils.get_install_locations(host_installed_paths), 655 host_expect, 656 ) 657 device_installed_paths = ['out/target/c/d'] 658 device_expect = set(['device']) 659 self.assertEqual( 660 test_finder_utils.get_install_locations(device_installed_paths), 661 device_expect, 662 ) 663 both_installed_paths = ['out/host/e', 'out/target/f'] 664 both_expect = set(['host', 'device']) 665 self.assertEqual( 666 test_finder_utils.get_install_locations(both_installed_paths), 667 both_expect, 668 ) 669 no_installed_paths = [] 670 no_expect = set() 671 self.assertEqual( 672 test_finder_utils.get_install_locations(no_installed_paths), no_expect 673 ) 674 675 # Disable the fail test due to the breakage if test xml rename to xml.data. 676 # pylint: disable=pointless-string-statement 677 ''' 678 def test_get_plans_from_vts_xml(self): 679 """Test get_plans_from_vts_xml method.""" 680 xml_path = os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 681 'vts-staging-default.xml.data') 682 self.assertEqual( 683 test_finder_utils.get_plans_from_vts_xml(xml_path), 684 VTS_PLAN_TARGETS) 685 xml_path = os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'NotExist.xml') 686 self.assertRaises(atest_error.XmlNotExistError, 687 test_finder_utils.get_plans_from_vts_xml, xml_path) 688 ''' 689 690 def test_get_levenshtein_distance(self): 691 """Test get_levenshetine distance module correctly returns distance.""" 692 self.assertEqual( 693 test_finder_utils.get_levenshtein_distance(uc.MOD1, uc.FUZZY_MOD1), 1 694 ) 695 696 self.assertEqual( 697 test_finder_utils.get_levenshtein_distance( 698 uc.MOD2, uc.FUZZY_MOD2, dir_costs=(1, 2, 3) 699 ), 700 3, 701 ) 702 703 self.assertEqual( 704 test_finder_utils.get_levenshtein_distance( 705 uc.MOD3, uc.FUZZY_MOD3, dir_costs=(1, 2, 1) 706 ), 707 8, 708 ) 709 710 # pylint: disable=consider-iterating-dictionary 711 def test_get_cc_class_info(self): 712 """Test get_cc_class_info method.""" 713 file_path = os.path.join(uc.TEST_DATA_DIR, 'my_cc_test.cc') 714 class_info = test_finder_utils.get_cc_class_info(file_path) 715 716 # 1. Ensure all classes are in the class info dict. 717 expect_classes = { 718 'Class1', 719 'FClass', 720 'FlagClass1', 721 'FFlagClass', 722 'ValueParamClass1', 723 'ValueParamClass2', 724 'TypedTestClass', 725 'TypedParamTestClass', 726 } 727 self.assertEqual({key for key in class_info.keys()}, expect_classes) 728 729 # 2. Ensure methods are correctly mapping to the right class. 730 self.assertEqual(class_info['ValueParamClass1']['methods'], {'VPMethod1'}) 731 self.assertEqual(class_info['ValueParamClass2']['methods'], {'VPMethod2'}) 732 self.assertEqual(class_info['TypedTestClass']['methods'], {'TypedTestName'}) 733 self.assertEqual( 734 class_info['TypedParamTestClass']['methods'], {'TypedParamTestName'} 735 ) 736 self.assertEqual(class_info['Class1']['methods'], {'Method1', 'Method2'}) 737 self.assertEqual(class_info['FClass']['methods'], {'FMethod1', 'FMethod2'}) 738 self.assertEqual( 739 class_info['FlagClass1']['methods'], {'Method1', 'Method2'} 740 ) 741 self.assertEqual( 742 class_info['FFlagClass']['methods'], {'FMethod1', 'FMethod2'} 743 ) 744 745 # 3. Ensure prefixes are correctly mapping to the right class. 746 self.assertEqual( 747 class_info['TypedParamTestClass']['prefixes'], 748 {'Instantiation3', 'Instantiation4'}, 749 ) 750 self.assertEqual( 751 class_info['ValueParamClass1']['prefixes'], {'Instantiation1'} 752 ) 753 self.assertEqual( 754 class_info['ValueParamClass2']['prefixes'], {'Instantiation2'} 755 ) 756 757 # 4. Ensure we can tell typed test. 758 self.assertTrue(class_info['TypedParamTestClass']['typed']) 759 self.assertTrue(class_info['TypedTestClass']['typed']) 760 self.assertFalse(class_info['ValueParamClass1']['typed']) 761 self.assertFalse(class_info['FClass']['typed']) 762 self.assertFalse(class_info['Class1']['typed']) 763 self.assertFalse(class_info['FFlagClass']['typed']) 764 self.assertFalse(class_info['FlagClass1']['typed']) 765 766 def test_get_java_method(self): 767 """Test get_java_method""" 768 expect_methods = {'testMethod1', 'testMethod2'} 769 target_java = os.path.join( 770 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.java' 771 ) 772 self.assertEqual( 773 expect_methods, test_finder_utils.get_java_methods(target_java) 774 ) 775 target_kt = os.path.join( 776 uc.TEST_DATA_DIR, 'class_file_path_testing', 'hello_world_test.kt' 777 ) 778 self.assertEqual( 779 expect_methods, test_finder_utils.get_java_methods(target_kt) 780 ) 781 782 def test_get_parent_cls_name(self): 783 """Test get_parent_cls_name""" 784 parent_cls = 'AtestClass' 785 target_java = os.path.join( 786 uc.TEST_DATA_DIR, 'path_testing', 'PathTesting.java' 787 ) 788 self.assertEqual( 789 parent_cls, test_finder_utils.get_parent_cls_name(target_java) 790 ) 791 parent_cls = 'AtestClassKt' 792 target_java = os.path.join( 793 uc.TEST_DATA_DIR, 'path_testing', 'PathTesting.kt' 794 ) 795 self.assertEqual( 796 parent_cls, test_finder_utils.get_parent_cls_name(target_java) 797 ) 798 799 @staticmethod 800 def _get_paths_side_effect(module_name): 801 """Mock return values for module_info.get_paths.""" 802 if module_name == UNIT_TEST_MODULE_1: 803 return [IT_TEST_MATCHED_1_PATH] 804 if module_name == UNIT_TEST_MODULE_2: 805 return [UNIT_TEST_MATCHED_2_PATH] 806 if module_name == UNIT_TEST_MODULE_3: 807 return [UNIT_TEST_NOT_MATCHED_1_PATH] 808 return [] 809 810 @mock.patch.object( 811 module_info.ModuleInfo, 812 'get_all_host_unit_tests', 813 return_value=[UNIT_TEST_MODULE_1, UNIT_TEST_MODULE_2, UNIT_TEST_MODULE_3], 814 ) 815 @mock.patch.object( 816 module_info.ModuleInfo, 817 'get_paths', 818 ) 819 def test_find_host_unit_tests(self, _get_paths, _mock_get_unit_tests): 820 """Test find_host_unit_tests""" 821 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 822 _get_paths.side_effect = self._get_paths_side_effect 823 expect_unit_tests = [UNIT_TEST_MODULE_1, UNIT_TEST_MODULE_2] 824 self.assertEqual( 825 sorted(expect_unit_tests), 826 sorted( 827 test_finder_utils.find_host_unit_tests( 828 mod_info, UNIT_TEST_SEARCH_ROOT 829 ) 830 ), 831 ) 832 833 def test_get_annotated_methods(self): 834 """Test get_annotated_methods""" 835 sample_path = os.path.join(uc.TEST_DATA_DIR, 'annotation', 'sample.txt') 836 real_methods = list( 837 test_finder_utils.get_annotated_methods('TestAnnotation1', sample_path) 838 ) 839 real_methods.sort() 840 expect_methods = ['annotation1_method1', 'annotation1_method2'] 841 expect_methods.sort() 842 self.assertEqual(expect_methods, real_methods) 843 844 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 845 def test_get_test_config_use_androidtestxml(self, _isfile): 846 """Test get_test_config_and_srcs using default AndroidTest.xml""" 847 android_root = '/' 848 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 849 t_info = test_info.TestInfo( 850 'androidtest_config_module', 'mock_runner', build_targets=set() 851 ) 852 expect_config = os.path.join( 853 android_root, uc.ANDTEST_CONFIG_PATH, constants.MODULE_CONFIG 854 ) 855 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 856 self.assertEqual(expect_config, result) 857 858 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 859 def test_get_test_config_single_config(self, _isfile): 860 """Test get_test_config_and_srcs manually set it's config""" 861 android_root = '/' 862 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 863 t_info = test_info.TestInfo( 864 'single_config_module', 'mock_runner', build_targets=set() 865 ) 866 expect_config = os.path.join( 867 android_root, uc.SINGLE_CONFIG_PATH, uc.SINGLE_CONFIG_NAME 868 ) 869 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 870 self.assertEqual(expect_config, result) 871 872 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 873 def test_get_test_config_main_multiple_config(self, _isfile): 874 """Test get_test_config_and_srcs which is the main module of multiple config""" 875 android_root = '/' 876 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 877 t_info = test_info.TestInfo( 878 'multiple_config_module', 'mock_runner', build_targets=set() 879 ) 880 expect_config = os.path.join( 881 android_root, uc.MULTIPLE_CONFIG_PATH, uc.MAIN_CONFIG_NAME 882 ) 883 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 884 self.assertEqual(expect_config, result) 885 886 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 887 def test_get_test_config_subtest_in_multiple_config(self, _isfile): 888 """Test get_test_config_and_srcs not the main module of multiple config""" 889 android_root = '/' 890 mock_dict = { 891 'ANDROID_BUILD_TOP': android_root, 892 'ANDROID_PRODUCT_OUT': PRODUCT_OUT_DIR, 893 'ANDROID_HOST_OUT': HOST_OUT_DIR, 894 } 895 with mock.patch.dict('os.environ', mock_dict, clear=True): 896 mod_info = module_info.load_from_file(module_file=JSON_FILE_PATH) 897 t_info = test_info.TestInfo( 898 'Multiple2', 'mock_runner', build_targets=set() 899 ) 900 expect_config = Path( 901 android_root, uc.MULTIPLE_CONFIG_PATH, uc.SUB_CONFIG_NAME_2 902 ) 903 904 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 905 906 self.assertEqual(expect_config, result) 907 908 def test_is_test_from_kernel_xml_input_xml_not_exist_return_false(self): 909 not_exist_xml = 'not/exist/xml/path' 910 test_name = 'test_name' 911 912 exist = test_finder_utils.is_test_from_kernel_xml(not_exist_xml, test_name) 913 914 self.assertEqual(exist, False) 915 916 def test_parse_test_reference_input_module_class_method_match(self): 917 test_module = 'myModule' 918 test_class = 'myClass' 919 test_method = 'myTest::Method' 920 test_ref = f'{test_module}:{test_class}#{test_method}' 921 922 result = test_finder_utils.parse_test_reference(test_ref) 923 924 self.assertEqual(test_module, result['module_name']) 925 self.assertEqual(test_class, result['pkg_class_name']) 926 self.assertEqual(test_method, result['method_name']) 927 928 def test_parse_test_reference_input_module_class_match(self): 929 test_module = 'myModule' 930 test_class = 'myClass' 931 test_ref = f'{test_module}:{test_class}' 932 933 result = test_finder_utils.parse_test_reference(test_ref) 934 935 self.assertEqual(test_module, result['module_name']) 936 self.assertEqual(test_class, result['pkg_class_name']) 937 self.assertEqual('', result.get('method_name', '')) 938 939 def test_parse_test_reference_input_module_class_parameter_method_match(self): 940 test_module = 'myModule' 941 test_class = 'myClass' 942 test_method = 'myTest::Method[0]' 943 test_ref = f'{test_module}:{test_class}#{test_method}' 944 945 result = test_finder_utils.parse_test_reference(test_ref) 946 947 self.assertEqual(test_module, result['module_name']) 948 self.assertEqual(test_class, result['pkg_class_name']) 949 self.assertEqual(test_method, result['method_name']) 950 951 def test_parse_test_reference_input_module_class_multiple_methods_match(self): 952 test_module = 'myModule' 953 test_class = 'myClass' 954 test_method = 'myTest::Method[0],myTest::Method[1]' 955 test_ref = f'{test_module}:{test_class}#{test_method}' 956 957 result = test_finder_utils.parse_test_reference(test_ref) 958 959 self.assertEqual(test_module, result['module_name']) 960 self.assertEqual(test_class, result['pkg_class_name']) 961 self.assertEqual(test_method, result['method_name']) 962 963 def test_parse_test_reference_input_class_method_not_match(self): 964 test_class = 'myClass' 965 test_method = 'myTest::Method' 966 test_ref = f'{test_class}#{test_method}' 967 968 result = test_finder_utils.parse_test_reference(test_ref) 969 970 self.assertEqual(result, dict()) 971 972 def test_parse_test_reference_input_module_dashed_match(self): 973 test_module = 'my-module' 974 test_class = 'BR/EI/ZH' 975 test_ref = f'{test_module}:{test_class}' 976 977 result = test_finder_utils.parse_test_reference(test_ref) 978 979 self.assertEqual(test_module, result['module_name']) 980 self.assertEqual(test_class, result['pkg_class_name']) 981 982 def test_parse_test_reference_input_module_pkg_method_match(self): 983 test_module = 'myModule' 984 test_package = 'my.package' 985 test_method = 'myTest::Method' 986 test_ref = f'{test_module}:{test_package}#{test_method}' 987 988 result = test_finder_utils.parse_test_reference(test_ref) 989 990 self.assertEqual(test_module, result['module_name']) 991 self.assertEqual(test_package, result['pkg_class_name']) 992 self.assertEqual(test_method, result['method_name']) 993 994 def test_parse_test_reference_input_plan_class_match(self): 995 test_module = 'my/Module' 996 test_class = 'class' 997 test_ref = f'{test_module}:{test_class}' 998 999 result = test_finder_utils.parse_test_reference(test_ref) 1000 1001 self.assertEqual(test_module, result['module_name']) 1002 self.assertEqual(test_class, result['pkg_class_name']) 1003 self.assertEqual('', result.get('method_name', '')) 1004 1005 def test_parse_test_reference_input_module_parameter_class_and_method_match( 1006 self, 1007 ): 1008 test_module = 'myModule' 1009 test_class = 'myClass/abc0' 1010 test_method = 'myTest0/Method[0]' 1011 test_ref = f'{test_module}:{test_class}#{test_method}' 1012 1013 result = test_finder_utils.parse_test_reference(test_ref) 1014 1015 self.assertEqual(test_module, result['module_name']) 1016 self.assertEqual(test_class, result['pkg_class_name']) 1017 self.assertEqual(test_method, result['method_name']) 1018 1019 1020if __name__ == '__main__': 1021 unittest.main() 1022