mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 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 | import unittest |
mikehoran | 1e50d2b | 2017-08-28 14:00:46 -0700 | [diff] [blame] | 20 | import os |
mikehoran | 9e62c29 | 2018-01-31 12:05:19 -0800 | [diff] [blame] | 21 | import re |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 22 | import mock |
| 23 | |
| 24 | import cli_translator as cli_t |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 25 | import constants |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 26 | import test_finder_handler |
Dan Shi | cdbda55 | 2018-05-18 23:31:33 -0700 | [diff] [blame] | 27 | import test_mapping |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 28 | import unittest_constants as uc |
Kevin Cheng | 7edb0b9 | 2017-12-14 15:00:25 -0800 | [diff] [blame] | 29 | import unittest_utils |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 30 | from test_finders import test_finder_base |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 31 | |
Dan Shi | d6881bb | 2017-10-12 15:13:25 -0700 | [diff] [blame] | 32 | # TEST_MAPPING related consts |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 33 | TEST_MAPPING_TOP_DIR = os.path.join(uc.TEST_DATA_DIR, 'test_mapping') |
| 34 | TEST_MAPPING_DIR = os.path.join(TEST_MAPPING_TOP_DIR, 'folder1') |
| 35 | TEST_1 = test_mapping.TestDetail({'name': 'test1'}) |
| 36 | TEST_2 = test_mapping.TestDetail({'name': 'test2'}) |
| 37 | TEST_3 = test_mapping.TestDetail({'name': 'test3'}) |
| 38 | TEST_4 = test_mapping.TestDetail({'name': 'test4'}) |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 39 | TEST_5 = test_mapping.TestDetail({'name': 'test5'}) |
| 40 | TEST_6 = test_mapping.TestDetail({'name': 'test6'}) |
| 41 | TEST_7 = test_mapping.TestDetail({'name': 'test7'}) |
| 42 | TEST_8 = test_mapping.TestDetail({'name': 'test8'}) |
| 43 | TEST_9 = test_mapping.TestDetail({'name': 'test9'}) |
| 44 | TEST_10 = test_mapping.TestDetail({'name': 'test10'}) |
Dan Shi | d6881bb | 2017-10-12 15:13:25 -0700 | [diff] [blame] | 45 | |
mikehoran | 9e62c29 | 2018-01-31 12:05:19 -0800 | [diff] [blame] | 46 | SEARCH_DIR_RE = re.compile(r'^find ([^ ]*).*$') |
| 47 | |
mikehoran | 58a68c4 | 2017-08-30 13:18:21 -0700 | [diff] [blame] | 48 | |
Dan Shi | cdbda55 | 2018-05-18 23:31:33 -0700 | [diff] [blame] | 49 | #pylint: disable=unused-argument |
| 50 | def gettestinfos_side_effect(test_names, test_mapping_test_details=None): |
Kevin Cheng | 09c2a2c | 2017-12-15 12:52:46 -0800 | [diff] [blame] | 51 | """Mock return values for _get_test_info.""" |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 52 | test_infos = set() |
| 53 | for test_name in test_names: |
| 54 | if test_name == uc.MODULE_NAME: |
| 55 | test_infos.add(uc.MODULE_INFO) |
| 56 | if test_name == uc.CLASS_NAME: |
| 57 | test_infos.add(uc.CLASS_INFO) |
| 58 | return test_infos |
mikehoran | 58a68c4 | 2017-08-30 13:18:21 -0700 | [diff] [blame] | 59 | |
mikehoran | 9e62c29 | 2018-01-31 12:05:19 -0800 | [diff] [blame] | 60 | |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 61 | #pylint: disable=protected-access |
mikehoran | 43ed32d | 2017-08-18 17:13:36 -0700 | [diff] [blame] | 62 | #pylint: disable=no-self-use |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 63 | class CLITranslatorUnittests(unittest.TestCase): |
| 64 | """Unit tests for cli_t.py""" |
| 65 | |
| 66 | def setUp(self): |
| 67 | """Run before execution of every test""" |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 68 | self.ctr = cli_t.CLITranslator() |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 69 | |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 70 | # Create a mock of args. |
| 71 | self.args = mock.Mock |
| 72 | self.args.tests = [] |
| 73 | # Test mapping related args |
| 74 | self.args.test_mapping = False |
| 75 | self.args.include_subdirs = False |
| 76 | |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 77 | @mock.patch.object(test_finder_handler, 'get_find_methods_for_test') |
| 78 | def test_get_test_infos(self, mock_getfindmethods): |
| 79 | """Test _get_test_infos method.""" |
| 80 | ctr = cli_t.CLITranslator() |
| 81 | find_method_return_module_info = lambda x, y: uc.MODULE_INFO |
| 82 | # pylint: disable=invalid-name |
| 83 | find_method_return_module_class_info = (lambda x, test: uc.MODULE_INFO |
| 84 | if test == uc.MODULE_NAME |
| 85 | else uc.CLASS_INFO) |
| 86 | find_method_return_nothing = lambda x, y: None |
| 87 | one_test = [uc.MODULE_NAME] |
| 88 | mult_test = [uc.MODULE_NAME, uc.CLASS_NAME] |
mikehoran | 43ed32d | 2017-08-18 17:13:36 -0700 | [diff] [blame] | 89 | |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 90 | # Let's make sure we return what we expect. |
| 91 | expected_test_infos = {uc.MODULE_INFO} |
| 92 | mock_getfindmethods.return_value = [ |
nelsonli | 34997d5 | 2018-08-17 09:43:28 +0800 | [diff] [blame] | 93 | test_finder_base.Finder(None, find_method_return_module_info, None)] |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 94 | unittest_utils.assert_strict_equal( |
| 95 | self, ctr._get_test_infos(one_test), expected_test_infos) |
| 96 | |
| 97 | # Check we receive multiple test infos. |
| 98 | expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO} |
| 99 | mock_getfindmethods.return_value = [ |
nelsonli | 34997d5 | 2018-08-17 09:43:28 +0800 | [diff] [blame] | 100 | test_finder_base.Finder(None, find_method_return_module_class_info, |
| 101 | None)] |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 102 | unittest_utils.assert_strict_equal( |
| 103 | self, ctr._get_test_infos(mult_test), expected_test_infos) |
| 104 | |
nelsonli | c4a7145 | 2018-09-13 14:10:30 +0800 | [diff] [blame^] | 105 | # Check return null set when we have no tests found. |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 106 | mock_getfindmethods.return_value = [ |
nelsonli | 34997d5 | 2018-08-17 09:43:28 +0800 | [diff] [blame] | 107 | test_finder_base.Finder(None, find_method_return_nothing, None)] |
nelsonli | c4a7145 | 2018-09-13 14:10:30 +0800 | [diff] [blame^] | 108 | null_test_info = set() |
| 109 | self.assertEqual(null_test_info, ctr._get_test_infos(one_test)) |
| 110 | self.assertEqual(null_test_info, ctr._get_test_infos(mult_test)) |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 111 | |
Dan Shi | cdbda55 | 2018-05-18 23:31:33 -0700 | [diff] [blame] | 112 | # Check the method works for test mapping. |
| 113 | test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST) |
| 114 | test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION) |
| 115 | expected_test_infos = {uc.MODULE_INFO, uc.CLASS_INFO} |
| 116 | mock_getfindmethods.return_value = [ |
nelsonli | 34997d5 | 2018-08-17 09:43:28 +0800 | [diff] [blame] | 117 | test_finder_base.Finder(None, find_method_return_module_class_info, |
| 118 | None)] |
Dan Shi | cdbda55 | 2018-05-18 23:31:33 -0700 | [diff] [blame] | 119 | test_infos = ctr._get_test_infos( |
| 120 | mult_test, [test_detail1, test_detail2]) |
| 121 | unittest_utils.assert_strict_equal( |
| 122 | self, test_infos, expected_test_infos) |
| 123 | for test_info in test_infos: |
| 124 | if test_info == uc.MODULE_INFO: |
| 125 | self.assertEqual( |
| 126 | test_detail1.options, |
| 127 | test_info.data[constants.TI_MODULE_ARG]) |
| 128 | else: |
| 129 | self.assertEqual( |
| 130 | test_detail2.options, |
| 131 | test_info.data[constants.TI_MODULE_ARG]) |
| 132 | |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 133 | @mock.patch.object(cli_t.CLITranslator, '_get_test_infos', |
| 134 | side_effect=gettestinfos_side_effect) |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 135 | def test_translate_class(self, _info): |
| 136 | """Test translate method for tests by class name.""" |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 137 | # Check that we can find a class. |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 138 | self.args.tests = [uc.CLASS_NAME] |
| 139 | targets, test_infos = self.ctr.translate(self.args) |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 140 | unittest_utils.assert_strict_equal( |
| 141 | self, targets, uc.CLASS_BUILD_TARGETS) |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 142 | unittest_utils.assert_strict_equal(self, test_infos, {uc.CLASS_INFO}) |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 143 | |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 144 | @mock.patch.object(cli_t.CLITranslator, '_get_test_infos', |
| 145 | side_effect=gettestinfos_side_effect) |
| 146 | def test_translate_module(self, _info): |
| 147 | """Test translate method for tests by module or class name.""" |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 148 | # Check that we get all the build targets we expect. |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 149 | self.args.tests = [uc.MODULE_NAME, uc.CLASS_NAME] |
| 150 | targets, test_infos = self.ctr.translate(self.args) |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 151 | unittest_utils.assert_strict_equal( |
| 152 | self, targets, uc.MODULE_CLASS_COMBINED_BUILD_TARGETS) |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 153 | unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO, |
| 154 | uc.CLASS_INFO}) |
| 155 | |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 156 | @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping') |
| 157 | @mock.patch.object(cli_t.CLITranslator, '_get_test_infos', |
| 158 | side_effect=gettestinfos_side_effect) |
| 159 | def test_translate_test_mapping(self, _info, mock_testmapping): |
| 160 | """Test translate method for tests in test mapping.""" |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 161 | # Check that test mappings feeds into get_test_info properly. |
Dan Shi | cdbda55 | 2018-05-18 23:31:33 -0700 | [diff] [blame] | 162 | test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST) |
| 163 | test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION) |
| 164 | mock_testmapping.return_value = ([test_detail1, test_detail2], None) |
Dan Shi | 0ddd3e4 | 2018-05-30 11:24:30 -0700 | [diff] [blame] | 165 | self.args.tests = [] |
| 166 | targets, test_infos = self.ctr.translate(self.args) |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 167 | unittest_utils.assert_strict_equal( |
| 168 | self, targets, uc.MODULE_CLASS_COMBINED_BUILD_TARGETS) |
Kevin Cheng | 8b2c94c | 2017-12-18 14:43:26 -0800 | [diff] [blame] | 169 | unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO, |
| 170 | uc.CLASS_INFO}) |
| 171 | |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 172 | @mock.patch.object(cli_t.CLITranslator, '_find_tests_by_test_mapping') |
| 173 | @mock.patch.object(cli_t.CLITranslator, '_get_test_infos', |
| 174 | side_effect=gettestinfos_side_effect) |
| 175 | def test_translate_test_mapping_all(self, _info, mock_testmapping): |
| 176 | """Test translate method for tests in test mapping.""" |
| 177 | # Check that test mappings feeds into get_test_info properly. |
| 178 | test_detail1 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST) |
| 179 | test_detail2 = test_mapping.TestDetail(uc.TEST_MAPPING_TEST_WITH_OPTION) |
| 180 | mock_testmapping.return_value = ([test_detail1, test_detail2], None) |
| 181 | self.args.tests = ['src_path:all'] |
| 182 | self.args.test_mapping = True |
| 183 | targets, test_infos = self.ctr.translate(self.args) |
| 184 | unittest_utils.assert_strict_equal( |
| 185 | self, targets, uc.MODULE_CLASS_COMBINED_BUILD_TARGETS) |
| 186 | unittest_utils.assert_strict_equal(self, test_infos, {uc.MODULE_INFO, |
| 187 | uc.CLASS_INFO}) |
| 188 | |
| 189 | def test_find_tests_by_test_mapping_presubmit(self): |
| 190 | """Test _find_tests_by_test_mapping method to locate presubmit tests.""" |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 191 | os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR} |
| 192 | with mock.patch.dict('os.environ', os_environ_mock, clear=True): |
| 193 | tests, all_tests = self.ctr._find_tests_by_test_mapping( |
| 194 | path=TEST_MAPPING_DIR, file_name='test_mapping_sample', |
| 195 | checked_files=set()) |
| 196 | expected = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9]) |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 197 | expected_all_tests = {'presubmit': expected, |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 198 | 'postsubmit': set( |
| 199 | [TEST_3, TEST_6, TEST_8, TEST_10]), |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 200 | 'other_group': set([TEST_4])} |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 201 | self.assertEqual(expected, tests) |
| 202 | self.assertEqual(expected_all_tests, all_tests) |
Dan Shi | d6881bb | 2017-10-12 15:13:25 -0700 | [diff] [blame] | 203 | |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 204 | def test_find_tests_by_test_mapping_postsubmit(self): |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 205 | """Test _find_tests_by_test_mapping method to locate postsubmit tests. |
| 206 | """ |
| 207 | os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR} |
| 208 | with mock.patch.dict('os.environ', os_environ_mock, clear=True): |
| 209 | tests, all_tests = self.ctr._find_tests_by_test_mapping( |
| 210 | path=TEST_MAPPING_DIR, |
| 211 | test_group=constants.TEST_GROUP_POSTSUBMIT, |
| 212 | file_name='test_mapping_sample', checked_files=set()) |
| 213 | expected_presubmit = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9]) |
| 214 | expected = set( |
| 215 | [TEST_1, TEST_2, TEST_3, TEST_5, TEST_6, TEST_7, TEST_8, TEST_9, |
| 216 | TEST_10]) |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 217 | expected_all_tests = {'presubmit': expected_presubmit, |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 218 | 'postsubmit': set( |
| 219 | [TEST_3, TEST_6, TEST_8, TEST_10]), |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 220 | 'other_group': set([TEST_4])} |
Dan Shi | 7a8e1ad | 2018-04-12 11:01:07 -0700 | [diff] [blame] | 221 | self.assertEqual(expected, tests) |
| 222 | self.assertEqual(expected_all_tests, all_tests) |
Dan Shi | d6881bb | 2017-10-12 15:13:25 -0700 | [diff] [blame] | 223 | |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 224 | def test_find_tests_by_test_mapping_all_group(self): |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 225 | """Test _find_tests_by_test_mapping method to locate postsubmit tests. |
| 226 | """ |
| 227 | os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR} |
| 228 | with mock.patch.dict('os.environ', os_environ_mock, clear=True): |
| 229 | tests, all_tests = self.ctr._find_tests_by_test_mapping( |
| 230 | path=TEST_MAPPING_DIR, test_group=constants.TEST_GROUP_ALL, |
| 231 | file_name='test_mapping_sample', checked_files=set()) |
| 232 | expected_presubmit = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9]) |
| 233 | expected = set([ |
| 234 | TEST_1, TEST_2, TEST_3, TEST_4, TEST_5, TEST_6, TEST_7, TEST_8, |
| 235 | TEST_9, TEST_10]) |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 236 | expected_all_tests = {'presubmit': expected_presubmit, |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 237 | 'postsubmit': set( |
| 238 | [TEST_3, TEST_6, TEST_8, TEST_10]), |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 239 | 'other_group': set([TEST_4])} |
| 240 | self.assertEqual(expected, tests) |
| 241 | self.assertEqual(expected_all_tests, all_tests) |
| 242 | |
| 243 | def test_find_tests_by_test_mapping_include_subdir(self): |
| 244 | """Test _find_tests_by_test_mapping method to include sub directory.""" |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 245 | os_environ_mock = {constants.ANDROID_BUILD_TOP: uc.TEST_DATA_DIR} |
| 246 | with mock.patch.dict('os.environ', os_environ_mock, clear=True): |
| 247 | tests, all_tests = self.ctr._find_tests_by_test_mapping( |
| 248 | path=TEST_MAPPING_TOP_DIR, file_name='test_mapping_sample', |
| 249 | include_subdirs=True, checked_files=set()) |
| 250 | expected = set([TEST_1, TEST_2, TEST_5, TEST_7, TEST_9]) |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 251 | expected_all_tests = {'presubmit': expected, |
Dan Shi | 350e747 | 2018-06-19 12:25:32 -0700 | [diff] [blame] | 252 | 'postsubmit': set([ |
| 253 | TEST_3, TEST_6, TEST_8, TEST_10]), |
Dan Shi | e4e267f | 2018-06-01 11:31:57 -0700 | [diff] [blame] | 254 | 'other_group': set([TEST_4])} |
| 255 | self.assertEqual(expected, tests) |
| 256 | self.assertEqual(expected_all_tests, all_tests) |
| 257 | |
| 258 | |
mikehoran | be9102f | 2017-08-04 16:04:03 -0700 | [diff] [blame] | 259 | if __name__ == '__main__': |
| 260 | unittest.main() |