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