• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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