1#!/usr/bin/env python
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 module_finder."""
18
19import re
20import unittest
21import os
22import mock
23
24# pylint: disable=import-error
25import atest_error
26import constants
27import module_info
28import unittest_constants as uc
29import unittest_utils
30from test_finders import module_finder
31from test_finders import test_finder_utils
32from test_finders import test_info
33from test_runners import atest_tf_test_runner as atf_tr
34
35MODULE_CLASS = '%s:%s' % (uc.MODULE_NAME, uc.CLASS_NAME)
36MODULE_PACKAGE = '%s:%s' % (uc.MODULE_NAME, uc.PACKAGE)
37FLAT_METHOD_INFO = test_info.TestInfo(
38    uc.MODULE_NAME,
39    atf_tr.AtestTradefedTestRunner.NAME,
40    uc.MODULE_BUILD_TARGETS,
41    data={constants.TI_FILTER: frozenset([uc.FLAT_METHOD_FILTER]),
42          constants.TI_REL_CONFIG: uc.CONFIG_FILE})
43MODULE_CLASS_METHOD = '%s#%s' % (MODULE_CLASS, uc.METHOD_NAME)
44CLASS_INFO_MODULE_2 = test_info.TestInfo(
45    uc.MODULE2_NAME,
46    atf_tr.AtestTradefedTestRunner.NAME,
47    uc.CLASS_BUILD_TARGETS,
48    data={constants.TI_FILTER: frozenset([uc.CLASS_FILTER]),
49          constants.TI_REL_CONFIG: uc.CONFIG2_FILE})
50DEFAULT_INSTALL_PATH = ['/path/to/install']
51ROBO_MOD_PATH = ['/shared/robo/path']
52NON_RUN_ROBO_MOD_NAME = 'robo_mod'
53RUN_ROBO_MOD_NAME = 'run_robo_mod'
54NON_RUN_ROBO_MOD = {constants.MODULE_NAME: NON_RUN_ROBO_MOD_NAME,
55                    constants.MODULE_PATH: ROBO_MOD_PATH,
56                    constants.MODULE_CLASS: ['random_class']}
57RUN_ROBO_MOD = {constants.MODULE_NAME: RUN_ROBO_MOD_NAME,
58                constants.MODULE_PATH: ROBO_MOD_PATH,
59                constants.MODULE_CLASS: [constants.MODULE_CLASS_ROBOLECTRIC]}
60
61
62SEARCH_DIR_RE = re.compile(r'^find ([^ ]*).*$')
63
64def get_mod_info_side_effect(mod):
65    """Mock out get_module_info for ModuleInfo."""
66    mod_info_dict = {
67        RUN_ROBO_MOD_NAME: RUN_ROBO_MOD,
68        NON_RUN_ROBO_MOD_NAME: NON_RUN_ROBO_MOD}
69    return mod_info_dict.get(mod)
70
71
72#pylint: disable=unused-argument
73def classoutside_side_effect(find_cmd, shell=False):
74    """Mock the check output of a find cmd where class outside module path."""
75    search_dir = SEARCH_DIR_RE.match(find_cmd).group(1).strip()
76    if search_dir == uc.ROOT:
77        return uc.FIND_ONE
78    return None
79
80
81#pylint: disable=protected-access
82class ModuleFinderUnittests(unittest.TestCase):
83    """Unit tests for module_finder.py"""
84
85    def setUp(self):
86        """Set up stuff for testing."""
87        self.mod_finder = module_finder.ModuleFinder()
88        self.mod_finder.module_info = mock.Mock(spec=module_info.ModuleInfo)
89        self.mod_finder.module_info.path_to_module_info = {}
90        self.mod_finder.root_dir = uc.ROOT
91
92    def test_is_vts_module(self):
93        """Test _load_module_info_file regular operation."""
94        mod_name = 'mod'
95        is_vts_module_info = {'compatibility_suites': ['vts', 'tests']}
96        self.mod_finder.module_info.get_module_info.return_value = is_vts_module_info
97        self.assertTrue(self.mod_finder._is_vts_module(mod_name))
98
99        is_not_vts_module = {'compatibility_suites': ['vts', 'cts']}
100        self.mod_finder.module_info.get_module_info.return_value = is_not_vts_module
101        self.assertFalse(self.mod_finder._is_vts_module(mod_name))
102
103    def test_is_auto_gen_test_config(self):
104        """Test _is_auto_gen_test_config correctly detects the module."""
105        mod_name = 'mod'
106        self.mod_finder.module_info.is_module.return_value = True
107        is_auto_test_config = {'auto_test_config': [True]}
108        is_not_auto_test_config = {'auto_test_config': [False]}
109        is_not_auto_test_config_again = {'auto_test_config': []}
110
111        self.mod_finder.module_info.get_module_info.return_value = is_auto_test_config
112        self.assertTrue(self.mod_finder._is_auto_gen_test_config(mod_name))
113        self.mod_finder.module_info.get_module_info.return_value = is_not_auto_test_config
114        self.assertFalse(self.mod_finder._is_auto_gen_test_config(mod_name))
115        self.mod_finder.module_info.get_module_info.return_value = is_not_auto_test_config_again
116        self.assertFalse(self.mod_finder._is_auto_gen_test_config(mod_name))
117        self.mod_finder.module_info.get_module_info.return_value = {}
118        self.assertFalse(self.mod_finder._is_auto_gen_test_config(mod_name))
119
120    # pylint: disable=unused-argument
121    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
122                       return_value=True)
123    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets',
124                       return_value=uc.MODULE_BUILD_TARGETS)
125    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
126                       return_value=False)
127    def test_find_test_by_module_name(self, _robo, _get_targ, _has_test_config):
128        """Test find_test_by_module_name."""
129        mod_info = {'installed': ['/path/to/install'],
130                    'path': [uc.MODULE_DIR]}
131        self.mod_finder.module_info.get_module_info.return_value = mod_info
132        unittest_utils.assert_equal_testinfos(
133            self,
134            self.mod_finder.find_test_by_module_name(uc.MODULE_NAME),
135            uc.MODULE_INFO)
136        self.mod_finder.module_info.get_module_info.return_value = None
137        self.assertIsNone(self.mod_finder.find_test_by_module_name('Not_Module'))
138
139    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
140                       return_value=True)
141    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
142                       return_value=False)
143    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
144                       return_value=False)
145    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets')
146    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config',
147                       return_value=False)
148    @mock.patch('subprocess.check_output', return_value=uc.FIND_ONE)
149    @mock.patch.object(test_finder_utils, 'get_fully_qualified_class_name',
150                       return_value=uc.FULL_CLASS_NAME)
151    @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect)
152    @mock.patch('os.path.isdir', return_value=True)
153    #pylint: disable=unused-argument
154    def test_find_test_by_class_name(self, _isdir, _isfile, _fqcn,
155                                     mock_checkoutput, _auto, mock_build, _robo,
156                                     _vts, _has_test_config):
157        """Test find_test_by_class_name."""
158        mock_build.return_value = uc.CLASS_BUILD_TARGETS
159        self.mod_finder.module_info.get_module_names.return_value = [uc.MODULE_NAME]
160        self.mod_finder.module_info.get_module_info.return_value = {
161            constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
162            constants.MODULE_NAME: uc.MODULE_NAME}
163        unittest_utils.assert_equal_testinfos(
164            self, self.mod_finder.find_test_by_class_name(uc.CLASS_NAME), uc.CLASS_INFO)
165
166        # with method
167        mock_build.return_value = uc.MODULE_BUILD_TARGETS
168        class_with_method = '%s#%s' % (uc.CLASS_NAME, uc.METHOD_NAME)
169        unittest_utils.assert_equal_testinfos(
170            self,
171            self.mod_finder.find_test_by_class_name(class_with_method),
172            uc.METHOD_INFO)
173        mock_build.return_value = uc.MODULE_BUILD_TARGETS
174        class_methods = '%s,%s' % (class_with_method, uc.METHOD2_NAME)
175        unittest_utils.assert_equal_testinfos(
176            self, self.mod_finder.find_test_by_class_name(class_methods),
177            FLAT_METHOD_INFO)
178        # module and rel_config passed in
179        mock_build.return_value = uc.CLASS_BUILD_TARGETS
180        unittest_utils.assert_equal_testinfos(
181            self, self.mod_finder.find_test_by_class_name(
182                uc.CLASS_NAME, uc.MODULE_NAME, uc.CONFIG_FILE), uc.CLASS_INFO)
183        # find output fails to find class file
184        mock_checkoutput.return_value = ''
185        self.assertIsNone(self.mod_finder.find_test_by_class_name('Not class'))
186        # class is outside given module path
187        mock_checkoutput.side_effect = classoutside_side_effect
188        unittest_utils.assert_equal_testinfos(
189            self, self.mod_finder.find_test_by_class_name(uc.CLASS_NAME,
190                                                          uc.MODULE2_NAME,
191                                                          uc.CONFIG2_FILE),
192            CLASS_INFO_MODULE_2)
193
194    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
195                       return_value=True)
196    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
197                       return_value=False)
198    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
199                       return_value=False)
200    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets')
201    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config',
202                       return_value=False)
203    @mock.patch('subprocess.check_output', return_value=uc.FIND_ONE)
204    @mock.patch.object(test_finder_utils, 'get_fully_qualified_class_name',
205                       return_value=uc.FULL_CLASS_NAME)
206    @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect)
207    #pylint: disable=unused-argument
208    def test_find_test_by_module_and_class(self, _isfile, _fqcn,
209                                           mock_checkoutput, _auto, mock_build,
210                                           _robo, _vts, _has_test_config):
211        """Test find_test_by_module_and_class."""
212        mock_build.return_value = uc.CLASS_BUILD_TARGETS
213        mod_info = {constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
214                    constants.MODULE_PATH: [uc.MODULE_DIR]}
215        self.mod_finder.module_info.get_module_info.return_value = mod_info
216        t_info = self.mod_finder.find_test_by_module_and_class(MODULE_CLASS)
217        unittest_utils.assert_equal_testinfos(self, t_info, uc.CLASS_INFO)
218        # with method
219        mock_build.return_value = uc.MODULE_BUILD_TARGETS
220        t_info = self.mod_finder.find_test_by_module_and_class(MODULE_CLASS_METHOD)
221        unittest_utils.assert_equal_testinfos(self, t_info, uc.METHOD_INFO)
222        # bad module, good class, returns None
223        bad_module = '%s:%s' % ('BadMod', uc.CLASS_NAME)
224        self.mod_finder.module_info.get_module_info.return_value = None
225        self.assertIsNone(self.mod_finder.find_test_by_module_and_class(bad_module))
226        # find output fails to find class file
227        mock_checkoutput.return_value = ''
228        bad_class = '%s:%s' % (uc.MODULE_NAME, 'Anything')
229        self.mod_finder.module_info.get_module_info.return_value = mod_info
230        self.assertIsNone(self.mod_finder.find_test_by_module_and_class(bad_class))
231
232    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
233                       return_value=True)
234    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
235                       return_value=False)
236    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
237                       return_value=False)
238    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets')
239    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config',
240                       return_value=False)
241    @mock.patch('subprocess.check_output', return_value=uc.FIND_PKG)
242    @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect)
243    @mock.patch('os.path.isdir', return_value=True)
244    #pylint: disable=unused-argument
245    def test_find_test_by_package_name(self, _isdir, _isfile, mock_checkoutput,
246                                       _auto, mock_build, _robo, _vts, _has_test_config):
247        """Test find_test_by_package_name."""
248        mock_build.return_value = uc.CLASS_BUILD_TARGETS
249        self.mod_finder.module_info.get_module_names.return_value = [uc.MODULE_NAME]
250        self.mod_finder.module_info.get_module_info.return_value = {
251            constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
252            constants.MODULE_NAME: uc.MODULE_NAME}
253        unittest_utils.assert_equal_testinfos(
254            self, self.mod_finder.find_test_by_package_name(uc.PACKAGE),
255            uc.PACKAGE_INFO)
256        # with method, should raise
257        pkg_with_method = '%s#%s' % (uc.PACKAGE, uc.METHOD_NAME)
258        self.assertRaises(atest_error.MethodWithoutClassError,
259                          self.mod_finder.find_test_by_package_name,
260                          pkg_with_method)
261        # module and rel_config passed in
262        unittest_utils.assert_equal_testinfos(
263            self, self.mod_finder.find_test_by_package_name(
264                uc.PACKAGE, uc.MODULE_NAME, uc.CONFIG_FILE), uc.PACKAGE_INFO)
265        # find output fails to find class file
266        mock_checkoutput.return_value = ''
267        self.assertIsNone(self.mod_finder.find_test_by_package_name('Not pkg'))
268
269    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
270                       return_value=True)
271    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
272                       return_value=False)
273    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
274                       return_value=False)
275    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets')
276    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config',
277                       return_value=False)
278    @mock.patch('subprocess.check_output', return_value=uc.FIND_PKG)
279    @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect)
280    #pylint: disable=unused-argument
281    def test_find_test_by_module_and_package(self, _isfile, mock_checkoutput,
282                                             _auto, mock_build, _robo, _vts, _has_test_config):
283        """Test find_test_by_module_and_package."""
284        mock_build.return_value = uc.CLASS_BUILD_TARGETS
285        mod_info = {constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
286                    constants.MODULE_PATH: [uc.MODULE_DIR]}
287        self.mod_finder.module_info.get_module_info.return_value = mod_info
288        t_info = self.mod_finder.find_test_by_module_and_package(MODULE_PACKAGE)
289        unittest_utils.assert_equal_testinfos(self, t_info, uc.PACKAGE_INFO)
290        # with method, raises
291        module_pkg_with_method = '%s:%s#%s' % (uc.MODULE2_NAME, uc.PACKAGE,
292                                               uc.METHOD_NAME)
293        self.assertRaises(atest_error.MethodWithoutClassError,
294                          self.mod_finder.find_test_by_module_and_package,
295                          module_pkg_with_method)
296        # bad module, good pkg, returns None
297        bad_module = '%s:%s' % ('BadMod', uc.PACKAGE)
298        self.mod_finder.module_info.get_module_info.return_value = None
299        self.assertIsNone(self.mod_finder.find_test_by_module_and_package(bad_module))
300        # find output fails to find package path
301        mock_checkoutput.return_value = ''
302        bad_pkg = '%s:%s' % (uc.MODULE_NAME, 'Anything')
303        self.mod_finder.module_info.get_module_info.return_value = mod_info
304        self.assertIsNone(self.mod_finder.find_test_by_module_and_package(bad_pkg))
305
306    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
307                       return_value=True)
308    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets')
309    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
310                       return_value=False)
311    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
312                       return_value=False)
313    @mock.patch.object(test_finder_utils, 'get_fully_qualified_class_name',
314                       return_value=uc.FULL_CLASS_NAME)
315    @mock.patch('os.path.realpath',
316                side_effect=unittest_utils.realpath_side_effect)
317    @mock.patch('os.path.isfile', side_effect=unittest_utils.isfile_side_effect)
318    @mock.patch.object(test_finder_utils, 'find_parent_module_dir')
319    @mock.patch('os.path.exists')
320    #pylint: disable=unused-argument
321    def test_find_test_by_path(self, mock_pathexists, mock_dir, _isfile, _real,
322                               _fqcn, _robo, _vts, mock_build, _has_test_config):
323        """Test find_test_by_path."""
324        mock_build.return_value = set()
325        # Check that we don't return anything with invalid test references.
326        mock_pathexists.return_value = False
327        unittest_utils.assert_equal_testinfos(
328            self, None, self.mod_finder.find_test_by_path('bad/path'))
329        mock_pathexists.return_value = True
330        mock_dir.return_value = None
331        unittest_utils.assert_equal_testinfos(
332            self, None, self.mod_finder.find_test_by_path('no/module'))
333        self.mod_finder.module_info.get_module_names.return_value = [uc.MODULE_NAME]
334        self.mod_finder.module_info.get_module_info.return_value = {
335            constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
336            constants.MODULE_NAME: uc.MODULE_NAME}
337
338        # Happy path testing.
339        mock_dir.return_value = uc.MODULE_DIR
340        class_path = '%s.java' % uc.CLASS_NAME
341        mock_build.return_value = uc.CLASS_BUILD_TARGETS
342        unittest_utils.assert_equal_testinfos(
343            self, uc.CLASS_INFO, self.mod_finder.find_test_by_path(class_path))
344
345        class_with_method = '%s#%s' % (class_path, uc.METHOD_NAME)
346        mock_build.return_value = uc.MODULE_BUILD_TARGETS
347        unittest_utils.assert_equal_testinfos(
348            self, self.mod_finder.find_test_by_path(class_with_method), uc.METHOD_INFO)
349
350        class_with_methods = '%s,%s' % (class_with_method, uc.METHOD2_NAME)
351        mock_build.return_value = uc.MODULE_BUILD_TARGETS
352        unittest_utils.assert_equal_testinfos(
353            self, self.mod_finder.find_test_by_path(class_with_methods),
354            FLAT_METHOD_INFO)
355
356    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config',
357                       return_value=True)
358    @mock.patch.object(module_finder.ModuleFinder, '_get_build_targets',
359                       return_value=uc.MODULE_BUILD_TARGETS)
360    @mock.patch.object(module_finder.ModuleFinder, '_is_vts_module',
361                       return_value=False)
362    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test',
363                       return_value=False)
364    @mock.patch.object(test_finder_utils, 'find_parent_module_dir',
365                       return_value=os.path.relpath(uc.TEST_DATA_DIR, uc.ROOT))
366    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config',
367                       return_value=False)
368    #pylint: disable=unused-argument
369    def test_find_test_by_path_part_2(self, _is_auto_gen, _find_parent, _is_vts,
370                                      _is_robo, _get_build, _has_test_config):
371        """Test find_test_by_path for directories."""
372        # Dir with java files in it, should run as package
373        class_dir = os.path.join(uc.TEST_DATA_DIR, 'path_testing')
374        self.mod_finder.module_info.get_module_names.return_value = [uc.MODULE_NAME]
375        self.mod_finder.module_info.get_module_info.return_value = {
376            constants.MODULE_INSTALLED: DEFAULT_INSTALL_PATH,
377            constants.MODULE_NAME: uc.MODULE_NAME}
378        unittest_utils.assert_equal_testinfos(
379            self, uc.PATH_INFO, self.mod_finder.find_test_by_path(class_dir))
380        # Dir with no java files in it, should run whole module
381        empty_dir = os.path.join(uc.TEST_DATA_DIR, 'path_testing_empty')
382        unittest_utils.assert_equal_testinfos(
383            self, uc.EMPTY_PATH_INFO,
384            self.mod_finder.find_test_by_path(empty_dir))
385
386    @mock.patch.object(module_finder.ModuleFinder, '_has_test_config')
387    @mock.patch.object(module_finder.ModuleFinder, '_is_robolectric_test')
388    def test_is_testable_module(self, mock_is_robo_test, mock_has_test_config):
389        """Test _is_testable_module."""
390        mock_is_robo_test.return_value = False
391        mock_has_test_config.return_value = True
392        installed_module_info = {constants.MODULE_INSTALLED:
393                                 DEFAULT_INSTALL_PATH}
394        non_installed_module_info = {constants.MODULE_NAME: 'rand_name'}
395        # Empty mod_info or a non-installed module.
396        self.assertFalse(self.mod_finder._is_testable_module(
397            non_installed_module_info))
398        self.assertFalse(self.mod_finder._is_testable_module({}))
399
400        # Testable Module or is a robo module for non-installed module.
401        self.assertTrue(self.mod_finder._is_testable_module(
402            installed_module_info))
403        mock_has_test_config.return_value = False
404        self.assertFalse(self.mod_finder._is_testable_module(
405            installed_module_info))
406        mock_is_robo_test.return_value = True
407        self.assertTrue(self.mod_finder._is_testable_module(
408            non_installed_module_info))
409
410    def test_get_robolectric_test_name(self):
411        """Test get_robolectric_test_name."""
412        # Happy path testing, make sure we get the run robo target.
413        self.mod_finder.module_info.get_module_info.side_effect = get_mod_info_side_effect
414        self.mod_finder.module_info.get_module_names.return_value = [
415            RUN_ROBO_MOD_NAME, NON_RUN_ROBO_MOD_NAME]
416        self.assertEqual(self.mod_finder._get_robolectric_test_name(
417            NON_RUN_ROBO_MOD_NAME), RUN_ROBO_MOD_NAME)
418        # Let's also make sure we don't return anything when we're not supposed
419        # to.
420        self.mod_finder.module_info.get_module_info.side_effect = get_mod_info_side_effect
421        self.mod_finder.module_info.get_module_names.return_value = [
422            NON_RUN_ROBO_MOD_NAME]
423        self.assertEqual(self.mod_finder._get_robolectric_test_name(
424            NON_RUN_ROBO_MOD_NAME), None)
425
426    def test_is_robolectric_test(self):
427        """Test _is_robolectric_test."""
428        # Happy path testing, make sure we get the run robo target.
429        self.mod_finder.module_info.get_module_info.side_effect = get_mod_info_side_effect
430        self.mod_finder.module_info.get_module_names.return_value = [
431            RUN_ROBO_MOD_NAME, NON_RUN_ROBO_MOD_NAME]
432
433        self.mod_finder.module_info.get_module_info.return_value = RUN_ROBO_MOD
434        # Test on a run robo module.
435        self.assertTrue(self.mod_finder._is_robolectric_test(RUN_ROBO_MOD_NAME))
436
437        # Test on a non-run robo module but shares with a run robo module.
438        self.assertTrue(self.mod_finder._is_robolectric_test(NON_RUN_ROBO_MOD_NAME))
439
440        # Make sure we don't find robo tests where they don't exist.
441        self.mod_finder.module_info.get_module_info.return_value = None
442        self.assertFalse(self.mod_finder._is_robolectric_test('rand_mod'))
443
444    @mock.patch.object(module_finder.ModuleFinder, '_is_auto_gen_test_config')
445    def test_has_test_config(self, mock_is_auto_gen):
446        """Test _has_test_config."""
447        mock_is_auto_gen.return_value = True
448        self.mod_finder.root_dir = uc.TEST_DATA_DIR
449        mod_info = {constants.MODULE_PATH:[uc.RELATIVE_TEST_DATA_DIR]}
450
451        # Validate we see the config when it's auto-generated.
452        self.assertTrue(self.mod_finder._has_test_config(mod_info))
453        self.assertTrue(self.mod_finder._has_test_config({}))
454        # Validate when actual config exists and there's no auto-generated config.
455        mock_is_auto_gen.return_value = False
456        self.assertTrue(self.mod_finder._has_test_config(mod_info))
457        self.assertFalse(self.mod_finder._has_test_config({}))
458
459if __name__ == '__main__':
460    unittest.main()
461