blob: 469a7c212a92a77eac6a64eeee369270256c14df [file] [log] [blame]
Xixuan Wuabbaa4c2017-08-23 17:31:49 -07001# 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."""
Xixuan Wu5ff0fac2019-01-07 10:06:35 -08006# pylint: disable=g-missing-super-call
Xixuan Wuabbaa4c2017-08-23 17:31:49 -07007
8import unittest
9
10import config_reader
11import constants
12import mock
Xixuan Wu7e30c9d2017-09-05 18:46:00 -070013import tot_manager
14
15
16class FakeTotMilestoneManager(tot_manager.TotMilestoneManager):
17
18 def __init__(self, is_sanity):
19 self.is_sanity = is_sanity
20 self.storage_client = None
21 self.tot = self._tot_milestone()
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070022
23
24class BaseTaskConfigReaderTestCase(unittest.TestCase):
25
26 _EVENT_TYPE = 'nightly'
27 _PRIORITY = config_reader.EVENT_CLASSES[_EVENT_TYPE].PRIORITY
28 _TIMEOUT = config_reader.EVENT_CLASSES[_EVENT_TYPE].TIMEOUT
29 _TASK_NAME = 'fake_task'
30 _SUITE = 'fake_suite'
31 _BRANCH_SPEC = 'tot-1'
32 _POOL = 'bvt'
33 _NUM = 2
34 _BOARD = 'link'
35
36 def setUp(self):
37 self.config = config_reader.ConfigReader(None)
38 self.config.add_section(self._TASK_NAME)
39 self.config.set(self._TASK_NAME, 'suite', self._SUITE)
40 self.config.set(self._TASK_NAME, 'branch_specs', self._BRANCH_SPEC)
41 self.config.set(self._TASK_NAME, 'run_on', self._EVENT_TYPE)
42 self.config.set(self._TASK_NAME, 'pool', self._POOL)
43 self.config.set(self._TASK_NAME, 'num', '%d' % self._NUM)
44 self.config.set(self._TASK_NAME, 'boards', self._BOARD)
45
46 tot_patcher = mock.patch('tot_manager.TotMilestoneManager')
47 self._tot = tot_patcher.start()
Xixuan Wu7e30c9d2017-09-05 18:46:00 -070048 self._tot.return_value = FakeTotMilestoneManager(True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -070049
50 board_family_patcher = mock.patch(
51 'build_lib.get_board_family_mapping_from_gs')
52 board_family_getter = board_family_patcher.start()
53 board_family_getter.return_value = {
54 'nyan': ['nyan', 'nyan_blaze', 'nyan_big'],
55 'ivybridge': ['link', 'link_freon']}
56
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070057 self.addCleanup(tot_patcher.stop)
Xixuan Wu244e0ec2018-05-23 14:49:55 -070058 self.addCleanup(board_family_patcher.stop)
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070059
60
61class TaskCreationTestCase(BaseTaskConfigReaderTestCase):
62
63 def testCreateTaskFromConfigNonexistentSection(self):
64 """Ensure a Task CANNOT be built without suite, and raise error."""
65 task_config = config_reader.TaskConfig(self.config)
66 self.assertRaises(config_reader.MalformedConfigEntryError,
67 task_config._create_task_from_config_section,
68 'non-existent section')
69
70 def testCreateTaskFromConfigNotAllowedHeader(self):
71 """Ensure a Task CANNOT be built without suite, and raise error."""
72 self.config.set(self._TASK_NAME, 'non-valid-header', 'test')
73 task_config = config_reader.TaskConfig(self.config)
74 self.assertRaises(config_reader.MalformedConfigEntryError,
75 task_config._create_task_from_config_section,
76 self._TASK_NAME)
77
78 def testGetTaskByKeyword(self):
79 """Ensure a Task can be built from a correct config."""
80 task_config = config_reader.TaskConfig(self.config)
Xixuan Wu4ac56dd2017-10-12 11:59:30 -070081 tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE)['tasks']
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070082 self.assertEqual(len(tasks), 1)
83 new_task = tasks[0]
84 self.assertEqual(new_task.name, self._TASK_NAME)
85 self.assertEqual(new_task.suite, self._SUITE)
86 self.assertEqual(new_task.branch_specs, [self._BRANCH_SPEC])
87 self.assertEqual(new_task.pool, self._POOL)
88 self.assertEqual(new_task.num, self._NUM)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070089 self.assertEqual(new_task.boards,
90 [t.lstrip() for t in self._BOARD.split(',')])
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070091 self.assertEqual(new_task.priority, self._PRIORITY)
92 self.assertEqual(new_task.timeout, self._TIMEOUT)
93
Xixuan Wuabbaa4c2017-08-23 17:31:49 -070094 def testGetTaskByKeywordNoRunonNoRaise(self):
95 """Ensure a Task CANNOT be built without run_on, but not raise error."""
96 self.config.remove_option(self._TASK_NAME, 'run_on')
97 task_config = config_reader.TaskConfig(self.config)
98 try:
Xixuan Wu4ac56dd2017-10-12 11:59:30 -070099 response = task_config.get_tasks_by_keyword(self._EVENT_TYPE)
100 self.assertEqual(len(response['tasks']), 0)
101 self.assertEqual(len(response['exceptions']), 1)
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700102 except config_reader.MalformedConfigEntryError:
103 self.fail('task_config should not raise error without run_on!')
104
105 def testGetTaskByKeywordNoSuiteNoRaise(self):
106 """Ensure a Task CANNOT be built without suite, but not raise error.
107
108 This is to ensure a malformed task won't affect other tasks' reading.
109 """
110 self.config.remove_option(self._TASK_NAME, 'suite')
111 task_config = config_reader.TaskConfig(self.config)
112 try:
Xixuan Wu4ac56dd2017-10-12 11:59:30 -0700113 response = task_config.get_tasks_by_keyword(self._EVENT_TYPE)
114 self.assertEqual(len(response['tasks']), 0)
115 self.assertEqual(len(response['exceptions']), 1)
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700116 except config_reader.MalformedConfigEntry:
117 self.fail('task_config should not raise error without suite!')
118
119 def testGetTaskByKeywordNoBranch(self):
120 """Ensure a Task can be built without branch_specs."""
121 self.config.remove_option(self._TASK_NAME, 'branch_specs')
122 task_config = config_reader.TaskConfig(self.config)
Xixuan Wu4ac56dd2017-10-12 11:59:30 -0700123 tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE)['tasks']
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700124 self.assertEqual(tasks[0].branch_specs, [])
125
126 def testGetTaskByKeywordNoNum(self):
127 """Ensure a Task can be built without num."""
128 self.config.remove_option(self._TASK_NAME, 'num')
129 task_config = config_reader.TaskConfig(self.config)
Xixuan Wu4ac56dd2017-10-12 11:59:30 -0700130 tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE)['tasks']
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700131 self.assertIsNone(tasks[0].num)
132
133 def testSetPriority(self):
134 """Ensure priority can be set by user."""
135 priority = constants.Priorities.DEFAULT
136 self.config.set(self._TASK_NAME, 'priority', str(priority))
137 task_config = config_reader.TaskConfig(self.config)
Xixuan Wu4ac56dd2017-10-12 11:59:30 -0700138 tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE)['tasks']
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700139 self.assertEqual(tasks[0].priority, priority)
140
141 def testSetTimeout(self):
142 """Ensure timeout can be set by user."""
143 timeout = 1000
144 self.config.set(self._TASK_NAME, 'timeout', str(timeout))
145 task_config = config_reader.TaskConfig(self.config)
Xixuan Wu4ac56dd2017-10-12 11:59:30 -0700146 tasks = task_config.get_tasks_by_keyword(self._EVENT_TYPE)['tasks']
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700147 self.assertEqual(tasks[0].timeout, timeout)
148
149
150class TaskInfoCheckTestCase(BaseTaskConfigReaderTestCase):
151
152 def testNonIntNum(self):
153 """Ensure a Task's num is a Integer."""
154 self.config.set(self._TASK_NAME, 'num', 'non_int')
155 task_config = config_reader.TaskConfig(self.config)
156 self.assertRaises(config_reader.MalformedConfigEntryError,
157 task_config._read_task_section,
158 self._TASK_NAME)
159
160 def testNonIntHour(self):
161 """Ensure a Task's hour is a Integer."""
162 self.config.set(self._TASK_NAME, 'hour', 'non_int')
163 task_config = config_reader.TaskConfig(self.config)
164 self.assertRaises(config_reader.MalformedConfigEntryError,
165 task_config._read_task_section,
166 self._TASK_NAME)
167
168 def testNonIntDay(self):
169 """Ensure a Task's hour is a Integer."""
170 self.config.set(self._TASK_NAME, 'day', 'non_int')
171 task_config = config_reader.TaskConfig(self.config)
172 self.assertRaises(config_reader.MalformedConfigEntryError,
173 task_config._read_task_section,
174 self._TASK_NAME)
175
176 def testNoSuite(self):
177 """Ensure a Task's suite exists."""
178 self.config.remove_option(self._TASK_NAME, 'suite')
179 task_config = config_reader.TaskConfig(self.config)
180 task_info = task_config._read_task_section(self._TASK_NAME)
181 self.assertRaises(config_reader.MalformedConfigEntryError,
182 task_config._validate_task_section,
183 task_info)
184
185 def testInvalidIntHour(self):
186 """Ensure a Task's hour is in 0~23."""
187 self.config.set(self._TASK_NAME, 'hour', '24')
188 task_config = config_reader.TaskConfig(self.config)
189 task_info = task_config._read_task_section(self._TASK_NAME)
190 self.assertRaises(config_reader.MalformedConfigEntryError,
191 task_config._validate_task_section,
192 task_info)
193
194 def testNoHourForNonNightlyEvent(self):
195 """Ensure a non-nightly Task cannot specify hour."""
196 self.config.set(self._TASK_NAME, 'hour', '10')
197 self.config.set(self._TASK_NAME, 'run_on', 'new_build')
198 task_config = config_reader.TaskConfig(self.config)
199 task_info = task_config._read_task_section(self._TASK_NAME)
200 self.assertRaises(config_reader.MalformedConfigEntryError,
201 task_config._validate_task_section,
202 task_info)
203
204 def testInvalidIntDay(self):
205 """Ensure a Task's day is in 0~6."""
206 self.config.set(self._TASK_NAME, 'day', '10')
207 self.config.set(self._TASK_NAME, 'run_on', 'weekly')
208 task_config = config_reader.TaskConfig(self.config)
209 task_info = task_config._read_task_section(self._TASK_NAME)
210 self.assertRaises(config_reader.MalformedConfigEntryError,
211 task_config._validate_task_section,
212 task_info)
213
214 def testNoDayForNonWeeklyEvent(self):
215 """Ensure a non-weekly Task cannot specify day."""
216 self.config.set(self._TASK_NAME, 'day', '1')
217 self.config.set(self._TASK_NAME, 'run_on', 'nightly')
218 task_config = config_reader.TaskConfig(self.config)
219 task_info = task_config._read_task_section(self._TASK_NAME)
220 self.assertRaises(config_reader.MalformedConfigEntryError,
221 task_config._validate_task_section,
222 task_info)
223
224 def testInValidOSType(self):
225 """Ensure a Task's os_type is valid."""
226 self.config.set(self._TASK_NAME, 'os_type', 'invalid')
227 task_config = config_reader.TaskConfig(self.config)
228 task_info = task_config._read_task_section(self._TASK_NAME)
229 self.assertRaises(config_reader.MalformedConfigEntryError,
230 task_config._check_os_type,
231 task_info)
232
233 def testNoLaunchControlForCrOS(self):
234 """Ensure a CrOS Task doesn't have launch control settings."""
235 self.config.set(self._TASK_NAME, 'os_type', 'CrOS')
236 self.config.set(self._TASK_NAME, 'branches', 'shamu-userdebug')
237 task_config = config_reader.TaskConfig(self.config)
238 task_info = task_config._read_task_section(self._TASK_NAME)
239 self.assertRaises(config_reader.MalformedConfigEntryError,
240 task_config._check_os_type,
241 task_info)
242
243 def testLaunchControlForNonCrOS(self):
244 """Ensure an android Task has launch control settings."""
245 self.config.set(self._TASK_NAME, 'os_type', 'android')
246 task_config = config_reader.TaskConfig(self.config)
247 task_info = task_config._read_task_section(self._TASK_NAME)
248 self.assertRaises(config_reader.MalformedConfigEntryError,
249 task_config._check_os_type,
250 task_info)
251
252 def testGetTestbedCount(self):
253 """Ensure testbed count can be successfully parsed."""
254 task_config = config_reader.TaskConfig(self.config)
255 self.assertEqual(task_config._get_testbed_dut_count('sharu-2'), 2)
256
257 def testNoTestbedForCrOS(self):
258 """Ensure CrOS task won't specify testbed parameters."""
259 self.config.set(self._TASK_NAME, 'boards', 'sharu-2')
260 task_config = config_reader.TaskConfig(self.config)
261 task_info = task_config._read_task_section(self._TASK_NAME)
262 self.assertRaises(config_reader.MalformedConfigEntryError,
263 task_config._check_testbed_parameter,
264 task_info)
265
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700266 def testInvalidBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700267 """Ensure to raise exception when a board family is invalid."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700268 self.config.set(self._TASK_NAME, 'board_families', 'fake_one')
269 task_config = config_reader.TaskConfig(self.config)
270 self.assertRaises(config_reader.MalformedConfigEntryError,
271 task_config._read_task_section,
272 self._TASK_NAME)
273
274 def testInvalidExcludeBoardFamilies(self):
275 """Ensure to raise exception when an exclude board family is invalid."""
276 self.config.set(self._TASK_NAME, 'exclude_board_families', 'fake_one')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700277 task_config = config_reader.TaskConfig(self.config)
278 self.assertRaises(config_reader.MalformedConfigEntryError,
279 task_config._read_task_section,
280 self._TASK_NAME)
281
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700282
283class LabReaderTestCase(unittest.TestCase):
284
285 def setUp(self):
286 self.config = config_reader.ConfigReader(None)
Xixuan Wu26d06e02017-09-20 14:50:28 -0700287 self.config.add_section(config_reader.ANDROID_SETTINGS)
Xixuan Wu6fb16272017-10-19 13:16:00 -0700288 self.config.add_section(config_reader.CROS_SETTINGS)
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700289 self.config.add_section(config_reader.RELEASED_RO_BUILDS)
290
291 def testGetAndroidBoardList(self):
292 """Ensure android board list can be correctly fetched."""
Xixuan Wu26d06e02017-09-20 14:50:28 -0700293 self.config.set(config_reader.ANDROID_SETTINGS, 'board_list',
294 '\nabox_edge,\nandroid-angler-1,\nangler-6')
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700295 lab_config = config_reader.LabConfig(self.config)
296 self.assertEqual(lab_config.get_android_board_list(),
297 set(['abox_edge', 'android-angler', 'angler']))
298
299 def testGetInvalidAndroidBoardListEntry(self):
300 """Ensure ValueError is raised if no valid board list entry."""
Xixuan Wu26d06e02017-09-20 14:50:28 -0700301 self.config.set(config_reader.ANDROID_SETTINGS, 'invalid_board_list',
302 '\nabox_edge,\nandroid-angler-1,\nangler-6')
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700303 lab_config = config_reader.LabConfig(self.config)
304 self.assertRaises(ValueError, lab_config.get_android_board_list)
305
306 def testGetEmptyAndroidBoardListEntry(self):
307 """Ensure ValueError is raised if no android board list is found."""
308 lab_config = config_reader.LabConfig(self.config)
309 self.assertRaises(ValueError, lab_config.get_android_board_list)
310
Xixuan Wu6fb16272017-10-19 13:16:00 -0700311 def testGetCrOSBoardList(self):
312 """Ensure android board list can be correctly fetched."""
313 self.config.set(config_reader.CROS_SETTINGS, 'board_list',
314 '\nlink,\nandroid-angler-1,\nangler-6')
315 self.config.set(config_reader.ANDROID_SETTINGS, 'board_list',
316 '\nandroid-angler-1,\nangler-6')
317 lab_config = config_reader.LabConfig(self.config)
318 self.assertEqual(lab_config.get_cros_board_list(),
319 set(['link']))
320
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700321 def testGetFirmwareROBuildList(self):
322 """Ensure firmware ro build can be successfully found."""
323 self.config.set(config_reader.RELEASED_RO_BUILDS, 'link', 'firmware')
324 lab_config = config_reader.LabConfig(self.config)
325 self.assertEqual(lab_config.get_firmware_ro_build_list('link'),
326 'firmware')
327
328 def testGetEmptyFirmwareROBuildList(self):
329 """Ensure ValueError is raised if no firmware ro build is found."""
330 lab_config = config_reader.LabConfig(self.config)
331 self.assertRaises(ValueError,
332 lab_config.get_firmware_ro_build_list, 'link')
333
C Shapiro7f24a002017-12-05 14:25:09 -0700334 def testGetCrOSModelMap(self):
335 """Ensure cros_model_map can be correctly fetched."""
336 self.config.set(config_reader.CROS_SETTINGS, 'model_list',
337 '\ncoral_astronaut,\ncoral_robo360')
338 lab_config = config_reader.LabConfig(self.config)
339 result = lab_config.get_cros_model_map()
340 self.assertEqual(len(result), 1)
341 self.assertEqual(result['coral'], ['astronaut', 'robo360'])
342
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700343 def testGetEmptyCrOSModelMap(self):
344 """Ensure cros_model_map can be correctly fetched."""
345 lab_config = config_reader.LabConfig(self.config)
346 self.assertEqual(lab_config.get_cros_model_map(), {})
347
348
349class MigrationReaderTestCase(unittest.TestCase):
350
351 def setUp(self):
352 self.config = config_reader.ConfigReader(None)
353 self.config.add_section(config_reader.SKYLAB_SETTINGS)
354
Xixuan Wubb74a372018-08-21 17:37:08 -0700355 def testGetSkylabBoardList(self):
356 """Ensure skylab_board_list can be correctly fetched."""
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700357 self.config.set(config_reader.SKYLAB_SETTINGS, 'board_list',
Xixuan Wubb74a372018-08-21 17:37:08 -0700358 '\nnyan_blaze,\nreef')
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700359 lab_config = config_reader.MigrationConfig(self.config)
Xixuan Wubb74a372018-08-21 17:37:08 -0700360 result = lab_config.get_skylab_board_list()
361 self.assertEqual(len(result), 2)
362 self.assertIn('nyan_blaze', result)
363 self.assertIn('reef', result)
364
Xixuan Wu446b8ad2018-08-23 11:25:43 -0700365 def testGetSkylabSuiteList(self):
366 """Ensure skylab_suite_list can be correctly fetched."""
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700367 self.config.set(config_reader.SKYLAB_SETTINGS, 'suite_list',
Xixuan Wu446b8ad2018-08-23 11:25:43 -0700368 '\nent-nightly,\nent-perbuild')
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700369 lab_config = config_reader.MigrationConfig(self.config)
Xixuan Wu446b8ad2018-08-23 11:25:43 -0700370 result = lab_config.get_skylab_suite_list()
371 self.assertEqual(len(result), 2)
372 self.assertIn('ent-nightly', result)
373 self.assertIn('ent-perbuild', result)
374
Xixuan Wu5ff0fac2019-01-07 10:06:35 -0800375 def testGetSkylabModelMap(self):
376 """Ensure skylab_board_list can be correctly fetched."""
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700377 self.config.set(config_reader.SKYLAB_SETTINGS, 'model_list',
Xixuan Wu5ff0fac2019-01-07 10:06:35 -0800378 '\ncoral_lava,\ncoral_santa')
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700379 lab_config = config_reader.MigrationConfig(self.config)
Xixuan Wu5ff0fac2019-01-07 10:06:35 -0800380 result = lab_config.get_skylab_model_map()
381 self.assertEqual(len(result), 1)
382 self.assertEqual(result['coral'], ['lava', 'santa'])
383
Xixuan Wuabbaa4c2017-08-23 17:31:49 -0700384
385if __name__ == '__main__':
386 unittest.main()