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 atest_utils.""" 18 19# pylint: disable=line-too-long 20 21import hashlib 22import os 23import subprocess 24import sys 25import tempfile 26import unittest 27 28from io import StringIO 29from unittest import mock 30 31import atest_error 32import atest_utils 33import constants 34import unittest_utils 35import unittest_constants 36 37from test_finders import test_info 38 39 40TEST_MODULE_NAME_A = 'ModuleNameA' 41TEST_RUNNER_A = 'FakeTestRunnerA' 42TEST_BUILD_TARGET_A = set(['bt1', 'bt2']) 43TEST_DATA_A = {'test_data_a_1': 'a1', 44 'test_data_a_2': 'a2'} 45TEST_SUITE_A = 'FakeSuiteA' 46TEST_MODULE_CLASS_A = 'FAKE_MODULE_CLASS_A' 47TEST_INSTALL_LOC_A = set(['host', 'device']) 48TEST_FINDER_A = 'MODULE' 49TEST_INFO_A = test_info.TestInfo(TEST_MODULE_NAME_A, TEST_RUNNER_A, 50 TEST_BUILD_TARGET_A, TEST_DATA_A, 51 TEST_SUITE_A, TEST_MODULE_CLASS_A, 52 TEST_INSTALL_LOC_A) 53TEST_INFO_A.test_finder = TEST_FINDER_A 54TEST_ZIP_DATA_DIR = 'zip_files' 55TEST_SINGLE_ZIP_NAME = 'single_file.zip' 56TEST_MULTI_ZIP_NAME = 'multi_file.zip' 57 58REPO_INFO_OUTPUT = '''Manifest branch: test_branch 59Manifest merge branch: refs/heads/test_branch 60Manifest groups: all,-notdefault 61---------------------------- 62''' 63 64#pylint: disable=protected-access 65class AtestUtilsUnittests(unittest.TestCase): 66 """Unit tests for atest_utils.py""" 67 68 def test_capture_fail_section_has_fail_section(self): 69 """Test capture_fail_section when has fail section.""" 70 test_list = ['AAAAAA', 'FAILED: Error1', '^\n', 'Error2\n', 71 '[ 6% 191/2997] BBBBBB\n', 'CCCCC', 72 '[ 20% 322/2997] DDDDDD\n', 'EEEEE'] 73 want_list = ['FAILED: Error1', '^\n', 'Error2\n'] 74 self.assertEqual(want_list, 75 atest_utils._capture_fail_section(test_list)) 76 77 def test_capture_fail_section_no_fail_section(self): 78 """Test capture_fail_section when no fail section.""" 79 test_list = ['[ 6% 191/2997] XXXXX', 'YYYYY: ZZZZZ'] 80 want_list = [] 81 self.assertEqual(want_list, 82 atest_utils._capture_fail_section(test_list)) 83 84 def test_is_test_mapping(self): 85 """Test method is_test_mapping.""" 86 tm_option_attributes = [ 87 'test_mapping', 88 'include_subdirs' 89 ] 90 for attr_to_test in tm_option_attributes: 91 args = mock.Mock() 92 for attr in tm_option_attributes: 93 setattr(args, attr, attr == attr_to_test) 94 args.tests = [] 95 args.host_unit_test_only = False 96 self.assertTrue( 97 atest_utils.is_test_mapping(args), 98 'Failed to validate option %s' % attr_to_test) 99 100 args = mock.Mock() 101 for attr in tm_option_attributes: 102 setattr(args, attr, False) 103 args.tests = [] 104 args.host_unit_test_only = True 105 self.assertFalse(atest_utils.is_test_mapping(args)) 106 107 args = mock.Mock() 108 for attr in tm_option_attributes: 109 setattr(args, attr, False) 110 args.tests = [':group_name'] 111 args.host_unit_test_only = False 112 self.assertTrue(atest_utils.is_test_mapping(args)) 113 114 args = mock.Mock() 115 for attr in tm_option_attributes: 116 setattr(args, attr, False) 117 args.tests = [':test1', 'test2'] 118 args.host_unit_test_only = False 119 self.assertFalse(atest_utils.is_test_mapping(args)) 120 121 args = mock.Mock() 122 for attr in tm_option_attributes: 123 setattr(args, attr, False) 124 args.tests = ['test2'] 125 args.host_unit_test_only = False 126 self.assertFalse(atest_utils.is_test_mapping(args)) 127 128 @mock.patch('curses.tigetnum') 129 def test_has_colors(self, mock_curses_tigetnum): 130 """Test method _has_colors.""" 131 # stream is file I/O 132 stream = open('/tmp/test_has_colors.txt', 'wb') 133 self.assertFalse(atest_utils._has_colors(stream)) 134 stream.close() 135 136 # stream is not a tty(terminal). 137 stream = mock.Mock() 138 stream.isatty.return_value = False 139 self.assertFalse(atest_utils._has_colors(stream)) 140 141 # stream is a tty(terminal) and colors < 2. 142 stream = mock.Mock() 143 stream.isatty.return_value = True 144 mock_curses_tigetnum.return_value = 1 145 self.assertFalse(atest_utils._has_colors(stream)) 146 147 # stream is a tty(terminal) and colors > 2. 148 stream = mock.Mock() 149 stream.isatty.return_value = True 150 mock_curses_tigetnum.return_value = 256 151 self.assertTrue(atest_utils._has_colors(stream)) 152 153 154 @mock.patch('atest_utils._has_colors') 155 def test_colorize(self, mock_has_colors): 156 """Test method colorize.""" 157 original_str = "test string" 158 green_no = 2 159 160 # _has_colors() return False. 161 mock_has_colors.return_value = False 162 converted_str = atest_utils.colorize(original_str, green_no, 163 highlight=True) 164 self.assertEqual(original_str, converted_str) 165 166 # Green with highlight. 167 mock_has_colors.return_value = True 168 converted_str = atest_utils.colorize(original_str, green_no, 169 highlight=True) 170 green_highlight_string = '\x1b[1;42m%s\x1b[0m' % original_str 171 self.assertEqual(green_highlight_string, converted_str) 172 173 # Green, no highlight. 174 mock_has_colors.return_value = True 175 converted_str = atest_utils.colorize(original_str, green_no, 176 highlight=False) 177 green_no_highlight_string = '\x1b[1;32m%s\x1b[0m' % original_str 178 self.assertEqual(green_no_highlight_string, converted_str) 179 180 181 @mock.patch('atest_utils._has_colors') 182 def test_colorful_print(self, mock_has_colors): 183 """Test method colorful_print.""" 184 testing_str = "color_print_test" 185 green_no = 2 186 187 # _has_colors() return False. 188 mock_has_colors.return_value = False 189 capture_output = StringIO() 190 sys.stdout = capture_output 191 atest_utils.colorful_print(testing_str, green_no, highlight=True, 192 auto_wrap=False) 193 sys.stdout = sys.__stdout__ 194 uncolored_string = testing_str 195 self.assertEqual(capture_output.getvalue(), uncolored_string) 196 197 # Green with highlight, but no wrap. 198 mock_has_colors.return_value = True 199 capture_output = StringIO() 200 sys.stdout = capture_output 201 atest_utils.colorful_print(testing_str, green_no, highlight=True, 202 auto_wrap=False) 203 sys.stdout = sys.__stdout__ 204 green_highlight_no_wrap_string = '\x1b[1;42m%s\x1b[0m' % testing_str 205 self.assertEqual(capture_output.getvalue(), 206 green_highlight_no_wrap_string) 207 208 # Green, no highlight, no wrap. 209 mock_has_colors.return_value = True 210 capture_output = StringIO() 211 sys.stdout = capture_output 212 atest_utils.colorful_print(testing_str, green_no, highlight=False, 213 auto_wrap=False) 214 sys.stdout = sys.__stdout__ 215 green_no_high_no_wrap_string = '\x1b[1;32m%s\x1b[0m' % testing_str 216 self.assertEqual(capture_output.getvalue(), 217 green_no_high_no_wrap_string) 218 219 # Green with highlight and wrap. 220 mock_has_colors.return_value = True 221 capture_output = StringIO() 222 sys.stdout = capture_output 223 atest_utils.colorful_print(testing_str, green_no, highlight=True, 224 auto_wrap=True) 225 sys.stdout = sys.__stdout__ 226 green_highlight_wrap_string = '\x1b[1;42m%s\x1b[0m\n' % testing_str 227 self.assertEqual(capture_output.getvalue(), green_highlight_wrap_string) 228 229 # Green with wrap, but no highlight. 230 mock_has_colors.return_value = True 231 capture_output = StringIO() 232 sys.stdout = capture_output 233 atest_utils.colorful_print(testing_str, green_no, highlight=False, 234 auto_wrap=True) 235 sys.stdout = sys.__stdout__ 236 green_wrap_no_highlight_string = '\x1b[1;32m%s\x1b[0m\n' % testing_str 237 self.assertEqual(capture_output.getvalue(), 238 green_wrap_no_highlight_string) 239 240 @mock.patch('socket.gethostname') 241 @mock.patch('subprocess.check_output') 242 def test_is_external_run(self, mock_output, mock_hostname): 243 """Test method is_external_run.""" 244 mock_output.return_value = '' 245 mock_hostname.return_value = '' 246 self.assertTrue(atest_utils.is_external_run()) 247 248 mock_output.return_value = 'test@other.com' 249 mock_hostname.return_value = 'abc.com' 250 self.assertTrue(atest_utils.is_external_run()) 251 252 mock_output.return_value = 'test@other.com' 253 mock_hostname.return_value = 'abc.google.com' 254 self.assertFalse(atest_utils.is_external_run()) 255 256 mock_output.return_value = 'test@other.com' 257 mock_hostname.return_value = 'abc.google.def.com' 258 self.assertTrue(atest_utils.is_external_run()) 259 260 mock_output.return_value = 'test@google.com' 261 self.assertFalse(atest_utils.is_external_run()) 262 263 mock_output.return_value = 'test@other.com' 264 mock_hostname.return_value = 'c.googlers.com' 265 self.assertFalse(atest_utils.is_external_run()) 266 267 mock_output.return_value = 'test@other.com' 268 mock_hostname.return_value = 'a.googlers.com' 269 self.assertTrue(atest_utils.is_external_run()) 270 271 mock_output.side_effect = OSError() 272 self.assertTrue(atest_utils.is_external_run()) 273 274 mock_output.side_effect = subprocess.CalledProcessError(1, 'cmd') 275 self.assertTrue(atest_utils.is_external_run()) 276 277 @mock.patch('metrics.metrics_base.get_user_type') 278 def test_print_data_collection_notice(self, mock_get_user_type): 279 """Test method print_data_collection_notice.""" 280 281 # get_user_type return 1(external). 282 mock_get_user_type.return_value = 1 283 notice_str = ('\n==================\nNotice:\n' 284 ' We collect anonymous usage statistics' 285 ' in accordance with our' 286 ' Content Licenses (https://source.android.com/setup/start/licenses),' 287 ' Contributor License Agreement (https://opensource.google.com/docs/cla/),' 288 ' Privacy Policy (https://policies.google.com/privacy) and' 289 ' Terms of Service (https://policies.google.com/terms).' 290 '\n==================\n\n') 291 capture_output = StringIO() 292 sys.stdout = capture_output 293 atest_utils.print_data_collection_notice() 294 sys.stdout = sys.__stdout__ 295 uncolored_string = notice_str 296 self.assertEqual(capture_output.getvalue(), uncolored_string) 297 298 # get_user_type return 0(internal). 299 mock_get_user_type.return_value = 0 300 notice_str = ('\n==================\nNotice:\n' 301 ' We collect usage statistics' 302 ' in accordance with our' 303 ' Content Licenses (https://source.android.com/setup/start/licenses),' 304 ' Contributor License Agreement (https://cla.developers.google.com/),' 305 ' Privacy Policy (https://policies.google.com/privacy) and' 306 ' Terms of Service (https://policies.google.com/terms).' 307 '\n==================\n\n') 308 capture_output = StringIO() 309 sys.stdout = capture_output 310 atest_utils.print_data_collection_notice() 311 sys.stdout = sys.__stdout__ 312 uncolored_string = notice_str 313 self.assertEqual(capture_output.getvalue(), uncolored_string) 314 315 @mock.patch('builtins.input') 316 @mock.patch('json.load') 317 def test_update_test_runner_cmd(self, mock_json_load_data, mock_input): 318 """Test method handle_test_runner_cmd without enable do_verification.""" 319 former_cmd_str = 'Former cmds =' 320 write_result_str = 'Save result mapping to test_result' 321 tmp_file = tempfile.NamedTemporaryFile() 322 input_cmd = 'atest_args' 323 runner_cmds = ['cmd1', 'cmd2'] 324 capture_output = StringIO() 325 sys.stdout = capture_output 326 # Previous data is empty. Should not enter strtobool. 327 # If entered, exception will be raised cause test fail. 328 mock_json_load_data.return_value = {} 329 atest_utils.handle_test_runner_cmd(input_cmd, 330 runner_cmds, 331 do_verification=False, 332 result_path=tmp_file.name) 333 sys.stdout = sys.__stdout__ 334 self.assertEqual(capture_output.getvalue().find(former_cmd_str), -1) 335 # Previous data is the same as the new input. Should not enter strtobool. 336 # If entered, exception will be raised cause test fail 337 capture_output = StringIO() 338 sys.stdout = capture_output 339 mock_json_load_data.return_value = {input_cmd:runner_cmds} 340 atest_utils.handle_test_runner_cmd(input_cmd, 341 runner_cmds, 342 do_verification=False, 343 result_path=tmp_file.name) 344 sys.stdout = sys.__stdout__ 345 self.assertEqual(capture_output.getvalue().find(former_cmd_str), -1) 346 self.assertEqual(capture_output.getvalue().find(write_result_str), -1) 347 # Previous data has different cmds. Should enter strtobool not update, 348 # should not find write_result_str. 349 prev_cmds = ['cmd1'] 350 mock_input.return_value = 'n' 351 capture_output = StringIO() 352 sys.stdout = capture_output 353 mock_json_load_data.return_value = {input_cmd:prev_cmds} 354 atest_utils.handle_test_runner_cmd(input_cmd, 355 runner_cmds, 356 do_verification=False, 357 result_path=tmp_file.name) 358 sys.stdout = sys.__stdout__ 359 self.assertEqual(capture_output.getvalue().find(write_result_str), -1) 360 361 @mock.patch('json.load') 362 def test_verify_test_runner_cmd(self, mock_json_load_data): 363 """Test method handle_test_runner_cmd without enable update_result.""" 364 tmp_file = tempfile.NamedTemporaryFile() 365 input_cmd = 'atest_args' 366 runner_cmds = ['cmd1', 'cmd2'] 367 # Previous data is the same as the new input. Should not raise exception. 368 mock_json_load_data.return_value = {input_cmd:runner_cmds} 369 atest_utils.handle_test_runner_cmd(input_cmd, 370 runner_cmds, 371 do_verification=True, 372 result_path=tmp_file.name) 373 # Previous data has different cmds. Should enter strtobool and hit 374 # exception. 375 prev_cmds = ['cmd1'] 376 mock_json_load_data.return_value = {input_cmd:prev_cmds} 377 self.assertRaises(atest_error.DryRunVerificationError, 378 atest_utils.handle_test_runner_cmd, 379 input_cmd, 380 runner_cmds, 381 do_verification=True, 382 result_path=tmp_file.name) 383 384 def test_get_test_info_cache_path(self): 385 """Test method get_test_info_cache_path.""" 386 input_file_name = 'mytest_name' 387 cache_root = '/a/b/c' 388 expect_hashed_name = ('%s.cache' % hashlib.md5(str(input_file_name). 389 encode()).hexdigest()) 390 self.assertEqual(os.path.join(cache_root, expect_hashed_name), 391 atest_utils.get_test_info_cache_path(input_file_name, 392 cache_root)) 393 394 def test_get_and_load_cache(self): 395 """Test method update_test_info_cache and load_test_info_cache.""" 396 test_reference = 'myTestRefA' 397 test_cache_dir = tempfile.mkdtemp() 398 atest_utils.update_test_info_cache(test_reference, [TEST_INFO_A], 399 test_cache_dir) 400 unittest_utils.assert_equal_testinfo_sets( 401 self, set([TEST_INFO_A]), 402 atest_utils.load_test_info_cache(test_reference, test_cache_dir)) 403 404 @mock.patch('os.getcwd') 405 def test_get_build_cmd(self, mock_cwd): 406 """Test method get_build_cmd.""" 407 build_top = '/home/a/b/c' 408 rel_path = 'd/e' 409 mock_cwd.return_value = os.path.join(build_top, rel_path) 410 os_environ_mock = {constants.ANDROID_BUILD_TOP: build_top} 411 with mock.patch.dict('os.environ', os_environ_mock, clear=True): 412 expected_cmd = ['../../build/soong/soong_ui.bash', '--make-mode'] 413 self.assertEqual(expected_cmd, atest_utils.get_build_cmd()) 414 415 @mock.patch('subprocess.check_output') 416 def test_get_modified_files(self, mock_co): 417 """Test method get_modified_files""" 418 mock_co.side_effect = [ 419 x.encode('utf-8') for x in ['/a/b/', 420 '\n', 421 'test_fp1.java\nc/test_fp2.java']] 422 self.assertEqual({'/a/b/test_fp1.java', '/a/b/c/test_fp2.java'}, 423 atest_utils.get_modified_files('')) 424 mock_co.side_effect = [ 425 x.encode('utf-8') for x in ['/a/b/', 426 'test_fp4', 427 '/test_fp3.java']] 428 self.assertEqual({'/a/b/test_fp4', '/a/b/test_fp3.java'}, 429 atest_utils.get_modified_files('')) 430 431 def test_delimiter(self): 432 """Test method delimiter""" 433 self.assertEqual('\n===\n\n', atest_utils.delimiter('=', 3, 1, 2)) 434 435 def test_has_python_module(self): 436 """Test method has_python_module""" 437 self.assertFalse(atest_utils.has_python_module('M_M')) 438 self.assertTrue(atest_utils.has_python_module('os')) 439 440 @mock.patch.object(atest_utils, 'matched_tf_error_log', return_value=True) 441 def test_read_zip_single_text(self, _matched): 442 """Test method extract_zip_text include only one text file.""" 443 zip_path = os.path.join(unittest_constants.TEST_DATA_DIR, 444 TEST_ZIP_DATA_DIR, TEST_SINGLE_ZIP_NAME) 445 expect_content = '\nfile1_line1\nfile1_line2\n' 446 self.assertEqual(expect_content, atest_utils.extract_zip_text(zip_path)) 447 448 @mock.patch.object(atest_utils, 'matched_tf_error_log', return_value=True) 449 def test_read_zip_multi_text(self, _matched): 450 """Test method extract_zip_text include multiple text files.""" 451 zip_path = os.path.join(unittest_constants.TEST_DATA_DIR, 452 TEST_ZIP_DATA_DIR, TEST_MULTI_ZIP_NAME) 453 expect_content = ('\nfile1_line1\nfile1_line2\n\nfile2_line1\n' 454 'file2_line2\n') 455 self.assertEqual(expect_content, atest_utils.extract_zip_text(zip_path)) 456 457 def test_matched_tf_error_log(self): 458 """Test method extract_zip_text include multiple text files.""" 459 matched_content = '05-25 17:37:04 E/XXXXX YYYYY' 460 not_matched_content = '05-25 17:37:04 I/XXXXX YYYYY' 461 # Test matched content 462 self.assertEqual(True, 463 atest_utils.matched_tf_error_log(matched_content)) 464 # Test not matched content 465 self.assertEqual(False, 466 atest_utils.matched_tf_error_log(not_matched_content)) 467 468 @mock.patch('os.chmod') 469 @mock.patch('shutil.copy2') 470 @mock.patch('atest_utils.has_valid_cert') 471 @mock.patch('subprocess.check_output') 472 @mock.patch('os.path.exists') 473 def test_get_flakes(self, mock_path_exists, mock_output, mock_valid_cert, 474 _cpc, _cm): 475 """Test method get_flakes.""" 476 # Test par file does not exist. 477 mock_path_exists.return_value = False 478 self.assertEqual(None, atest_utils.get_flakes()) 479 # Test par file exists. 480 mock_path_exists.return_value = True 481 mock_output.return_value = (b'flake_percent:0.10001\n' 482 b'postsubmit_flakes_per_week:12.0') 483 mock_valid_cert.return_value = True 484 expected_flake_info = {'flake_percent':'0.10001', 485 'postsubmit_flakes_per_week':'12.0'} 486 self.assertEqual(expected_flake_info, 487 atest_utils.get_flakes()) 488 # Test no valid cert 489 mock_valid_cert.return_value = False 490 self.assertEqual(None, 491 atest_utils.get_flakes()) 492 493 @mock.patch('subprocess.check_call') 494 def test_has_valid_cert(self, mock_call): 495 """Test method has_valid_cert.""" 496 # raise subprocess.CalledProcessError 497 mock_call.raiseError.side_effect = subprocess.CalledProcessError 498 self.assertFalse(atest_utils.has_valid_cert()) 499 with mock.patch("constants.CERT_STATUS_CMD", ''): 500 self.assertFalse(atest_utils.has_valid_cert()) 501 with mock.patch("constants.CERT_STATUS_CMD", 'CMD'): 502 # has valid cert 503 mock_call.return_value = 0 504 self.assertTrue(atest_utils.has_valid_cert()) 505 # no valid cert 506 mock_call.return_value = 4 507 self.assertFalse(atest_utils.has_valid_cert()) 508 509 # pylint: disable=no-member 510 def test_read_test_record_proto(self): 511 """Test method read_test_record.""" 512 test_record_file_path = os.path.join(unittest_constants.TEST_DATA_DIR, 513 "test_record.proto.testonly") 514 test_record = atest_utils.read_test_record(test_record_file_path) 515 self.assertEqual(test_record.children[0].inline_test_record.test_record_id, 516 'x86 hello_world_test') 517 518 def test_is_valid_json_file_file_not_exist(self): 519 """Test method is_valid_json_file if file not exist.""" 520 json_file_path = os.path.join(unittest_constants.TEST_DATA_DIR, 521 "not_exist.json") 522 self.assertFalse(atest_utils.is_valid_json_file(json_file_path)) 523 524 def test_is_valid_json_file_content_valid(self): 525 """Test method is_valid_json_file if file exist and content is valid.""" 526 json_file_path = os.path.join(unittest_constants.TEST_DATA_DIR, 527 "module-info.json") 528 self.assertTrue(atest_utils.is_valid_json_file(json_file_path)) 529 530 def test_is_valid_json_file_content_not_valid(self): 531 """Test method is_valid_json_file if file exist but content is valid.""" 532 json_file_path = os.path.join(unittest_constants.TEST_DATA_DIR, 533 "not-valid-module-info.json") 534 self.assertFalse(atest_utils.is_valid_json_file(json_file_path)) 535 536 @mock.patch('subprocess.check_output') 537 @mock.patch('os.getenv') 538 def test_get_manifest_branch(self, mock_env, mock_check_output): 539 """Test method get_manifest_branch""" 540 mock_env.return_value = 'any_path' 541 mock_check_output.return_value = REPO_INFO_OUTPUT 542 self.assertEqual('test_branch', atest_utils.get_manifest_branch()) 543 544 mock_env.return_value = 'any_path' 545 mock_check_output.return_value = 'not_matched_branch_pattern.' 546 self.assertEqual(None, atest_utils.get_manifest_branch()) 547 548 mock_env.return_value = 'any_path' 549 mock_check_output.side_effect = subprocess.CalledProcessError( 550 1, 551 'repo info') 552 self.assertEqual(None, atest_utils.get_manifest_branch()) 553 554 mock_env.return_value = None 555 mock_check_output.return_value = REPO_INFO_OUTPUT 556 self.assertEqual(None, atest_utils.get_manifest_branch()) 557 558 def test_has_wildcard(self): 559 """Test method of has_wildcard""" 560 self.assertFalse(atest_utils.has_wildcard('test1')) 561 self.assertFalse(atest_utils.has_wildcard(['test1'])) 562 self.assertTrue(atest_utils.has_wildcard('test1?')) 563 self.assertTrue(atest_utils.has_wildcard(['test1', 'b*', 'a?b*'])) 564 565 # pylint: disable=anomalous-backslash-in-string 566 def test_quote(self): 567 """Test method of quote()""" 568 target_str = r'TEST_(F|P)[0-9].*\w$' 569 expected_str = '\'TEST_(F|P)[0-9].*\w$\'' 570 self.assertEqual(atest_utils.quote(target_str), expected_str) 571 self.assertEqual(atest_utils.quote('TEST_P224'), 'TEST_P224') 572 573 @mock.patch('builtins.input', return_value='') 574 def test_prompt_with_yn_result(self, mock_input): 575 """Test method of prompt_with_yn_result""" 576 msg = 'Do you want to continue?' 577 mock_input.return_value = '' 578 self.assertTrue(atest_utils.prompt_with_yn_result(msg, True)) 579 self.assertFalse(atest_utils.prompt_with_yn_result(msg, False)) 580 mock_input.return_value = 'y' 581 self.assertTrue(atest_utils.prompt_with_yn_result(msg, True)) 582 mock_input.return_value = 'nO' 583 self.assertFalse(atest_utils.prompt_with_yn_result(msg, True)) 584 585 def test_get_android_junit_config_filters(self): 586 """Test method of get_android_junit_config_filters""" 587 no_filter_test_config = os.path.join( 588 unittest_constants.TEST_DATA_DIR, 589 "filter_configs", "no_filter.cfg") 590 self.assertEqual({}, 591 atest_utils.get_android_junit_config_filters( 592 no_filter_test_config)) 593 594 filtered_test_config = os.path.join( 595 unittest_constants.TEST_DATA_DIR, 596 'filter_configs', 'filter.cfg') 597 filter_dict = atest_utils.get_android_junit_config_filters( 598 filtered_test_config) 599 include_annotations = filter_dict.get(constants.INCLUDE_ANNOTATION) 600 include_annotations.sort() 601 self.assertEqual( 602 ['include1', 'include2'], 603 include_annotations) 604 exclude_annotation = filter_dict.get(constants.EXCLUDE_ANNOTATION) 605 exclude_annotation.sort() 606 self.assertEqual( 607 ['exclude1', 'exclude2'], 608 exclude_annotation) 609 610 def test_md5sum(self): 611 """Test method of md5sum""" 612 exist_string = os.path.join(unittest_constants.TEST_DATA_DIR, 613 unittest_constants.JSON_FILE) 614 inexist_string = os.path.join(unittest_constants.TEST_DATA_DIR, 615 unittest_constants.CLASS_NAME) 616 self.assertEqual( 617 atest_utils.md5sum(exist_string), 'c26aab9baae99bcfb97633b69e9ceefd') 618 self.assertEqual( 619 atest_utils.md5sum(inexist_string), '') 620 621 def test_check_md5(self): 622 """Test method of check_md5""" 623 file1 = os.path.join(unittest_constants.TEST_DATA_DIR, 624 unittest_constants.JSON_FILE) 625 checksum_file = '/tmp/_tmp_module-info.json' 626 atest_utils.save_md5([file1], '/tmp/_tmp_module-info.json') 627 self.assertTrue(atest_utils.check_md5(checksum_file)) 628 os.remove(checksum_file) 629 self.assertFalse(atest_utils.check_md5(checksum_file)) 630 self.assertTrue(atest_utils.check_md5(checksum_file, missing_ok=True)) 631 632 def test_get_config_parameter(self): 633 """Test method of get_config_parameter""" 634 parameter_config = os.path.join( 635 unittest_constants.TEST_DATA_DIR, 636 "parameter_config", "parameter.cfg") 637 no_parameter_config = os.path.join( 638 unittest_constants.TEST_DATA_DIR, 639 "parameter_config", "no_parameter.cfg") 640 641 # Test parameter empty value 642 self.assertEqual(set(), 643 atest_utils.get_config_parameter( 644 no_parameter_config)) 645 646 # Test parameter empty value 647 self.assertEqual({'value_1', 'value_2', 'value_3', 'value_4'}, 648 atest_utils.get_config_parameter( 649 parameter_config)) 650 651if __name__ == "__main__": 652 unittest.main() 653