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=line-too-long 20 21import os 22import tempfile 23import unittest 24 25from unittest import mock 26 27import atest_error 28import constants 29import module_info 30import unittest_constants as uc 31import unittest_utils 32 33from test_finders import test_finder_utils 34from 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 = {'VtsTestName', 52 'DATA/nativetest/vts_treble_vintf_test/vts_treble_vintf_test', 53 'DATA/nativetest64/vts_treble_vintf_test/vts_treble_vintf_test', 54 'DATA/lib/libhidl-gen-hash.so', 55 'DATA/lib64/libhidl-gen-hash.so', 56 'hal-hidl-hash/frameworks/hardware/interfaces/current.txt', 57 'hal-hidl-hash/hardware/interfaces/current.txt', 58 'hal-hidl-hash/system/hardware/interfaces/current.txt', 59 'hal-hidl-hash/system/libhidl/transport/current.txt', 60 'target_with_delim', 61 'out/dir/target', 62 'push_file1_target1', 63 'push_file1_target2', 64 'push_file2_target1', 65 'push_file2_target2', 66 'CtsDeviceInfo.apk', 67 'DATA/app/DeviceHealthTests/DeviceHealthTests.apk', 68 'DATA/app/sl4a/sl4a.apk'} 69VTS_PLAN_TARGETS = {os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-staging-default.xml.data'), 70 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-aa.xml.data'), 71 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-bb.xml.data'), 72 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-cc.xml.data'), 73 os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'vts-dd.xml.data')} 74XML_TARGETS = {'CtsJankDeviceTestCases', 'perf-setup', 'cts-tradefed', 75 'GtsEmptyTestApp'} 76PATH_TO_MODULE_INFO_WITH_AUTOGEN = { 77 'foo/bar/jank' : [{'auto_test_config' : True}]} 78PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN = { 79 'foo/bar/jank' : [{'auto_test_config' : True}, 80 {'auto_test_config' : True}]} 81PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN_AND_ROBO = { 82 'foo/bar' : [{'auto_test_config' : True}, 83 {'auto_test_config' : True}], 84 'foo/bar/jank': [{constants.MODULE_CLASS : [constants.MODULE_CLASS_ROBOLECTRIC]}]} 85UNIT_TEST_SEARCH_ROOT = 'my/unit/test/root' 86IT_TEST_MATCHED_1_PATH = os.path.join(UNIT_TEST_SEARCH_ROOT, 'sub1') 87UNIT_TEST_MATCHED_2_PATH = os.path.join(UNIT_TEST_SEARCH_ROOT, 'sub1', 'sub2') 88UNIT_TEST_NOT_MATCHED_1_PATH = os.path.join( 89 os.path.dirname(UNIT_TEST_SEARCH_ROOT), 'sub1') 90UNIT_TEST_MODULE_1 = 'unit_test_module_1' 91UNIT_TEST_MODULE_2 = 'unit_test_module_2' 92UNIT_TEST_MODULE_3 = 'unit_test_module_3' 93DALVIK_TEST_CONFIG = 'AndroidDalvikTest.xml.data' 94LIBCORE_TEST_CONFIG = 'AndroidLibCoreTest.xml.data' 95DALVIK_XML_TARGETS = XML_TARGETS | test_finder_utils.DALVIK_TEST_DEPS 96 97#pylint: disable=protected-access 98class TestFinderUtilsUnittests(unittest.TestCase): 99 """Unit tests for test_finder_utils.py""" 100 101 def test_split_methods(self): 102 """Test _split_methods method.""" 103 # Class 104 unittest_utils.assert_strict_equal( 105 self, 106 test_finder_utils.split_methods('Class.Name'), 107 ('Class.Name', set())) 108 unittest_utils.assert_strict_equal( 109 self, 110 test_finder_utils.split_methods('Class.Name#Method'), 111 ('Class.Name', {'Method'})) 112 unittest_utils.assert_strict_equal( 113 self, 114 test_finder_utils.split_methods('Class.Name#Method,Method2'), 115 ('Class.Name', {'Method', 'Method2'})) 116 unittest_utils.assert_strict_equal( 117 self, 118 test_finder_utils.split_methods('Class.Name#Method,Method2'), 119 ('Class.Name', {'Method', 'Method2'})) 120 unittest_utils.assert_strict_equal( 121 self, 122 test_finder_utils.split_methods('Class.Name#Method,Method2'), 123 ('Class.Name', {'Method', 'Method2'})) 124 self.assertRaises( 125 atest_error.TooManyMethodsError, test_finder_utils.split_methods, 126 'class.name#Method,class.name.2#method') 127 # Path 128 unittest_utils.assert_strict_equal( 129 self, 130 test_finder_utils.split_methods('foo/bar/class.java'), 131 ('foo/bar/class.java', set())) 132 unittest_utils.assert_strict_equal( 133 self, 134 test_finder_utils.split_methods('foo/bar/class.java#Method'), 135 ('foo/bar/class.java', {'Method'})) 136 137 @mock.patch.object(test_finder_utils, 'has_method_in_file', 138 return_value=False) 139 @mock.patch('builtins.input', return_value='0') 140 def test_extract_test_path(self, _, has_method): 141 """Test extract_test_dir method.""" 142 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 143 unittest_utils.assert_strict_equal( 144 self, test_finder_utils.extract_test_path(uc.FIND_ONE), paths) 145 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 146 unittest_utils.assert_strict_equal( 147 self, test_finder_utils.extract_test_path(FIND_TWO), paths) 148 has_method.return_value = True 149 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 150 unittest_utils.assert_strict_equal( 151 self, test_finder_utils.extract_test_path(uc.FIND_ONE, 'method'), paths) 152 153 def test_has_method_in_file(self): 154 """Test has_method_in_file method.""" 155 test_path = os.path.join(uc.TEST_DATA_DIR, 'class_file_path_testing', 156 'hello_world_test.cc') 157 self.assertTrue(test_finder_utils.has_method_in_file( 158 test_path, frozenset(['PrintHelloWorld']))) 159 self.assertFalse(test_finder_utils.has_method_in_file( 160 test_path, frozenset(['PrintHelloWorld1']))) 161 test_path = os.path.join(uc.TEST_DATA_DIR, 'class_file_path_testing', 162 'hello_world_test.java') 163 self.assertTrue(test_finder_utils.has_method_in_file( 164 test_path, frozenset(['testMethod1']))) 165 test_path = os.path.join(uc.TEST_DATA_DIR, 'class_file_path_testing', 166 'hello_world_test.java') 167 self.assertFalse(test_finder_utils.has_method_in_file( 168 test_path, frozenset(['testMethod', 'testMethod2']))) 169 test_path = os.path.join(uc.TEST_DATA_DIR, 'class_file_path_testing', 170 'hello_world_test.java') 171 self.assertFalse(test_finder_utils.has_method_in_file( 172 test_path, frozenset(['testMethod']))) 173 174 def test_has_method_in_kt_file(self): 175 """Test has_method_in_file method with kt class path.""" 176 test_path = os.path.join(uc.TEST_DATA_DIR, 'class_file_path_testing', 177 'hello_world_test.kt') 178 self.assertTrue(test_finder_utils.has_method_in_file( 179 test_path, frozenset(['testMethod1']))) 180 self.assertFalse(test_finder_utils.has_method_in_file( 181 test_path, frozenset(['testMethod']))) 182 self.assertTrue(test_finder_utils.has_method_in_file( 183 test_path, frozenset(['testMethod1', 'testMethod2']))) 184 self.assertFalse(test_finder_utils.has_method_in_file( 185 test_path, frozenset(['testMethod', 'testMethod2']))) 186 187 @mock.patch('builtins.input', return_value='1') 188 def test_extract_test_from_tests(self, mock_input): 189 """Test method extract_test_from_tests method.""" 190 tests = [] 191 self.assertEqual(test_finder_utils.extract_test_from_tests(tests), None) 192 paths = [os.path.join(uc.ROOT, CLASS_DIR, uc.CLASS_NAME + '.java')] 193 unittest_utils.assert_strict_equal( 194 self, test_finder_utils.extract_test_path(uc.FIND_ONE), paths) 195 paths = [os.path.join(uc.ROOT, OTHER_DIR, OTHER_CLASS_NAME)] 196 mock_input.return_value = '1' 197 unittest_utils.assert_strict_equal( 198 self, test_finder_utils.extract_test_path(FIND_TWO), paths) 199 # Test inputing out-of-range integer or a string 200 mock_input.return_value = '100' 201 self.assertEqual(test_finder_utils.extract_test_from_tests( 202 uc.CLASS_NAME), []) 203 mock_input.return_value = 'lOO' 204 self.assertEqual(test_finder_utils.extract_test_from_tests( 205 uc.CLASS_NAME), []) 206 207 @mock.patch('builtins.input', return_value='1') 208 def test_extract_test_from_multiselect(self, mock_input): 209 """Test method extract_test_from_tests method.""" 210 # selecting 'All' 211 paths = ['/a/b/c.java', '/d/e/f.java', '/g/h/i.java'] 212 mock_input.return_value = '3' 213 unittest_utils.assert_strict_equal( 214 self, sorted(test_finder_utils.extract_test_from_tests( 215 FIND_THREE_LIST)), sorted(paths)) 216 # multi-select 217 paths = ['/a/b/c.java', '/g/h/i.java'] 218 mock_input.return_value = '0,2' 219 unittest_utils.assert_strict_equal( 220 self, sorted(test_finder_utils.extract_test_from_tests( 221 FIND_THREE_LIST)), sorted(paths)) 222 # selecting a range 223 paths = ['/d/e/f.java', '/g/h/i.java'] 224 mock_input.return_value = '1-2' 225 unittest_utils.assert_strict_equal( 226 self, test_finder_utils.extract_test_from_tests(FIND_THREE_LIST), paths) 227 # mixed formats 228 paths = ['/a/b/c.java', '/d/e/f.java', '/g/h/i.java'] 229 mock_input.return_value = '0,1-2' 230 unittest_utils.assert_strict_equal( 231 self, sorted(test_finder_utils.extract_test_from_tests( 232 FIND_THREE_LIST)), sorted(paths)) 233 # input unsupported formats, return empty 234 paths = [] 235 mock_input.return_value = '?/#' 236 unittest_utils.assert_strict_equal( 237 self, test_finder_utils.extract_test_path(FIND_THREE), paths) 238 239 @mock.patch('os.path.isdir') 240 def test_is_equal_or_sub_dir(self, mock_isdir): 241 """Test is_equal_or_sub_dir method.""" 242 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', '/')) 243 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', '/a')) 244 self.assertTrue(test_finder_utils.is_equal_or_sub_dir('/a/b/c', 245 '/a/b/c')) 246 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a/b', 247 '/a/b/c')) 248 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a', '/f')) 249 mock_isdir.return_value = False 250 self.assertFalse(test_finder_utils.is_equal_or_sub_dir('/a/b', '/a')) 251 252 @mock.patch('os.path.isdir', return_value=True) 253 @mock.patch('os.path.isfile', 254 side_effect=unittest_utils.isfile_side_effect) 255 def test_find_parent_module_dir(self, _isfile, _isdir): 256 """Test _find_parent_module_dir method.""" 257 abs_class_dir = '/%s' % CLASS_DIR 258 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 259 mock_module_info.path_to_module_info = {} 260 unittest_utils.assert_strict_equal( 261 self, 262 test_finder_utils.find_parent_module_dir(uc.ROOT, 263 abs_class_dir, 264 mock_module_info), 265 uc.MODULE_DIR) 266 267 @mock.patch('os.path.isdir', return_value=True) 268 @mock.patch('os.path.isfile', return_value=False) 269 def test_find_parent_module_dir_with_autogen_config(self, _isfile, _isdir): 270 """Test _find_parent_module_dir method.""" 271 abs_class_dir = '/%s' % CLASS_DIR 272 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 273 mock_module_info.path_to_module_info = PATH_TO_MODULE_INFO_WITH_AUTOGEN 274 unittest_utils.assert_strict_equal( 275 self, 276 test_finder_utils.find_parent_module_dir(uc.ROOT, 277 abs_class_dir, 278 mock_module_info), 279 uc.MODULE_DIR) 280 281 @mock.patch('os.path.isdir', return_value=True) 282 @mock.patch('os.path.isfile', side_effect=[False] * 5 + [True]) 283 def test_find_parent_module_dir_with_autogen_subconfig(self, _isfile, _isdir): 284 """Test _find_parent_module_dir method. 285 286 This case is testing when the auto generated config is in a 287 sub-directory of a larger test that contains a test config in a parent 288 directory. 289 """ 290 abs_class_dir = '/%s' % CLASS_DIR 291 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 292 mock_module_info.path_to_module_info = ( 293 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN) 294 unittest_utils.assert_strict_equal( 295 self, 296 test_finder_utils.find_parent_module_dir(uc.ROOT, 297 abs_class_dir, 298 mock_module_info), 299 uc.MODULE_DIR) 300 301 @mock.patch('os.path.isdir', return_value=True) 302 @mock.patch('os.path.isfile', return_value=False) 303 def test_find_parent_module_dir_with_multi_autogens(self, _isfile, _isdir): 304 """Test _find_parent_module_dir method. 305 306 This case returns folders with multiple autogenerated configs defined. 307 """ 308 abs_class_dir = '/%s' % CLASS_DIR 309 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 310 mock_module_info.path_to_module_info = ( 311 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN) 312 unittest_utils.assert_strict_equal( 313 self, 314 test_finder_utils.find_parent_module_dir(uc.ROOT, 315 abs_class_dir, 316 mock_module_info), 317 uc.MODULE_DIR) 318 319 @mock.patch('os.path.isdir', return_value=True) 320 @mock.patch('os.path.isfile', return_value=False) 321 def test_find_parent_module_dir_with_robo_and_autogens(self, _isfile, 322 _isdir): 323 """Test _find_parent_module_dir method. 324 325 This case returns folders with multiple autogenerated configs defined 326 with a Robo test above them, which is the expected result. 327 """ 328 abs_class_dir = '/%s' % CLASS_DIR 329 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 330 mock_module_info.path_to_module_info = ( 331 PATH_TO_MODULE_INFO_WITH_MULTI_AUTOGEN_AND_ROBO) 332 unittest_utils.assert_strict_equal( 333 self, 334 test_finder_utils.find_parent_module_dir(uc.ROOT, 335 abs_class_dir, 336 mock_module_info), 337 uc.MODULE_DIR) 338 339 340 @mock.patch('os.path.isdir', return_value=True) 341 @mock.patch('os.path.isfile', return_value=False) 342 def test_find_parent_module_dir_robo(self, _isfile, _isdir): 343 """Test _find_parent_module_dir method. 344 345 Make sure we behave as expected when we encounter a robo module path. 346 """ 347 abs_class_dir = '/%s' % CLASS_DIR 348 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 349 mock_module_info.is_robolectric_module.return_value = True 350 rel_class_dir_path = os.path.relpath(abs_class_dir, uc.ROOT) 351 mock_module_info.path_to_module_info = {rel_class_dir_path: [{}]} 352 unittest_utils.assert_strict_equal( 353 self, 354 test_finder_utils.find_parent_module_dir(uc.ROOT, 355 abs_class_dir, 356 mock_module_info), 357 rel_class_dir_path) 358 359 def test_get_targets_from_xml(self): 360 """Test get_targets_from_xml method.""" 361 # Mocking Etree is near impossible, so use a real file, but mocking 362 # ModuleInfo is still fine. Just have it return False when it finds a 363 # module that states it's not a module. 364 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 365 mock_module_info.is_module.side_effect = lambda module: ( 366 not module == 'is_not_module') 367 xml_file = os.path.join(uc.TEST_DATA_DIR, 368 constants.MODULE_CONFIG + '.data') 369 unittest_utils.assert_strict_equal( 370 self, 371 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 372 XML_TARGETS) 373 374 def test_get_targets_from_dalvik_xml(self): 375 """Test get_targets_from_xml method with dalvik class.""" 376 # Mocking Etree is near impossible, so use a real file, but mocking 377 # ModuleInfo is still fine. Just have it return False when it finds a 378 # module that states it's not a module. 379 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 380 mock_module_info.is_module.side_effect = lambda module: ( 381 not module == 'is_not_module') 382 xml_file = os.path.join(uc.TEST_DATA_DIR, DALVIK_TEST_CONFIG) 383 unittest_utils.assert_strict_equal( 384 self, 385 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 386 DALVIK_XML_TARGETS) 387 388 def test_get_targets_from_libcore_xml(self): 389 """Test get_targets_from_xml method with libcore class.""" 390 # Mocking Etree is near impossible, so use a real file, but mocking 391 # ModuleInfo is still fine. Just have it return False when it finds a 392 # module that states it's not a module. 393 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 394 mock_module_info.is_module.side_effect = lambda module: ( 395 not module == 'is_not_module') 396 xml_file = os.path.join(uc.TEST_DATA_DIR, LIBCORE_TEST_CONFIG) 397 unittest_utils.assert_strict_equal( 398 self, 399 test_finder_utils.get_targets_from_xml(xml_file, mock_module_info), 400 DALVIK_XML_TARGETS) 401 402 @mock.patch.object(test_finder_utils, '_VTS_PUSH_DIR', 403 os.path.join(uc.TEST_DATA_DIR, VTS_PUSH_DIR)) 404 def test_get_targets_from_vts_xml(self): 405 """Test get_targets_from_vts_xml method.""" 406 # Mocking Etree is near impossible, so use a real file, but mock out 407 # ModuleInfo, 408 mock_module_info = mock.Mock(spec=module_info.ModuleInfo) 409 mock_module_info.is_module.return_value = True 410 xml_file = os.path.join(uc.TEST_DATA_DIR, VTS_XML) 411 unittest_utils.assert_strict_equal( 412 self, 413 test_finder_utils.get_targets_from_vts_xml(xml_file, '', 414 mock_module_info), 415 VTS_XML_TARGETS) 416 417 @mock.patch('subprocess.check_output') 418 def test_get_ignored_dirs(self, _mock_check_output): 419 """Test _get_ignored_dirs method.""" 420 421 # Clean cached value for test. 422 test_finder_utils._get_ignored_dirs.cached_ignore_dirs = [] 423 424 build_top = '/a/b' 425 _mock_check_output.return_value = ('/a/b/c/.find-ignore\n' 426 '/a/b/out/.out-dir\n' 427 '/a/b/d/.out-dir\n\n') 428 # Case 1: $OUT_DIR = ''. No customized out dir. 429 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 430 constants.ANDROID_OUT_DIR: ''} 431 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 432 correct_ignore_dirs = ['/a/b/c', '/a/b/out', '/a/b/d'] 433 ignore_dirs = test_finder_utils._get_ignored_dirs() 434 self.assertEqual(ignore_dirs, correct_ignore_dirs) 435 # Case 2: $OUT_DIR = 'out2' 436 test_finder_utils._get_ignored_dirs.cached_ignore_dirs = [] 437 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 438 constants.ANDROID_OUT_DIR: 'out2'} 439 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 440 correct_ignore_dirs = ['/a/b/c', '/a/b/out', '/a/b/d', '/a/b/out2'] 441 ignore_dirs = test_finder_utils._get_ignored_dirs() 442 self.assertEqual(ignore_dirs, correct_ignore_dirs) 443 # Case 3: The $OUT_DIR is abs dir but not under $ANDROID_BUILD_TOP 444 test_finder_utils._get_ignored_dirs.cached_ignore_dirs = [] 445 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 446 constants.ANDROID_OUT_DIR: '/x/y/e/g'} 447 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 448 correct_ignore_dirs = ['/a/b/c', '/a/b/out', '/a/b/d'] 449 ignore_dirs = test_finder_utils._get_ignored_dirs() 450 self.assertEqual(ignore_dirs, correct_ignore_dirs) 451 # Case 4: The $OUT_DIR is abs dir and under $ANDROID_BUILD_TOP 452 test_finder_utils._get_ignored_dirs.cached_ignore_dirs = [] 453 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 454 constants.ANDROID_OUT_DIR: '/a/b/e/g'} 455 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 456 correct_ignore_dirs = ['/a/b/c', '/a/b/out', '/a/b/d', '/a/b/e/g'] 457 ignore_dirs = test_finder_utils._get_ignored_dirs() 458 self.assertEqual(ignore_dirs, correct_ignore_dirs) 459 # Case 5: There is a file of '.out-dir' under $OUT_DIR. 460 test_finder_utils._get_ignored_dirs.cached_ignore_dirs = [] 461 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 462 constants.ANDROID_OUT_DIR: 'out'} 463 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 464 correct_ignore_dirs = ['/a/b/c', '/a/b/out', '/a/b/d'] 465 ignore_dirs = test_finder_utils._get_ignored_dirs() 466 self.assertEqual(ignore_dirs, correct_ignore_dirs) 467 # Case 6: Testing cache. All of the changes are useless. 468 _mock_check_output.return_value = ('/a/b/X/.find-ignore\n' 469 '/a/b/YY/.out-dir\n' 470 '/a/b/d/.out-dir\n\n') 471 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top, 472 constants.ANDROID_OUT_DIR: 'new'} 473 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 474 cached_answer = ['/a/b/c', '/a/b/out', '/a/b/d'] 475 none_cached_answer = ['/a/b/X', '/a/b/YY', '/a/b/d', 'a/b/new'] 476 ignore_dirs = test_finder_utils._get_ignored_dirs() 477 self.assertEqual(ignore_dirs, cached_answer) 478 self.assertNotEqual(ignore_dirs, none_cached_answer) 479 480 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 481 @mock.patch('builtins.input', return_value='0') 482 def test_search_integration_dirs(self, mock_input): 483 """Test search_integration_dirs.""" 484 mock_input.return_value = '0' 485 paths = [os.path.join(uc.ROOT, INT_DIR1, INT_FILE_NAME+'.xml')] 486 int_dirs = [INT_DIR1] 487 test_result = test_finder_utils.search_integration_dirs(INT_FILE_NAME, int_dirs) 488 unittest_utils.assert_strict_equal(self, test_result, paths) 489 int_dirs = [INT_DIR1, INT_DIR2] 490 test_result = test_finder_utils.search_integration_dirs(INT_FILE_NAME, int_dirs) 491 unittest_utils.assert_strict_equal(self, test_result, paths) 492 493 @mock.patch('os.path.isfile', return_value=False) 494 @mock.patch('os.environ.get', return_value=uc.TEST_CONFIG_DATA_DIR) 495 @mock.patch('builtins.input', return_value='0') 496 # pylint: disable=too-many-statements 497 def test_find_class_file(self, mock_input, _mock_env, _mock_isfile): 498 """Test find_class_file.""" 499 # 1. Java class(find). 500 java_tmp_test_result = [] 501 mock_input.return_value = '0' 502 java_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.java') 503 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 504 uc.FIND_PATH_TESTCASE_JAVA)) 505 mock_input.return_value = '1' 506 kt_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.kt') 507 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 508 uc.FIND_PATH_TESTCASE_JAVA)) 509 self.assertTrue(java_class in java_tmp_test_result) 510 self.assertTrue(kt_class in java_tmp_test_result) 511 512 # 2. Java class(read index). 513 del java_tmp_test_result[:] 514 mock_input.return_value = '0' 515 _mock_isfile = True 516 test_finder_utils.FIND_INDEXES['CLASS'] = uc.CLASS_INDEX 517 java_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.java') 518 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 519 uc.FIND_PATH_TESTCASE_JAVA)) 520 mock_input.return_value = '1' 521 kt_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_TESTCASE_JAVA + '.kt') 522 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 523 uc.FIND_PATH_TESTCASE_JAVA)) 524 self.assertTrue(java_class in java_tmp_test_result) 525 self.assertTrue(kt_class in java_tmp_test_result) 526 527 # 3. Qualified Java class(find). 528 del java_tmp_test_result[:] 529 mock_input.return_value = '0' 530 _mock_isfile = False 531 java_qualified_class = '{0}.{1}'.format(uc.FIND_PATH_FOLDER, uc.FIND_PATH_TESTCASE_JAVA) 532 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 533 java_qualified_class)) 534 mock_input.return_value = '1' 535 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 536 java_qualified_class)) 537 self.assertTrue(java_class in java_tmp_test_result) 538 self.assertTrue(kt_class in java_tmp_test_result) 539 540 # 4. Qualified Java class(read index). 541 del java_tmp_test_result[:] 542 mock_input.return_value = '0' 543 _mock_isfile = True 544 test_finder_utils.FIND_INDEXES['QUALIFIED_CLASS'] = uc.QCLASS_INDEX 545 java_qualified_class = '{0}.{1}'.format(uc.FIND_PATH_FOLDER, uc.FIND_PATH_TESTCASE_JAVA) 546 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 547 java_qualified_class)) 548 mock_input.return_value = '1' 549 java_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 550 java_qualified_class)) 551 self.assertTrue(java_class in java_tmp_test_result) 552 self.assertTrue(kt_class in java_tmp_test_result) 553 554 # 5. CC class(find). 555 cc_tmp_test_result = [] 556 _mock_isfile = False 557 mock_input.return_value = '0' 558 cpp_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cpp') 559 cc_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 560 uc.FIND_PATH_TESTCASE_CC, 561 True)) 562 mock_input.return_value = '1' 563 cc_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cc') 564 cc_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 565 uc.FIND_PATH_TESTCASE_CC, 566 True)) 567 self.assertTrue(cpp_class in cc_tmp_test_result) 568 self.assertTrue(cc_class in cc_tmp_test_result) 569 570 # 6. CC class(read index). 571 del cc_tmp_test_result[:] 572 mock_input.return_value = '0' 573 _mock_isfile = True 574 test_finder_utils.FIND_INDEXES['CC_CLASS'] = uc.CC_CLASS_INDEX 575 cpp_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cpp') 576 cc_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 577 uc.FIND_PATH_TESTCASE_CC, 578 True)) 579 mock_input.return_value = '1' 580 cc_class = os.path.join(uc.FIND_PATH, uc.FIND_PATH_FILENAME_CC + '.cc') 581 cc_tmp_test_result.extend(test_finder_utils.find_class_file(uc.FIND_PATH, 582 uc.FIND_PATH_TESTCASE_CC, 583 True)) 584 self.assertTrue(cpp_class in cc_tmp_test_result) 585 self.assertTrue(cc_class in cc_tmp_test_result) 586 587 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 588 @mock.patch('builtins.input', return_value='0') 589 @mock.patch.object(test_finder_utils, 'get_dir_path_and_filename') 590 @mock.patch('os.path.exists', return_value=True) 591 def test_get_int_dir_from_path(self, _exists, _find, mock_input): 592 """Test get_int_dir_from_path.""" 593 mock_input.return_value = '0' 594 int_dirs = [INT_DIR1] 595 path = os.path.join(uc.ROOT, INT_DIR1, INT_FILE_NAME+'.xml') 596 _find.return_value = (INT_DIR1, INT_FILE_NAME+'.xml') 597 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 598 unittest_utils.assert_strict_equal(self, test_result, INT_DIR1) 599 _find.return_value = (INT_DIR1, None) 600 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 601 unittest_utils.assert_strict_equal(self, test_result, None) 602 int_dirs = [INT_DIR1, INT_DIR2] 603 _find.return_value = (INT_DIR1, INT_FILE_NAME+'.xml') 604 test_result = test_finder_utils.get_int_dir_from_path(path, int_dirs) 605 unittest_utils.assert_strict_equal(self, test_result, INT_DIR1) 606 607 def test_get_install_locations(self): 608 """Test get_install_locations.""" 609 host_installed_paths = ["out/host/a/b"] 610 host_expect = set(['host']) 611 self.assertEqual(test_finder_utils.get_install_locations(host_installed_paths), 612 host_expect) 613 device_installed_paths = ["out/target/c/d"] 614 device_expect = set(['device']) 615 self.assertEqual(test_finder_utils.get_install_locations(device_installed_paths), 616 device_expect) 617 both_installed_paths = ["out/host/e", "out/target/f"] 618 both_expect = set(['host', 'device']) 619 self.assertEqual(test_finder_utils.get_install_locations(both_installed_paths), 620 both_expect) 621 no_installed_paths = [] 622 no_expect = set() 623 self.assertEqual(test_finder_utils.get_install_locations(no_installed_paths), 624 no_expect) 625 626 # Disable the fail test due to the breakage if test xml rename to xml.data. 627 # pylint: disable=pointless-string-statement 628 ''' 629 def test_get_plans_from_vts_xml(self): 630 """Test get_plans_from_vts_xml method.""" 631 xml_path = os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 632 'vts-staging-default.xml.data') 633 self.assertEqual( 634 test_finder_utils.get_plans_from_vts_xml(xml_path), 635 VTS_PLAN_TARGETS) 636 xml_path = os.path.join(uc.TEST_DATA_DIR, VTS_PLAN_DIR, 'NotExist.xml') 637 self.assertRaises(atest_error.XmlNotExistError, 638 test_finder_utils.get_plans_from_vts_xml, xml_path) 639 ''' 640 641 def test_get_levenshtein_distance(self): 642 """Test get_levenshetine distance module correctly returns distance.""" 643 self.assertEqual(test_finder_utils.get_levenshtein_distance(uc.MOD1, uc.FUZZY_MOD1), 1) 644 self.assertEqual(test_finder_utils.get_levenshtein_distance(uc.MOD2, uc.FUZZY_MOD2, 645 dir_costs=(1, 2, 3)), 3) 646 self.assertEqual(test_finder_utils.get_levenshtein_distance(uc.MOD3, uc.FUZZY_MOD3, 647 dir_costs=(1, 2, 1)), 8) 648 649 def test_is_parameterized_java_class(self): 650 """Test is_parameterized_java_class method.""" 651 matched_contents = (['@RunWith(Parameterized.class)'], 652 [' @RunWith( Parameterized.class ) '], 653 ['@RunWith(TestParameterInjector.class)'], 654 ['@RunWith(JUnitParamsRunner.class)'], 655 ['@RunWith(DataProviderRunner.class)'], 656 ['@RunWith(JukitoRunner.class)'], 657 ['@RunWith(Theories.class)'], 658 ['@RunWith(BedsteadJUnit4.class)']) 659 not_matched_contents = (['// @RunWith(Parameterized.class)'], 660 ['*RunWith(Parameterized.class)']) 661 # Test matched patterns 662 for matched_content in matched_contents: 663 try: 664 tmp_file = tempfile.NamedTemporaryFile(mode='wt') 665 tmp_file.writelines(matched_content) 666 tmp_file.flush() 667 finally: 668 tmp_file.close() 669 # Test not matched patterns 670 for not_matched_content in not_matched_contents: 671 try: 672 tmp_file = tempfile.NamedTemporaryFile(mode='wt') 673 tmp_file.writelines(not_matched_content) 674 tmp_file.flush() 675 finally: 676 tmp_file.close() 677 678 def test_get_cc_test_classes_methods(self): 679 """Test get_cc_test_classes_methods method.""" 680 expect_classes = ('MyClass1', 'MyClass2', 'MyClass3', 'MyClass4', 681 'MyClass5') 682 expect_methods = ('Method1', 'Method2', 'Method3', 'Method5') 683 expect_para_classes = ('MyInstantClass1', 'MyInstantClass2', 684 'MyInstantClass3', 'MyInstantTypeClass1', 685 'MyInstantTypeClass2') 686 expected_result = [sorted(expect_classes), sorted(expect_methods), 687 sorted(expect_para_classes)] 688 file_path = os.path.join(uc.TEST_DATA_DIR, 'my_cc_test.cc') 689 classes, methods, para_classes = ( 690 test_finder_utils.get_cc_test_classes_methods(file_path)) 691 self.assertEqual(expected_result, 692 [sorted(classes), 693 sorted(methods), 694 sorted(para_classes)]) 695 696 def test_get_java_method(self): 697 """Test get_java_method""" 698 expect_methods = {'testMethod1', 'testMethod2'} 699 target_java = os.path.join(uc.TEST_DATA_DIR, 700 'class_file_path_testing', 701 'hello_world_test.java') 702 self.assertEqual(expect_methods, 703 test_finder_utils.get_java_methods(target_java)) 704 target_kt = os.path.join(uc.TEST_DATA_DIR, 705 'class_file_path_testing', 706 'hello_world_test.kt') 707 self.assertEqual(expect_methods, 708 test_finder_utils.get_java_methods(target_kt)) 709 710 def test_get_parent_cls_name(self): 711 """Test get_parent_cls_name""" 712 parent_cls = 'AtestClass' 713 target_java = os.path.join(uc.TEST_DATA_DIR, 714 'path_testing', 715 'PathTesting.java') 716 self.assertEqual(parent_cls, 717 test_finder_utils.get_parent_cls_name(target_java)) 718 719 def test_get_package_name(self): 720 """Test get_package_name""" 721 package_name = 'com.test.hello_world_test' 722 target_java = os.path.join(uc.TEST_DATA_DIR, 723 'class_file_path_testing', 724 'hello_world_test.java') 725 self.assertEqual(package_name, 726 test_finder_utils.get_package_name(target_java)) 727 target_kt = os.path.join(uc.TEST_DATA_DIR, 728 'class_file_path_testing', 729 'hello_world_test.kt') 730 self.assertEqual(package_name, 731 test_finder_utils.get_package_name(target_kt)) 732 733 def get_paths_side_effect(self, module_name): 734 """Mock return values for module_info.get_paths.""" 735 if module_name == UNIT_TEST_MODULE_1: 736 return [IT_TEST_MATCHED_1_PATH] 737 if module_name == UNIT_TEST_MODULE_2: 738 return [UNIT_TEST_MATCHED_2_PATH] 739 if module_name == UNIT_TEST_MODULE_3: 740 return [UNIT_TEST_NOT_MATCHED_1_PATH] 741 return [] 742 743 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 744 @mock.patch.object(module_info.ModuleInfo, 'get_all_unit_tests', 745 return_value=[UNIT_TEST_MODULE_1, 746 UNIT_TEST_MODULE_2, 747 UNIT_TEST_MODULE_3]) 748 @mock.patch.object(module_info.ModuleInfo, 'get_paths',) 749 def test_find_host_unit_tests(self, _get_paths, _mock_get_unit_tests): 750 """Test find_host_unit_tests""" 751 mod_info = module_info.ModuleInfo(module_file=JSON_FILE_PATH) 752 _get_paths.side_effect = self.get_paths_side_effect 753 expect_unit_tests = [UNIT_TEST_MODULE_1, UNIT_TEST_MODULE_2] 754 self.assertEqual( 755 sorted(expect_unit_tests), 756 sorted(test_finder_utils.find_host_unit_tests( 757 mod_info, UNIT_TEST_SEARCH_ROOT))) 758 759 def test_get_annotated_methods(self): 760 """Test get_annotated_methods""" 761 sample_path = os.path.join( 762 uc.TEST_DATA_DIR, 'annotation', 'sample.txt') 763 real_methods = list(test_finder_utils.get_annotated_methods( 764 'TestAnnotation1', sample_path)) 765 real_methods.sort() 766 expect_methods = ['annotation1_method1', 'annotation1_method2'] 767 expect_methods.sort() 768 self.assertEqual(expect_methods, real_methods) 769 770 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 771 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 772 def test_get_test_config_use_androidtestxml(self, _isfile): 773 """Test get_test_config_and_srcs using default AndroidTest.xml""" 774 android_root = '/' 775 mod_info = module_info.ModuleInfo(module_file=JSON_FILE_PATH) 776 t_info = test_info.TestInfo( 777 'androidtest_config_module', 'mock_runner', build_targets=set()) 778 expect_config = os.path.join(android_root, uc.ANDTEST_CONFIG_PATH, 779 constants.MODULE_CONFIG) 780 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 781 self.assertEqual(expect_config, result) 782 783 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 784 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 785 def test_get_test_config_single_config(self, _isfile): 786 """Test get_test_config_and_srcs manualy set it's config""" 787 android_root = '/' 788 mod_info = module_info.ModuleInfo(module_file=JSON_FILE_PATH) 789 t_info = test_info.TestInfo( 790 'single_config_module', 'mock_runner', build_targets=set()) 791 expect_config = os.path.join( 792 android_root, uc.SINGLE_CONFIG_PATH, uc.SINGLE_CONFIG_NAME) 793 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 794 self.assertEqual(expect_config, result) 795 796 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 797 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 798 def test_get_test_config_main_multiple_config(self, _isfile): 799 """Test get_test_config_and_srcs which is the main module of multiple config""" 800 android_root = '/' 801 mod_info = module_info.ModuleInfo(module_file=JSON_FILE_PATH) 802 t_info = test_info.TestInfo( 803 'multiple_config_module', 'mock_runner', build_targets=set()) 804 expect_config = os.path.join( 805 android_root, uc.MULTIPLE_CONFIG_PATH, uc.MAIN_CONFIG_NAME) 806 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 807 self.assertEqual(expect_config, result) 808 809 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/'}) 810 @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect) 811 def test_get_test_config_subtest_in_multiple_config(self, _isfile): 812 """Test get_test_config_and_srcs not the main module of multiple config""" 813 android_root = '/' 814 mod_info = module_info.ModuleInfo(module_file=JSON_FILE_PATH) 815 t_info = test_info.TestInfo( 816 'Multiple2', 'mock_runner', build_targets=set()) 817 expect_config = os.path.join( 818 android_root, uc.MULTIPLE_CONFIG_PATH, uc.SUB_CONFIG_NAME_2) 819 result, _ = test_finder_utils.get_test_config_and_srcs(t_info, mod_info) 820 self.assertEqual(expect_config, result) 821 822if __name__ == '__main__': 823 unittest.main() 824