• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2017, 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 cli_translator."""
18
19# pylint: disable=line-too-long
20
21import unittest
22import json
23import os
24import re
25import sys
26import tempfile
27
28from importlib import reload
29from io import StringIO
30from unittest import mock
31
32from atest import atest_arg_parser
33from atest import atest_utils
34from atest import cli_translator as cli_t
35from atest import constants
36from atest import module_info
37from atest import test_finder_handler
38from atest import test_mapping
39from atest import unittest_constants as uc
40from atest import unittest_utils
41
42from atest.metrics import metrics
43from atest.test_finders import module_finder
44from atest.test_finders import test_finder_base
45from atest.test_finders import test_finder_utils
46
47
48# TEST_MAPPING related consts
49TEST_MAPPING_TOP_DIR = os.path.join(uc.TEST_DATA_DIR, 'test_mapping')
50TEST_MAPPING_DIR = os.path.join(TEST_MAPPING_TOP_DIR, 'folder1')
51TEST_1 = test_mapping.TestDetail({'name': 'test1', 'host': True})
52TEST_2 = test_mapping.TestDetail({'name': 'test2'})
53TEST_3 = test_mapping.TestDetail({'name': 'test3'})
54TEST_4 = test_mapping.TestDetail({'name': 'test4'})
55TEST_5 = test_mapping.TestDetail({'name': 'test5'})
56TEST_6 = test_mapping.TestDetail({'name': 'test6'})
57TEST_7 = test_mapping.TestDetail({'name': 'test7'})
58TEST_8 = test_mapping.TestDetail({'name': 'test8'})
59TEST_9 = test_mapping.TestDetail({'name': 'test9'})
60TEST_10 = test_mapping.TestDetail({'name': 'test10'})
61
62SEARCH_DIR_RE = re.compile(r'^find ([^ ]*).*$')
63BUILD_TOP_DIR = tempfile.TemporaryDirectory().name
64PRODUCT_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/target/product/vsoc_x86_64')
65HOST_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/host/linux-x86')
66
67#pylint: disable=unused-argument
68def gettestinfos_side_effect(test_names, test_mapping_test_details=None,
69                             is_rebuild_module_info=False):
70    """Mock return values for _get_test_info."""
71    test_infos = set()
72    for test_name in test_names:
73        if test_name == uc.MODULE_NAME:
74            test_infos.add(uc.MODULE_INFO)
75        if test_name == uc.CLASS_NAME:
76            test_infos.add(uc.CLASS_INFO)
77        if test_name == uc.HOST_UNIT_TEST_NAME_1:
78            test_infos.add(uc.MODULE_INFO_HOST_1)
79        if test_name == uc.HOST_UNIT_TEST_NAME_2:
80            test_infos.add(uc.MODULE_INFO_HOST_2)
81    return test_infos
82
83
84#pylint: disable=protected-access
85class CLITranslatorUnittests(unittest.TestCase):
86    """Unit tests for cli_t.py"""
87
88    def setUp(self):
89        """Run before execution of every test"""
90        self.ctr = cli_t.CLITranslator()
91
92        # Create a mock of args.
93        parser = atest_arg_parser.AtestArgParser()
94        parser.add_atest_args()
95        self.args = parser.parse_args()
96        self.args.tests = []
97        # Test mapping related args
98        self.args.test_mapping = False
99        self.args.include_subdirs = False
100        self.args.enable_file_patterns = False
101        self.args.rebuild_module_info = False
102        # Cache finder related args
103        self.args.clear_cache = False
104        self.ctr.mod_info = mock.Mock
105        self.ctr.mod_info.name_to_module_info = {}
106
107    def tearDown(self):
108        """Run after execution of every test"""
109        reload(uc)
110
111    @mock.patch.object(atest_utils, 'update_test_info_cache')
112    @mock.patch('builtins.input', return_value='n')
113    @mock.patch.object(module_finder.ModuleFinder, 'find_test_by_module_name')
114    @mock.patch.object(module_finder.ModuleFinder, 'get_fuzzy_searching_results')
115    @mock.patch.object(metrics, 'FindTestFinishEvent')
116    @mock.patch.object(test_finder_handler, 'get_find_methods_for_test')
117    # pylint: disable=too-many-locals
118    def test_get_test_infos(self, mock_getfindmethods, _metrics,
119                            mock_getfuzzyresults, mock_findtestbymodule,
120                            mock_input, _mock_update_test_info):
121        """Test _get_test_infos method."""
122        ctr = cli_t.CLITranslator()
123        find_method_return_module_info = lambda x, y: uc.MODULE_INFOS
124        # pylint: disable=invalid-name
125        find_method_return_module_class_info = (lambda x, test: uc.MODULE_INFOS
126                                                if test == uc.MODULE_NAME
127                                                else uc.CLASS_INFOS)
128        find_method_return_nothing = lambda x, y: None
129        one_test = [uc.MODULE_NAME]
130        mult_test = [uc.MODULE_NAME, uc.CLASS_NAME]
131
132        # Let's make sure we return what we expect.
133        expected_test_infos = {uc.MODULE_INFO}
134        mock_getfindmethods.return_value = [
135            test_finder_base.Finder(None, find_method_return_module_info, None)]
136        unittest_utils.assert_strict_equal(
137            self, ctr._get_test_infos(one_test), expected_test_infos)
138
139        # Check we receive multiple test infos.
140        expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO}
141        mock_getfindmethods.return_value = [
142            test_finder_base.Finder(None, find_method_return_module_class_info,
143                                    None)]
144        unittest_utils.assert_strict_equal(
145            self, ctr._get_test_infos(mult_test), expected_test_infos)
146
147        # Check return null set when we have no tests found or multiple results.
148        mock_getfindmethods.return_value = [
149            test_finder_base.Finder(None, find_method_return_nothing, None)]
150        null_test_info = set()
151        mock_getfuzzyresults.return_value = []
152        self.assertEqual(null_test_info, ctr._get_test_infos(one_test))
153        self.assertEqual(null_test_info, ctr._get_test_infos(mult_test))
154
155        # Check returning test_info when the user says Yes.
156        mock_input.return_value = "Y"
157        mock_getfindmethods.return_value = [
158            test_finder_base.Finder(None, find_method_return_module_info, None)]
159        mock_getfuzzyresults.return_value = one_test
160        mock_findtestbymodule.return_value = uc.MODULE_INFO
161        unittest_utils.assert_strict_equal(
162            self, ctr._get_test_infos([uc.TYPO_MODULE_NAME]), {uc.MODULE_INFO})
163
164        # Check the method works for test mapping.
165        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
166        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
167        expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO}
168        mock_getfindmethods.return_value = [
169            test_finder_base.Finder(None, find_method_return_module_class_info,
170                                    None)]
171        test_infos = ctr._get_test_infos(
172            mult_test, [test_detail1, test_detail2])
173        unittest_utils.assert_strict_equal(
174            self, test_infos, expected_test_infos)
175        for test_info in test_infos:
176            if test_info == uc.MODULE_INFO:
177                self.assertEqual(
178                    test_detail1.options,
179                    test_info.data[constants.TI_MODULE_ARG])
180            else:
181                self.assertEqual(
182                    test_detail2.options,
183                    test_info.data[constants.TI_MODULE_ARG])
184
185    @mock.patch.object(atest_utils, 'update_test_info_cache')
186    @mock.patch.object(metrics, 'FindTestFinishEvent')
187    @mock.patch.object(test_finder_handler, 'get_find_methods_for_test')
188    def test_get_test_infos_2(self, mock_getfindmethods, _metrics,
189        _mock_update_test_info):
190        """Test _get_test_infos method."""
191        ctr = cli_t.CLITranslator()
192        find_method_return_module_info2 = lambda x, y: uc.MODULE_INFOS2
193        find_method_ret_mod_cls_info2 = (
194            lambda x, test: uc.MODULE_INFOS2
195            if test == uc.MODULE_NAME else uc.CLASS_INFOS2)
196        one_test = [uc.MODULE_NAME]
197        mult_test = [uc.MODULE_NAME, uc.CLASS_NAME]
198        # Let's make sure we return what we expect.
199        expected_test_infos = {uc.MODULE_INFO, uc.MODULE_INFO2}
200        mock_getfindmethods.return_value = [
201            test_finder_base.Finder(None, find_method_return_module_info2,
202                                    None)]
203        unittest_utils.assert_strict_equal(
204            self, ctr._get_test_infos(one_test), expected_test_infos)
205        # Check we receive multiple test infos.
206        expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO, uc.MODULE_INFO2,
207                               uc.CLASS_INFO2}
208        mock_getfindmethods.return_value = [
209            test_finder_base.Finder(None, find_method_ret_mod_cls_info2,
210                                    None)]
211        unittest_utils.assert_strict_equal(
212            self, ctr._get_test_infos(mult_test), expected_test_infos)
213        # Check the method works for test mapping.
214        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
215        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
216        expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO, uc.MODULE_INFO2,
217                               uc.CLASS_INFO2}
218        mock_getfindmethods.return_value = [
219            test_finder_base.Finder(None, find_method_ret_mod_cls_info2,
220                                    None)]
221        test_infos = ctr._get_test_infos(
222            mult_test, [test_detail1, test_detail2])
223        unittest_utils.assert_strict_equal(
224            self, test_infos, expected_test_infos)
225        for test_info in test_infos:
226            if test_info in [uc.MODULE_INFO, uc.MODULE_INFO2]:
227                self.assertEqual(
228                    test_detail1.options,
229                    test_info.data[constants.TI_MODULE_ARG])
230            elif test_info in [uc.CLASS_INFO, uc.CLASS_INFO2]:
231                self.assertEqual(
232                    test_detail2.options,
233                    test_info.data[constants.TI_MODULE_ARG])
234
235    @mock.patch.object(module_finder.ModuleFinder, 'get_fuzzy_searching_results')
236    @mock.patch.object(metrics, 'FindTestFinishEvent')
237    @mock.patch.object(test_finder_handler, 'get_find_methods_for_test')
238    def test_get_test_infos_with_mod_info(
239            self, mock_getfindmethods, _metrics, mock_getfuzzyresults,):
240        """Test _get_test_infos method."""
241        mod_info = module_info.ModuleInfo(
242            module_file=os.path.join(uc.TEST_DATA_DIR, uc.JSON_FILE),
243            index_dir=HOST_OUT_DIR)
244        ctr = cli_t.CLITranslator(mod_info=mod_info)
245        null_test_info = set()
246        mock_getfindmethods.return_value = []
247        mock_getfuzzyresults.return_value = []
248        unittest_utils.assert_strict_equal(
249            self, ctr._get_test_infos('not_exist_module'), null_test_info)
250
251    @mock.patch.object(test_finder_utils, 'find_host_unit_tests',
252                       return_value=set())
253    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test')
254    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
255                       side_effect=gettestinfos_side_effect)
256    def test_translate_class(self, _info, host_unit_tests, _find):
257        """Test translate method for tests by class name."""
258        # Check that we can find a class.
259        host_unit_tests.return_value = False
260        self.args.tests = [uc.CLASS_NAME]
261        self.args.host_unit_test_only = False
262        test_infos = self.ctr.translate(self.args)
263        unittest_utils.assert_strict_equal(
264            self,
265            _gather_build_targets(test_infos),
266            uc.CLASS_BUILD_TARGETS)
267        unittest_utils.assert_strict_equal(self, test_infos, {uc.CLASS_INFO})
268
269    @mock.patch.object(test_finder_utils, 'find_host_unit_tests',
270                       return_value=set())
271    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test')
272    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
273                       side_effect=gettestinfos_side_effect)
274    def test_translate_module(self, _info, host_unit_tests, _find):
275        """Test translate method for tests by module or class name."""
276        # Check that we get all the build targets we expect.
277        host_unit_tests.return_value = []
278        self.args.tests = [uc.MODULE_NAME, uc.CLASS_NAME]
279        self.args.host_unit_test_only = False
280        test_infos = self.ctr.translate(self.args)
281        unittest_utils.assert_strict_equal(
282            self,
283            _gather_build_targets(test_infos),
284            uc.MODULE_CLASS_COMBINED_BUILD_TARGETS)
285        unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO,
286                                                              uc.CLASS_INFO})
287
288    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test')
289    @mock.patch.object(test_finder_utils, 'find_host_unit_tests', return_value=[])
290    @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping')
291    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
292                       side_effect=gettestinfos_side_effect)
293    def test_translate_test_mapping(self, _info, mock_testmapping,
294        _find_unit_tests, host_unit_tests):
295        """Test translate method for tests in test mapping."""
296        # Check that test mappings feeds into get_test_info properly.
297        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
298        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
299        mock_testmapping.return_value = ([test_detail1, test_detail2], None)
300        self.args.tests = []
301        self.args.host = False
302        self.args.host_unit_test_only = False
303        host_unit_tests.return_value = False
304        test_infos = self.ctr.translate(self.args)
305        unittest_utils.assert_strict_equal(
306            self,
307            _gather_build_targets(test_infos),
308            uc.MODULE_CLASS_COMBINED_BUILD_TARGETS)
309        unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO,
310                                                              uc.CLASS_INFO})
311
312    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test')
313    @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping')
314    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
315                       side_effect=gettestinfos_side_effect)
316    def test_translate_test_mapping_all(self, _info, mock_testmapping, host_unit_tests):
317        """Test translate method for tests in test mapping."""
318        # Check that test mappings feeds into get_test_info properly.
319        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
320        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
321        mock_testmapping.return_value = ([test_detail1, test_detail2], None)
322        self.args.tests = ['src_path:all']
323        self.args.test_mapping = True
324        self.args.host = False
325        host_unit_tests.return_value = False
326        test_infos = self.ctr.translate(self.args)
327        unittest_utils.assert_strict_equal(
328            self,
329            _gather_build_targets(test_infos),
330            uc.MODULE_CLASS_COMBINED_BUILD_TARGETS)
331        unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO,
332                                                              uc.CLASS_INFO})
333
334    def test_find_tests_by_test_mapping_presubmit(self):
335        """Test _find_tests_by_test_mapping method to locate presubmit tests."""
336        # TODO: (b/264015241) Stop mocking build variables.
337        os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR}
338        with mock.patch.dict('os.environ', os_environ_mock, clear=True):
339            tests, all_tests = self.ctr._find_tests_by_test_mapping(
340                path=TEST_MAPPING_DIR, file_name='test_mapping_sample',
341                checked_files=set())
342        expected = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9])
343        expected_all_tests = {'presubmit': expected,
344                              'postsubmit': set(
345                                  [TEST_3, TEST_6, TEST_8, TEST_10]),
346                              'other_group': set([TEST_4])}
347        self.assertEqual(expected, tests)
348        self.assertEqual(expected_all_tests, all_tests)
349
350    def test_find_tests_by_test_mapping_postsubmit(self):
351        """Test _find_tests_by_test_mapping method to locate postsubmit tests.
352        """
353        # TODO: (b/264015241) Stop mocking build variables.
354        os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR}
355        with mock.patch.dict('os.environ', os_environ_mock, clear=True):
356            tests, all_tests = self.ctr._find_tests_by_test_mapping(
357                path=TEST_MAPPING_DIR,
358                test_groups=[constants.TEST_GROUP_POSTSUBMIT],
359                file_name='test_mapping_sample', checked_files=set())
360        expected_presubmit = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9])
361        expected = set([TEST_3, TEST_6, TEST_8, TEST_10])
362        expected_all_tests = {'presubmit': expected_presubmit,
363                              'postsubmit': set(
364                                  [TEST_3, TEST_6, TEST_8, TEST_10]),
365                              'other_group': set([TEST_4])}
366        self.assertEqual(expected, tests)
367        self.assertEqual(expected_all_tests, all_tests)
368
369    def test_find_tests_by_test_mapping_all_group(self):
370        """Test _find_tests_by_test_mapping method to locate postsubmit tests.
371        """
372        # TODO: (b/264015241) Stop mocking build variables.
373        os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR}
374        with mock.patch.dict('os.environ', os_environ_mock, clear=True):
375            tests, all_tests = self.ctr._find_tests_by_test_mapping(
376                path=TEST_MAPPING_DIR, test_groups=[constants.TEST_GROUP_ALL],
377                file_name='test_mapping_sample', checked_files=set())
378        expected_presubmit = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9])
379        expected = set([
380            TEST_1, TEST_2, TEST_3, TEST_4, TEST_5, TEST_6, TEST_7, TEST_8,
381            TEST_9, TEST_10])
382        expected_all_tests = {'presubmit': expected_presubmit,
383                              'postsubmit': set(
384                                  [TEST_3, TEST_6, TEST_8, TEST_10]),
385                              'other_group': set([TEST_4])}
386        self.assertEqual(expected, tests)
387        self.assertEqual(expected_all_tests, all_tests)
388
389    def test_find_tests_by_test_mapping_include_subdir(self):
390        """Test _find_tests_by_test_mapping method to include sub directory."""
391        # TODO: (b/264015241) Stop mocking build variables.
392        os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR}
393        with mock.patch.dict('os.environ', os_environ_mock, clear=True):
394            tests, all_tests = self.ctr._find_tests_by_test_mapping(
395                path=TEST_MAPPING_TOP_DIR, file_name='test_mapping_sample',
396                include_subdirs=True, checked_files=set())
397        expected = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9])
398        expected_all_tests = {'presubmit': expected,
399                              'postsubmit': set([
400                                  TEST_3, TEST_6, TEST_8, TEST_10]),
401                              'other_group': set([TEST_4])}
402        self.assertEqual(expected, tests)
403        self.assertEqual(expected_all_tests, all_tests)
404
405    @mock.patch('builtins.input', return_value='')
406    def test_confirm_running(self, mock_input):
407        """Test _confirm_running method."""
408        self.assertTrue(self.ctr._confirm_running([TEST_1]))
409        mock_input.return_value = 'N'
410        self.assertFalse(self.ctr._confirm_running([TEST_2]))
411
412    def test_print_fuzzy_searching_results(self):
413        """Test _print_fuzzy_searching_results"""
414        modules = [uc.MODULE_NAME, uc.MODULE2_NAME]
415        capture_output = StringIO()
416        sys.stdout = capture_output
417        self.ctr._print_fuzzy_searching_results(modules)
418        sys.stdout = sys.__stdout__
419        output = 'Did you mean the following modules?\n{0}\n{1}\n'.format(
420            uc.MODULE_NAME, uc.MODULE2_NAME)
421        self.assertEqual(capture_output.getvalue(), output)
422
423    def test_filter_comments(self):
424        """Test filter_comments method"""
425        file_with_comments = os.path.join(TEST_MAPPING_TOP_DIR,
426                                          'folder6',
427                                          'test_mapping_sample_with_comments')
428        file_with_comments_golden = os.path.join(TEST_MAPPING_TOP_DIR,
429                                                 'folder6',
430                                                 'test_mapping_sample_golden')
431        test_mapping_dict = json.loads(
432            self.ctr.filter_comments(file_with_comments))
433        test_mapping_dict_gloden = None
434        with open(file_with_comments_golden) as json_file:
435            test_mapping_dict_gloden = json.load(json_file)
436
437        self.assertEqual(test_mapping_dict, test_mapping_dict_gloden)
438
439    @mock.patch.object(module_info.ModuleInfo, 'get_testable_modules')
440    def test_extract_testable_modules_by_wildcard(self, mock_mods):
441        """Test _extract_testable_modules_by_wildcard method."""
442        mod_info = module_info.ModuleInfo(
443            module_file=os.path.join(uc.TEST_DATA_DIR, uc.JSON_FILE),
444            index_dir=HOST_OUT_DIR)
445        ctr = cli_t.CLITranslator(mod_info=mod_info)
446        mock_mods.return_value = ['test1', 'test2', 'test3', 'test11',
447                                  'Test22', 'Test100', 'aTest101']
448        # test '*'
449        expr1 = ['test*']
450        result1 = ['test1', 'test2', 'test3', 'test11']
451        self.assertEqual(ctr._extract_testable_modules_by_wildcard(expr1),
452                         result1)
453        # test '?'
454        expr2 = ['test?']
455        result2 = ['test1', 'test2', 'test3']
456        self.assertEqual(ctr._extract_testable_modules_by_wildcard(expr2),
457                         result2)
458        # test '*' and '?'
459        expr3 = ['*Test???']
460        result3 = ['Test100', 'aTest101']
461        self.assertEqual(ctr._extract_testable_modules_by_wildcard(expr3),
462                         result3)
463
464    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test',
465                       return_value=True)
466    @mock.patch.object(test_finder_utils, 'find_host_unit_tests',
467                       return_value=[uc.HOST_UNIT_TEST_NAME_1,
468                                     uc.HOST_UNIT_TEST_NAME_2])
469    @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping')
470    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
471                       side_effect=gettestinfos_side_effect)
472    def test_translate_test_mapping_host_unit_test(
473        self, _info, mock_testmapping, _find_unit_tests, _has_host_unit_test):
474        """Test translate method for tests belong to host unit tests."""
475        # Check that test mappings feeds into get_test_info properly.
476        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
477        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
478        mock_testmapping.return_value = ([test_detail1, test_detail2], None)
479        self.args.tests = []
480        self.args.host = False
481        self.args.host_unit_test_only = False
482        test_infos = self.ctr.translate(self.args)
483        unittest_utils.assert_strict_equal(self,
484                                           test_infos,
485                                           {uc.MODULE_INFO,
486                                            uc.CLASS_INFO,
487                                            uc.MODULE_INFO_HOST_1,
488                                            uc.MODULE_INFO_HOST_2})
489
490    @mock.patch.object(cli_t.CLITranslator, '_has_host_unit_test',
491                       return_value=True)
492    @mock.patch.object(test_finder_utils, 'find_host_unit_tests',
493                       return_value=[uc.HOST_UNIT_TEST_NAME_1,
494                                     uc.HOST_UNIT_TEST_NAME_2])
495    @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping')
496    @mock.patch.object(cli_t.CLITranslator, '_get_test_infos',
497                       side_effect=gettestinfos_side_effect)
498    def test_translate_test_mapping_without_host_unit_test(
499        self, _info, mock_testmapping, _find_unit_tests, _has_host_unit_test):
500        """Test translate method not using host unit tests if test_mapping arg .
501        """
502        # Check that test mappings feeds into get_test_info properly.
503        test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST)
504        test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION)
505        mock_testmapping.return_value = ([test_detail1, test_detail2], None)
506        self.args.tests = []
507        self.args.host = False
508        self.args.test_mapping = True
509        self.args.host_unit_test_only = False
510        test_infos = self.ctr.translate(self.args)
511        unittest_utils.assert_strict_equal(
512            self,
513            test_infos,
514            {uc.MODULE_INFO, uc.CLASS_INFO})
515
516
517class ParseTestIdentifierTest(unittest.TestCase):
518    """Test parse_test_identifier with different test names."""
519
520    def test_no_mainline_modules(self):
521        """non-mainline module testing."""
522        given = 'testName'
523
524        identifier = cli_t.parse_test_identifier(given)
525
526        self.assertEqual('testName', identifier.test_name)
527        self.assertEqual([], identifier.module_names)
528        self.assertEqual([], identifier.binary_names)
529
530    def test_single_mainline_module(self):
531        """only one mainline module."""
532        given = 'testName[Module1.apk]'
533
534        identifier = cli_t.parse_test_identifier(given)
535
536        self.assertEqual('testName', identifier.test_name)
537        self.assertEqual(['Module1'], identifier.module_names)
538        self.assertEqual(['Module1.apk'], identifier.binary_names)
539
540    def test_multiple_mainline_modules(self):
541        """multiple mainline modules."""
542        given = 'testName[Module1.apk+Module2.apex]'
543
544        identifier = cli_t.parse_test_identifier(given)
545
546        self.assertEqual('testName', identifier.test_name)
547        self.assertEqual(
548            ['Module1', 'Module2'], identifier.module_names)
549        self.assertEqual(
550            ['Module1.apk', 'Module2.apex'], identifier.binary_names)
551
552    def test_missing_closing_bracket(self):
553        """test the brackets are not in pair"""
554        given = 'testName[Module1.apk+Module2.apex'
555
556        identifier = cli_t.parse_test_identifier(given)
557
558        self.assertEqual(given, identifier.test_name)
559        self.assertEqual([], identifier.module_names)
560        self.assertEqual([], identifier.binary_names)
561
562if __name__ == '__main__':
563    unittest.main()
564
565
566def _gather_build_targets(test_infos):
567    targets = set()
568    for t_info in test_infos:
569        targets |= t_info.build_targets
570    return targets
571