Xixuan Wu | abbaa4c | 2017-08-23 17:31:49 -0700 | [diff] [blame] | 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Module for config reader unittests.""" |
| 6 | |
| 7 | import unittest |
| 8 | |
| 9 | import config_reader |
| 10 | import constants |
| 11 | import mock |
Xixuan Wu | 7e30c9d | 2017-09-05 18:46:00 -0700 | [diff] [blame] | 12 | import tot_manager |
| 13 | |
| 14 | |
| 15 | class FakeTotMilestoneManager(tot_manager.TotMilestoneManager): |
| 16 | |
| 17 | def __init__(self, is_sanity): |
| 18 | self.is_sanity = is_sanity |
| 19 | self.storage_client = None |
| 20 | self.tot = self._tot_milestone() |
Xixuan Wu | abbaa4c | 2017-08-23 17:31:49 -0700 | [diff] [blame] | 21 | |
| 22 | |
| 23 | class BaseTaskConfigReaderTestCase(unittest.TestCase): |
| 24 | |
| 25 | _EVENT_TYPE = 'nightly' |
| 26 | _PRIORITY = config_reader.EVENT_CLASSES[_EVENT_TYPE].PRIORITY |
| 27 | _TIMEOUT = config_reader.EVENT_CLASSES[_EVENT_TYPE].TIMEOUT |
| 28 | _TASK_NAME = 'fake_task' |
| 29 | _SUITE = 'fake_suite' |
| 30 | _BRANCH_SPEC = 'tot-1' |
| 31 | _POOL = 'bvt' |
| 32 | _NUM = 2 |
| 33 | _BOARD = 'link' |
| 34 | |
| 35 | def setUp(self): |
| 36 | self.config = config_reader.ConfigReader(None) |
| 37 | self.config.add_section(self._TASK_NAME) |
| 38 | self.config.set(self._TASK_NAME, 'suite', self._SUITE) |
| 39 | self.config.set(self._TASK_NAME, 'branch_specs', self._BRANCH_SPEC) |
| 40 | self.config.set(self._TASK_NAME, 'run_on', self._EVENT_TYPE) |
| 41 | self.config.set(self._TASK_NAME, 'pool', self._POOL) |
| 42 | self.config.set(self._TASK_NAME, 'num', '%d' % self._NUM) |
| 43 | self.config.set(self._TASK_NAME, 'boards', self._BOARD) |
| 44 | |
| 45 | tot_patcher = mock.patch('tot_manager.TotMilestoneManager') |
| 46 | self._tot = tot_patcher.start() |
Xixuan Wu | 7e30c9d | 2017-09-05 18:46:00 -0700 | [diff] [blame] | 47 | self._tot.return_value = FakeTotMilestoneManager(True) |
Xixuan Wu | abbaa4c | 2017-08-23 17:31:49 -0700 | [diff] [blame] | 48 | self.addCleanup(tot_patcher.stop) |
| 49 | |
| 50 | |
| 51 | class TaskCreationTestCase(BaseTaskConfigReaderTestCase): |
| 52 | |
| 53 | def testCreateTaskFromConfigNonexistentSection(self): |
| 54 | """Ensure a Task CANNOT be built without suite, and raise error.""" |
| 55 | task_config = config_reader.TaskConfig(self.config) |
| 56 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 57 | task_config._create_task_from_config_section, |
| 58 | 'non-existent section') |
| 59 | |
| 60 | def testCreateTaskFromConfigNotAllowedHeader(self): |
| 61 | """Ensure a Task CANNOT be built without suite, and raise error.""" |
| 62 | self.config.set(self._TASK_NAME, 'non-valid-header', 'test') |
| 63 | task_config = config_reader.TaskConfig(self.config) |
| 64 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 65 | task_config._create_task_from_config_section, |
| 66 | self._TASK_NAME) |
| 67 | |
| 68 | def testGetTaskByKeyword(self): |
| 69 | """Ensure a Task can be built from a correct config.""" |
| 70 | task_config = config_reader.TaskConfig(self.config) |
| 71 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 72 | self.assertEqual(len(tasks), 1) |
| 73 | new_task = tasks[0] |
| 74 | self.assertEqual(new_task.name, self._TASK_NAME) |
| 75 | self.assertEqual(new_task.suite, self._SUITE) |
| 76 | self.assertEqual(new_task.branch_specs, [self._BRANCH_SPEC]) |
| 77 | self.assertEqual(new_task.pool, self._POOL) |
| 78 | self.assertEqual(new_task.num, self._NUM) |
Xixuan Wu | 0c76d5b | 2017-08-30 16:40:17 -0700 | [diff] [blame] | 79 | self.assertEqual(new_task.boards, |
| 80 | [t.lstrip() for t in self._BOARD.split(',')]) |
Xixuan Wu | abbaa4c | 2017-08-23 17:31:49 -0700 | [diff] [blame] | 81 | self.assertEqual(new_task.priority, self._PRIORITY) |
| 82 | self.assertEqual(new_task.timeout, self._TIMEOUT) |
| 83 | |
Xixuan Wu | abbaa4c | 2017-08-23 17:31:49 -0700 | [diff] [blame] | 84 | def testGetTaskByKeywordNoRunonNoRaise(self): |
| 85 | """Ensure a Task CANNOT be built without run_on, but not raise error.""" |
| 86 | self.config.remove_option(self._TASK_NAME, 'run_on') |
| 87 | task_config = config_reader.TaskConfig(self.config) |
| 88 | try: |
| 89 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 90 | self.assertEqual(len(tasks), 0) |
| 91 | except config_reader.MalformedConfigEntryError: |
| 92 | self.fail('task_config should not raise error without run_on!') |
| 93 | |
| 94 | def testGetTaskByKeywordNoSuiteNoRaise(self): |
| 95 | """Ensure a Task CANNOT be built without suite, but not raise error. |
| 96 | |
| 97 | This is to ensure a malformed task won't affect other tasks' reading. |
| 98 | """ |
| 99 | self.config.remove_option(self._TASK_NAME, 'suite') |
| 100 | task_config = config_reader.TaskConfig(self.config) |
| 101 | try: |
| 102 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 103 | self.assertEqual(len(tasks), 0) |
| 104 | except config_reader.MalformedConfigEntry: |
| 105 | self.fail('task_config should not raise error without suite!') |
| 106 | |
| 107 | def testGetTaskByKeywordNoBranch(self): |
| 108 | """Ensure a Task can be built without branch_specs.""" |
| 109 | self.config.remove_option(self._TASK_NAME, 'branch_specs') |
| 110 | task_config = config_reader.TaskConfig(self.config) |
| 111 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 112 | self.assertEqual(tasks[0].branch_specs, []) |
| 113 | |
| 114 | def testGetTaskByKeywordNoNum(self): |
| 115 | """Ensure a Task can be built without num.""" |
| 116 | self.config.remove_option(self._TASK_NAME, 'num') |
| 117 | task_config = config_reader.TaskConfig(self.config) |
| 118 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 119 | self.assertIsNone(tasks[0].num) |
| 120 | |
| 121 | def testSetPriority(self): |
| 122 | """Ensure priority can be set by user.""" |
| 123 | priority = constants.Priorities.DEFAULT |
| 124 | self.config.set(self._TASK_NAME, 'priority', str(priority)) |
| 125 | task_config = config_reader.TaskConfig(self.config) |
| 126 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 127 | self.assertEqual(tasks[0].priority, priority) |
| 128 | |
| 129 | def testSetTimeout(self): |
| 130 | """Ensure timeout can be set by user.""" |
| 131 | timeout = 1000 |
| 132 | self.config.set(self._TASK_NAME, 'timeout', str(timeout)) |
| 133 | task_config = config_reader.TaskConfig(self.config) |
| 134 | tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE) |
| 135 | self.assertEqual(tasks[0].timeout, timeout) |
| 136 | |
| 137 | |
| 138 | class TaskInfoCheckTestCase(BaseTaskConfigReaderTestCase): |
| 139 | |
| 140 | def testNonIntNum(self): |
| 141 | """Ensure a Task's num is a Integer.""" |
| 142 | self.config.set(self._TASK_NAME, 'num', 'non_int') |
| 143 | task_config = config_reader.TaskConfig(self.config) |
| 144 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 145 | task_config._read_task_section, |
| 146 | self._TASK_NAME) |
| 147 | |
| 148 | def testNonIntHour(self): |
| 149 | """Ensure a Task's hour is a Integer.""" |
| 150 | self.config.set(self._TASK_NAME, 'hour', 'non_int') |
| 151 | task_config = config_reader.TaskConfig(self.config) |
| 152 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 153 | task_config._read_task_section, |
| 154 | self._TASK_NAME) |
| 155 | |
| 156 | def testNonIntDay(self): |
| 157 | """Ensure a Task's hour is a Integer.""" |
| 158 | self.config.set(self._TASK_NAME, 'day', 'non_int') |
| 159 | task_config = config_reader.TaskConfig(self.config) |
| 160 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 161 | task_config._read_task_section, |
| 162 | self._TASK_NAME) |
| 163 | |
| 164 | def testNoSuite(self): |
| 165 | """Ensure a Task's suite exists.""" |
| 166 | self.config.remove_option(self._TASK_NAME, 'suite') |
| 167 | task_config = config_reader.TaskConfig(self.config) |
| 168 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 169 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 170 | task_config._validate_task_section, |
| 171 | task_info) |
| 172 | |
| 173 | def testInvalidIntHour(self): |
| 174 | """Ensure a Task's hour is in 0~23.""" |
| 175 | self.config.set(self._TASK_NAME, 'hour', '24') |
| 176 | task_config = config_reader.TaskConfig(self.config) |
| 177 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 178 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 179 | task_config._validate_task_section, |
| 180 | task_info) |
| 181 | |
| 182 | def testNoHourForNonNightlyEvent(self): |
| 183 | """Ensure a non-nightly Task cannot specify hour.""" |
| 184 | self.config.set(self._TASK_NAME, 'hour', '10') |
| 185 | self.config.set(self._TASK_NAME, 'run_on', 'new_build') |
| 186 | task_config = config_reader.TaskConfig(self.config) |
| 187 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 188 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 189 | task_config._validate_task_section, |
| 190 | task_info) |
| 191 | |
| 192 | def testInvalidIntDay(self): |
| 193 | """Ensure a Task's day is in 0~6.""" |
| 194 | self.config.set(self._TASK_NAME, 'day', '10') |
| 195 | self.config.set(self._TASK_NAME, 'run_on', 'weekly') |
| 196 | task_config = config_reader.TaskConfig(self.config) |
| 197 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 198 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 199 | task_config._validate_task_section, |
| 200 | task_info) |
| 201 | |
| 202 | def testNoDayForNonWeeklyEvent(self): |
| 203 | """Ensure a non-weekly Task cannot specify day.""" |
| 204 | self.config.set(self._TASK_NAME, 'day', '1') |
| 205 | self.config.set(self._TASK_NAME, 'run_on', 'nightly') |
| 206 | task_config = config_reader.TaskConfig(self.config) |
| 207 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 208 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 209 | task_config._validate_task_section, |
| 210 | task_info) |
| 211 | |
| 212 | def testInValidOSType(self): |
| 213 | """Ensure a Task's os_type is valid.""" |
| 214 | self.config.set(self._TASK_NAME, 'os_type', 'invalid') |
| 215 | task_config = config_reader.TaskConfig(self.config) |
| 216 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 217 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 218 | task_config._check_os_type, |
| 219 | task_info) |
| 220 | |
| 221 | def testNoLaunchControlForCrOS(self): |
| 222 | """Ensure a CrOS Task doesn't have launch control settings.""" |
| 223 | self.config.set(self._TASK_NAME, 'os_type', 'CrOS') |
| 224 | self.config.set(self._TASK_NAME, 'branches', 'shamu-userdebug') |
| 225 | task_config = config_reader.TaskConfig(self.config) |
| 226 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 227 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 228 | task_config._check_os_type, |
| 229 | task_info) |
| 230 | |
| 231 | def testLaunchControlForNonCrOS(self): |
| 232 | """Ensure an android Task has launch control settings.""" |
| 233 | self.config.set(self._TASK_NAME, 'os_type', 'android') |
| 234 | task_config = config_reader.TaskConfig(self.config) |
| 235 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 236 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 237 | task_config._check_os_type, |
| 238 | task_info) |
| 239 | |
| 240 | def testGetTestbedCount(self): |
| 241 | """Ensure testbed count can be successfully parsed.""" |
| 242 | task_config = config_reader.TaskConfig(self.config) |
| 243 | self.assertEqual(task_config._get_testbed_dut_count('sharu-2'), 2) |
| 244 | |
| 245 | def testNoTestbedForCrOS(self): |
| 246 | """Ensure CrOS task won't specify testbed parameters.""" |
| 247 | self.config.set(self._TASK_NAME, 'boards', 'sharu-2') |
| 248 | task_config = config_reader.TaskConfig(self.config) |
| 249 | task_info = task_config._read_task_section(self._TASK_NAME) |
| 250 | self.assertRaises(config_reader.MalformedConfigEntryError, |
| 251 | task_config._check_testbed_parameter, |
| 252 | task_info) |
| 253 | |
| 254 | |
| 255 | class LabReaderTestCase(unittest.TestCase): |
| 256 | |
| 257 | def setUp(self): |
| 258 | self.config = config_reader.ConfigReader(None) |
| 259 | self.config.add_section(config_reader.ANDROID_BOARD) |
| 260 | self.config.add_section(config_reader.RELEASED_RO_BUILDS) |
| 261 | |
| 262 | def testGetAndroidBoardList(self): |
| 263 | """Ensure android board list can be correctly fetched.""" |
| 264 | self.config.set(config_reader.ANDROID_BOARD, 'board_list', |
| 265 | 'abox_edge,android-angler-1,angler-6') |
| 266 | lab_config = config_reader.LabConfig(self.config) |
| 267 | self.assertEqual(lab_config.get_android_board_list(), |
| 268 | set(['abox_edge', 'android-angler', 'angler'])) |
| 269 | |
| 270 | def testGetInvalidAndroidBoardListEntry(self): |
| 271 | """Ensure ValueError is raised if no valid board list entry.""" |
| 272 | self.config.set(config_reader.ANDROID_BOARD, 'invalid_board_list', |
| 273 | 'abox_edge,android-angler-1,angler-6') |
| 274 | lab_config = config_reader.LabConfig(self.config) |
| 275 | self.assertRaises(ValueError, lab_config.get_android_board_list) |
| 276 | |
| 277 | def testGetEmptyAndroidBoardListEntry(self): |
| 278 | """Ensure ValueError is raised if no android board list is found.""" |
| 279 | lab_config = config_reader.LabConfig(self.config) |
| 280 | self.assertRaises(ValueError, lab_config.get_android_board_list) |
| 281 | |
| 282 | def testGetFirmwareROBuildList(self): |
| 283 | """Ensure firmware ro build can be successfully found.""" |
| 284 | self.config.set(config_reader.RELEASED_RO_BUILDS, 'link', 'firmware') |
| 285 | lab_config = config_reader.LabConfig(self.config) |
| 286 | self.assertEqual(lab_config.get_firmware_ro_build_list('link'), |
| 287 | 'firmware') |
| 288 | |
| 289 | def testGetEmptyFirmwareROBuildList(self): |
| 290 | """Ensure ValueError is raised if no firmware ro build is found.""" |
| 291 | lab_config = config_reader.LabConfig(self.config) |
| 292 | self.assertRaises(ValueError, |
| 293 | lab_config.get_firmware_ro_build_list, 'link') |
| 294 | |
| 295 | |
| 296 | if __name__ == '__main__': |
| 297 | unittest.main() |