blob: f010e41bce9e50af2c3ba80ad48f8899906352c5 [file] [log] [blame]
Xixuan Wu0c76d5b2017-08-30 16:40:17 -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 task unittests."""
Xixuan Wu5ff0fac2019-01-07 10:06:35 -08006# pylint: disable=g-missing-super-call
Xixuan Wu0c76d5b2017-08-30 16:40:17 -07007
Xinan Lindf0698a2020-02-05 22:38:11 -08008import json
Xixuan Wu0c76d5b2017-08-30 16:40:17 -07009import re
10import unittest
11
Xixuan Wu5451a662017-10-17 10:57:40 -070012import build_lib
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070013import config_reader
14import mock
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070015import task
Xixuan Wu51bb7102019-03-18 14:51:44 -070016import task_config_reader
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070017import tot_manager
18
Xinan Lindf0698a2020-02-05 22:38:11 -080019from chromite.api.gen.test_platform.suite_scheduler import analytics_pb2
20from chromite.api.gen.chromiumos import branch_pb2
21
22from google.protobuf import json_format
23
24FAKE_UUID = 'c78e0bf3-4142-11ea-bc66-88e9fe4c5349'
25
26
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070027class FakeTotMilestoneManager(tot_manager.TotMilestoneManager):
28 """Mock class for tot_manager.TotMilestoneManager."""
29
30 def __init__(self, is_sanity):
31 self.is_sanity = is_sanity
32 self.storage_client = None
33 self.tot = self._tot_milestone()
34
35
Xixuan Wu8d2f2862018-08-28 16:48:04 -070036class FakeLabConfig(object):
Xixuan Wuf4a4c882019-03-15 14:48:26 -070037 """Mock class for config_reader.LabConfig."""
38
39 def get_cros_model_map(self):
40 return {'coral': ['robo', 'nasher', 'lava']}
41
42
Xinan Lindf0698a2020-02-05 22:38:11 -080043class FakeBigqueryRestClient(object):
44
45 def __init__(self, rest_client, project=None, dataset=None, table=None):
46 """Initialize the mock class."""
47 self.table = table
48 self.rows = []
49
50 def insert(self, rows):
51 self.rows = rows
52 return True
53
54
Xixuan Wu5451a662017-10-17 10:57:40 -070055class TaskBaseTestCase(unittest.TestCase):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070056
57 BOARD = 'fake_board'
Xixuan Wu8d2f2862018-08-28 16:48:04 -070058 UNIBUILD_BOARD = 'coral'
Po-Hsien Wang6d589732018-05-15 17:19:34 -070059 EXCLUDE_BOARD = 'exclude_fake_board'
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070060 NAME = 'fake_name'
61 SUITE = 'fake_suite'
62 POOL = 'fake_pool'
63 PLATFORM = '6182.0.0-rc2'
64 MILESTONE = '30'
65 NUM = 1
66 PRIORITY = 50
67 TIMEOUT = 600
68
69 def setUp(self):
70 tot_patcher = mock.patch('tot_manager.TotMilestoneManager')
71 self._mock_tot = tot_patcher.start()
72 self.addCleanup(tot_patcher.stop)
73 # Can't pass in False since storage_client is not mocked.
74 self._mock_tot.return_value = FakeTotMilestoneManager(True)
Xinan Lindf0698a2020-02-05 22:38:11 -080075
76 _mock_bq_client = mock.patch('rest_client.BigqueryRestClient')
77 mock_bq_client = _mock_bq_client.start()
78 self.addCleanup(_mock_bq_client.stop)
79 self.mock_bq_client = FakeBigqueryRestClient(
80 None, project='proj', dataset='dataset', table='foo')
81 mock_bq_client.return_value = self.mock_bq_client
82
Xixuan Wu51bb7102019-03-18 14:51:44 -070083 self.task = task.Task(task_config_reader.TaskInfo(
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070084 name=self.NAME,
85 suite=self.SUITE,
86 branch_specs=[],
87 pool=self.POOL,
88 num=self.NUM,
Xixuan Wu8d2f2862018-08-28 16:48:04 -070089 boards=','.join([self.BOARD, self.UNIBUILD_BOARD]),
Po-Hsien Wang6d589732018-05-15 17:19:34 -070090 exclude_boards=self.EXCLUDE_BOARD,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070091 priority=self.PRIORITY,
92 timeout=self.TIMEOUT))
93
Xixuan Wuf4a4c882019-03-15 14:48:26 -070094 self._empty_configs = config_reader.Configs(
Xinan Lin576022d2020-01-21 18:12:47 -080095 lab_config=config_reader.LabConfig(None))
Xixuan Wuf4a4c882019-03-15 14:48:26 -070096 self._fake_configs = config_reader.Configs(
Xinan Lin576022d2020-01-21 18:12:47 -080097 lab_config=FakeLabConfig())
Xixuan Wuf4a4c882019-03-15 14:48:26 -070098
Xinan Lin028f9582019-12-11 10:55:33 -080099 self.firmware_dict = {
100 ('cros', 'fake_board'): ('fake_board-release/R30-6182.0.0-rc2'),
101 ('firmware', 'fake_board'): ('firmware-fake_board-12345.67.'
102 'A-firmwarebranch/RFoo-1.0.0-b1234567'
103 '/fake_board')
104 }
105
Xixuan Wu5451a662017-10-17 10:57:40 -0700106
107class TaskTestCase(TaskBaseTestCase):
108
109 def setUp(self):
110 super(TaskTestCase, self).setUp()
111
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700112 mock_push = mock.patch('task.Task._push_suite')
113 self._mock_push = mock_push.start()
114 self.addCleanup(mock_push.stop)
115
116 def testSetSpecCompareInfoEqual(self):
117 """Test compare info setting for specs that equals to a milestone."""
118 self.task.branch_specs = re.split(r'\s*,\s*', '==tot-2')
119 self.task._set_spec_compare_info()
120 self.assertTrue(self.task._version_equal_constraint)
121 self.assertFalse(self.task._version_gte_constraint)
122 self.assertFalse(self.task._version_lte_constraint)
123 self.assertEqual(self.task._bare_branches, [])
124
125 def testSetSpecCompareInfoLess(self):
126 """Test compare info setting for specs that is less than a milestone."""
127 self.task.branch_specs = re.split(r'\s*,\s*', '<=tot')
128 self.task._set_spec_compare_info()
129 self.assertFalse(self.task._version_equal_constraint)
130 self.assertFalse(self.task._version_gte_constraint)
131 self.assertTrue(self.task._version_lte_constraint)
132 self.assertEqual(self.task._bare_branches, [])
133
134 def testSetSpecCompareInfoGreater(self):
135 """Test compare info setting for specs that is greater than a milestone."""
136 self.task.branch_specs = re.split(r'\s*,\s*', '>=tot-2')
137 self.task._set_spec_compare_info()
138 self.assertFalse(self.task._version_equal_constraint)
139 self.assertTrue(self.task._version_gte_constraint)
140 self.assertFalse(self.task._version_lte_constraint)
141 self.assertEqual(self.task._bare_branches, [])
142
143 def testFitsSpecEqual(self):
144 """Test milestone check for specs that equals to a milestone."""
145 self.task.branch_specs = re.split(r'\s*,\s*', '==tot-1')
146 self.task._set_spec_compare_info()
147 self.assertFalse(self.task._fits_spec('40'))
148 self.assertTrue(self.task._fits_spec('39'))
149 self.assertFalse(self.task._fits_spec('38'))
150
151 def testFitsSpecLess(self):
152 """Test milestone check for specs that is less than a milestone."""
153 self.task.branch_specs = re.split(r'\s*,\s*', '<=tot-1')
154 self.task._set_spec_compare_info()
155 self.assertFalse(self.task._fits_spec('40'))
156 self.assertTrue(self.task._fits_spec('39'))
157 self.assertTrue(self.task._fits_spec('38'))
158
159 def testFitsSpecGreater(self):
160 """Test milestone check for specs that is greater than a milestone."""
161 self.task.branch_specs = re.split(r'\s*,\s*', '>=tot-2')
162 self.task._set_spec_compare_info()
163 self.assertTrue(self.task._fits_spec('39'))
164 self.assertTrue(self.task._fits_spec('38'))
165 self.assertFalse(self.task._fits_spec('37'))
166
167 def testGetFirmwareFromLabConfig(self):
168 """Test get firmware from lab config successfully."""
169 with mock.patch('config_reader.LabConfig.get_firmware_ro_build_list',
170 return_value='build1,build2'):
171 firmware = self.task._get_firmware_build(
Xinan Lin028f9582019-12-11 10:55:33 -0800172 'released_ro_2', self.BOARD, self.firmware_dict,
173 config_reader.LabConfig(None))
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700174 self.assertEqual(firmware, 'build2')
175
176 def testGetFirmwareFromLabConfigOutofIndex(self):
177 """Test get firmware from lab config when firmware index is invalid."""
178 with mock.patch('config_reader.LabConfig.get_firmware_ro_build_list',
179 return_value='build1,build2'):
180 self.assertRaises(ValueError,
181 self.task._get_latest_firmware_build_from_lab_config,
182 'released_ro_3',
183 self.BOARD,
184 config_reader.LabConfig(None))
185 self.assertIsNone(self.task._get_firmware_build(
Xinan Lin028f9582019-12-11 10:55:33 -0800186 'released_ro_3', self.BOARD, self.firmware_dict,
187 config_reader.LabConfig(None)))
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700188
Xinan Lin028f9582019-12-11 10:55:33 -0800189 def testGetFirmwareSuccessfully(self):
190 """Test get firmware from firmware_dict successfully."""
Xinan Lin39dcca82019-07-26 18:55:51 -0700191
192 firmware = self.task._get_firmware_build(
Xinan Lin028f9582019-12-11 10:55:33 -0800193 'cros', self.BOARD, self.firmware_dict, None)
Xinan Lin39dcca82019-07-26 18:55:51 -0700194 self.assertEqual(
195 firmware,
196 '{0}-release/R{1}-{2}'.format(self.BOARD,
197 self.MILESTONE,
198 self.PLATFORM))
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700199 firmware = self.task._get_firmware_build(
Xinan Lin028f9582019-12-11 10:55:33 -0800200 'firmware', self.BOARD, self.firmware_dict, None)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700201 self.assertEqual(
202 firmware,
Xinan Lin39dcca82019-07-26 18:55:51 -0700203 'firmware-{0}-12345.67.A-firmwarebranch/'
204 'RFoo-1.0.0-b1234567/{0}'.format(self.BOARD))
205
Xinan Lin028f9582019-12-11 10:55:33 -0800206 def testGetNonExistentBoard(self):
207 """Test get firmware for non-existent board from firmware_dict."""
208 self.assertIsNone(self.task._get_firmware_build(
209 'firmware', 'non-existent', self.firmware_dict, None))
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700210
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700211 def testScheduleCrosSuccessfully(self):
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700212 """test schedule cros builds successfully."""
213 branch_builds = {(self.BOARD, None, 'release', '56'): '0000.00.00'}
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700214 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800215 self.firmware_dict,
216 self._fake_configs)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700217 self.assertEqual(self._mock_push.call_count, 1)
218
219 def testScheduleCrosNonvalidBoard(self):
220 """Test schedule no cros builds due to non-allowed board."""
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700221 branch_builds = {('%s_2' % self.BOARD, None, 'release', '56'): '0000.00.00'}
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700222 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800223 self.firmware_dict,
224 self._empty_configs)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700225 self.assertEqual(self._mock_push.call_count, 0)
226
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700227 def testScheduleCrosExcludeBoard(self):
228 """Test schedule no cros builds due to board is excluded."""
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700229 branch_builds = {(self.EXCLUDE_BOARD, None, 'release', '56'): '0000.00.00'}
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700230 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800231 self.firmware_dict,
232 self._empty_configs)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700233 self.assertEqual(self._mock_push.call_count, 0)
234
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700235 def testScheduleCrosSuccessfullyWithSpecifiedModel(self):
236 """Test schedule unibuild with specific model."""
237 self.task.board = self.UNIBUILD_BOARD
238 branch_builds = {(self.UNIBUILD_BOARD, 'robo', 'release', '56'):
239 '0000.00.00',
240 (self.UNIBUILD_BOARD, 'lava', 'release', '56'):
241 '0000.00.00'}
242 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800243 self.firmware_dict,
244 self._fake_configs)
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700245 self.assertEqual(self._mock_push.call_count, 2)
246
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700247 def testScheduleCrosNonValidSpec(self):
248 """Test schedule no cros builds due to non-allowed branch milestone."""
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700249 branch_builds = {(self.BOARD, None, 'release', '56'): '0000.00.00'}
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700250 # Only run tasks whose milestone = tot (R40)
251 self.task.branch_specs = re.split(r'\s*,\s*', '==tot')
252 self.task._set_spec_compare_info()
253 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800254 self.firmware_dict,
255 self._empty_configs)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700256 self.assertEqual(self._mock_push.call_count, 0)
257
258 def testScheduleCrosSuccessfullyWithValidFirmware(self):
259 """Test schedule cros builds successfully with valid firmware."""
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700260 branch_builds = {(self.BOARD, None, 'release', '56'): '0000.00.00'}
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700261 self.task.firmware_ro_build_spec = 'firmware'
262 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800263 self.firmware_dict,
264 self._fake_configs)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700265 self.assertEqual(self._mock_push.call_count, 1)
266
267 def testScheduleCrosWithNonValidFirmware(self):
268 """Test schedule no cros builds due to non-existent firmware."""
Xinan Lin028f9582019-12-11 10:55:33 -0800269 branch_builds = {('foo-board', None, 'release', '56'): '0000.00.00'}
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700270 self.task.firmware_ro_build_spec = 'firmware'
271 self.task._schedule_cros_builds(branch_builds,
Xinan Lin028f9582019-12-11 10:55:33 -0800272 self.firmware_dict,
273 self._empty_configs)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700274 self.assertEqual(self._mock_push.call_count, 0)
275
276 def testScheduleLaunchControlWithFullBranches(self):
277 """Test schedule all launch control builds successfully."""
278 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
279 'git_nyc-mr1-release/shamu-userdebug/3783920']}
280 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
281 self.task.launch_control_branches = [
282 t.lstrip() for t in lc_branches.split(',')]
283 self.task._schedule_launch_control_builds(lc_builds)
284 self.assertEqual(self._mock_push.call_count, 2)
285
286 def testScheduleLaunchControlWithPartlyBranches(self):
287 """Test schedule part of launch control builds due to branch check."""
288 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
289 'git_nyc-mr1-release/shamu-userdebug/3783920']}
290 lc_branches = 'git_nyc-mr1-release'
291 self.task.launch_control_branches = [
292 t.lstrip() for t in lc_branches.split(',')]
293 self.task._schedule_launch_control_builds(lc_builds)
294 self.assertEqual(self._mock_push.call_count, 1)
295
296 def testScheduleLaunchControlWithNoBranches(self):
297 """Test schedule none of launch control builds due to branch check."""
298 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
299 'git_nyc-mr1-release/shamu-userdebug/3783920']}
300 self.task.launch_control_branches = []
301 self.task._schedule_launch_control_builds(lc_builds)
302 self.assertEqual(self._mock_push.call_count, 0)
303
304 def testScheduleLaunchControlNonvalidBoard(self):
305 """Test schedule none of launch control builds due to board check."""
306 lc_builds = {'%s_2' % self.BOARD:
307 ['git_nyc-mr2-release/shamu-userdebug/3844975',
308 'git_nyc-mr1-release/shamu-userdebug/3783920']}
309 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
310 self.task.launch_control_branches = [
311 t.lstrip() for t in lc_branches.split(',')]
312 self.task._schedule_launch_control_builds(lc_builds)
313 self.assertEqual(self._mock_push.call_count, 0)
Xixuan Wu5451a662017-10-17 10:57:40 -0700314
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700315 def testScheduleLaunchControlExcludeBoard(self):
316 """Test schedule none of launch control builds due to board check."""
317 lc_builds = {self.EXCLUDE_BOARD:
318 ['git_nyc-mr2-release/shamu-userdebug/3844975',
319 'git_nyc-mr1-release/shamu-userdebug/3783920']}
320 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
321 self.task.launch_control_branches = [
322 t.lstrip() for t in lc_branches.split(',')]
323 self.task._schedule_launch_control_builds(lc_builds)
324 self.assertEqual(self._mock_push.call_count, 0)
325
Xixuan Wu5451a662017-10-17 10:57:40 -0700326
327class TaskPushTestCase(TaskBaseTestCase):
328
329 def setUp(self):
330 super(TaskPushTestCase, self).setUp()
331 mock_push = mock.patch('task_executor.push')
332 self._mock_push = mock_push.start()
333 self.addCleanup(mock_push.stop)
334
335 def testScheduleCrOSIsPushSuccessfully(self):
336 """Test IS_PUSHED is changed if some CrOS suites are scheduled."""
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700337 branch_builds = {(self.BOARD, None, 'release', '56'): '0000.00.00'}
Xixuan Wu5451a662017-10-17 10:57:40 -0700338 self.task.os_type = build_lib.OS_TYPE_CROS
339 self.assertTrue(self.task.schedule(
Xinan Lin028f9582019-12-11 10:55:33 -0800340 [], (branch_builds, []), self.firmware_dict, self._fake_configs))
Xixuan Wu5451a662017-10-17 10:57:40 -0700341
342 def testScheduleLaunchControlIsPushSuccessfully(self):
343 """Test IS_PUSHED is changed if some launch control suites are scheduled."""
344 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
345 'git_nyc-mr1-release/shamu-userdebug/3783920']}
346 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
347 self.task.launch_control_branches = [
348 t.lstrip() for t in lc_branches.split(',')]
349 self.task.os_type = build_lib.OS_TYPES_LAUNCH_CONTROL
350 self.assertTrue(self.task.schedule(
Xinan Lin028f9582019-12-11 10:55:33 -0800351 lc_builds, ([], []), self.firmware_dict,
352 self._empty_configs))
Xixuan Wu5451a662017-10-17 10:57:40 -0700353
354 def testScheduleCrosIsPushInvalidBoard(self):
355 """Test schedule no cros builds due to non-allowed board."""
Craig Bergstrom58263d32018-04-26 14:11:35 -0600356 branch_builds = (
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700357 {('%s_2' % self.BOARD, None, 'release', '56'): '0000.00.00'}, {},
Craig Bergstrom58263d32018-04-26 14:11:35 -0600358 )
Xixuan Wu5451a662017-10-17 10:57:40 -0700359 self.task.os_type = build_lib.OS_TYPE_CROS
360 self.assertFalse(self.task.schedule(
Xinan Lin028f9582019-12-11 10:55:33 -0800361 [], branch_builds, self.firmware_dict, self._empty_configs))
Xixuan Wu5451a662017-10-17 10:57:40 -0700362
363 def testScheduleLaunchControlIsPushInvalidBoard(self):
364 """Test schedule none of launch control builds due to board check."""
365 lc_builds = {'%s_2' % self.BOARD:
366 ['git_nyc-mr2-release/shamu-userdebug/3844975',
367 'git_nyc-mr1-release/shamu-userdebug/3783920']}
368 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
369 self.task.launch_control_branches = [
370 t.lstrip() for t in lc_branches.split(',')]
371 self.task.os_type = build_lib.OS_TYPES_LAUNCH_CONTROL
372 self.task._schedule_launch_control_builds(lc_builds)
373 self.assertFalse(self.task.schedule(
Xinan Lin028f9582019-12-11 10:55:33 -0800374 lc_builds, ([], []), self.firmware_dict,
375 self._empty_configs))
Xinan Lindf0698a2020-02-05 22:38:11 -0800376
377
378class TaskJobSectionTestCase(TaskBaseTestCase):
379
380 def setUp(self):
381 super(TaskJobSectionTestCase, self).setUp()
382 mock_push = mock.patch('task_executor.push')
383 self._mock_push = mock_push.start()
384 self.addCleanup(mock_push.stop)
385
386 def testJobSectionName(self):
387 """Test the job section name if recorded."""
388 self.task.schedule(
389 [], ([], []), self.firmware_dict, self._fake_configs)
390 self.assertEqual(self._mock_push.call_count, 0)
391 job_sec = json_format.Parse(
392 json.dumps(self.mock_bq_client.rows[0]['json']),
393 analytics_pb2.ScheduleJobSection())
394 self.assertEqual(job_sec.job_name, 'fake_name')
395
396 def testAddBoard(self):
397 """Test the configured board is recorded."""
398 new_task = task.Task(task_config_reader.TaskInfo(
399 name=self.NAME,
400 suite=self.SUITE,
401 branch_specs=[],
402 boards='coral'))
403 new_task.schedule(
404 [], ([], []), self.firmware_dict, self._fake_configs)
405 job_sec = json_format.Parse(
406 json.dumps(self.mock_bq_client.rows[0]['json']),
407 analytics_pb2.ScheduleJobSection())
408 self.assertEqual(len(job_sec.build_targets), 1)
409 self.assertEqual(job_sec.build_targets[0].name, 'coral')
410
411 def testAddModel(self):
412 """Test the configured model is recorded."""
413 new_task = task.Task(task_config_reader.TaskInfo(
414 name=self.NAME,
415 suite=self.SUITE,
416 branch_specs=[],
417 boards='coral',
418 exclude_models='coral_robo,coral_nasher'))
419 new_task.schedule(
420 [], ([], []), self.firmware_dict, self._fake_configs)
421 job_sec = json_format.Parse(
422 json.dumps(self.mock_bq_client.rows[0]['json']),
423 analytics_pb2.ScheduleJobSection())
424 # lava is the only coral model that was not excluded.
425 self.assertEqual(len(job_sec.models), 1)
426 self.assertEqual(job_sec.models[0].value, 'lava')
427
428 def testAddMatchedBuild(self):
429 """Test the matched build is recorded."""
430 branch_builds = {('coral', '', 'release', '40'):
431 '0000.00.00',
432 ('hatch', '', 'release', '37'):
433 '0000.00.00'}
434 new_task = task.Task(task_config_reader.TaskInfo(
435 name=self.NAME,
436 suite=self.SUITE,
437 branch_specs=['>=tot-2'],
438 boards='coral,hatch',
439 os_type=build_lib.OS_TYPE_CROS))
440 new_task.schedule(
441 [], (branch_builds, []), self.firmware_dict, self._fake_configs)
442 job_sec = json_format.Parse(
443 json.dumps(self.mock_bq_client.rows[0]['json']),
444 analytics_pb2.ScheduleJobSection())
445 self.assertEqual(len(job_sec.matched_builds), 1)
446 build = job_sec.matched_builds[0].release_build
447 # hatch should not be recorded as its build is too old.
448 self.assertEqual(build.build_target.name, 'coral')
449 self.assertEqual(build.milestone, 40)
450 self.assertEqual(build.chrome_os_version, '0000.00.00')
451 self.assertEqual(build.type, branch_pb2.Branch.RELEASE)
452
453 def testAddMatchedRelaxBuild(self):
454 """Test the matched relax build is recorded."""
455 relax_builds = {('coral', '', 'release', '40'):
456 '0000.00.00',
457 ('hatch', '', 'release', '37'):
458 '0000.00.00'}
459 new_task = task.Task(task_config_reader.TaskInfo(
460 name=self.NAME,
461 suite=self.SUITE,
462 branch_specs=['>=tot-2'],
463 boards='coral,hatch',
464 only_hwtest_sanity_required=True,
465 os_type=build_lib.OS_TYPE_CROS))
466 new_task.schedule(
467 [], ([], relax_builds), self.firmware_dict, self._fake_configs)
468 job_sec = json_format.Parse(
469 json.dumps(self.mock_bq_client.rows[0]['json']),
470 analytics_pb2.ScheduleJobSection())
471 self.assertEqual(len(job_sec.matched_builds), 1)
472 build = job_sec.matched_builds[0].relax_build
473 # hatch should not be recorded as its build is too old.
474 self.assertEqual(build.build_target.name, 'coral')
475 self.assertEqual(build.milestone, 40)
476 self.assertEqual(build.chrome_os_version, '0000.00.00')
477 self.assertEqual(build.type, branch_pb2.Branch.RELEASE)
478
479 def testAddMatchedFirmwareBuild(self):
480 """Test the matched firmware build is recorded."""
481 branch_builds = {('fake_board', '', 'release', '40'):
482 '0000.00.00'}
483 new_task = task.Task(task_config_reader.TaskInfo(
484 name=self.NAME,
485 suite=self.SUITE,
486 branch_specs=['>=tot-2'],
487 boards='fake_board',
488 firmware_rw_build_spec='firmware',
489 os_type=build_lib.OS_TYPE_CROS))
490 new_task.schedule(
491 [], (branch_builds, []), self.firmware_dict, self._fake_configs)
492 job_sec = json_format.Parse(
493 json.dumps(self.mock_bq_client.rows[0]['json']),
494 analytics_pb2.ScheduleJobSection())
495 self.assertEqual(len(job_sec.matched_builds), 2)
496 build = job_sec.matched_builds[1].firmware_rw_build
497 self.assertEqual(build.build_target.name, 'fake_board')
498 self.assertEqual(build.type, branch_pb2.Branch.FIRMWARE)
499 self.assertEqual(build.artifact.path,
500 self.firmware_dict['firmware', 'fake_board'])
501
502 def testScheduleJobSuccessfully(self):
503 """Test the scheduled job is recorded."""
504 branch_builds = {('coral', 'lava', 'release', '40'):
505 '0000.00.00'}
506 new_task = task.Task(task_config_reader.TaskInfo(
507 name=self.NAME,
508 suite=self.SUITE,
509 branch_specs=['>=tot-2'],
510 boards='coral',
511 os_type=build_lib.OS_TYPE_CROS))
512 with mock.patch('uuid.uuid1', return_value=FAKE_UUID):
513 new_task.schedule(
514 [], (branch_builds, []), self.firmware_dict, self._fake_configs)
515 job_sec = json_format.Parse(
516 json.dumps(self.mock_bq_client.rows[0]['json']),
517 analytics_pb2.ScheduleJobSection())
518 self.assertEqual(len(job_sec.schedule_jobs), 1)
519 job = job_sec.schedule_jobs[0]
520 self.assertEqual(job.build_target.name, 'coral')
521 self.assertEqual(job.model.value, 'lava')
522 self.assertEqual(job.queued_task_id, FAKE_UUID)
523
524 def testScheduleJobFailedforFirmwareRO(self):
525 """Test the dropped job due to firmware absence is recorded."""
526 branch_builds = {('coral', 'lava', 'release', '40'):
527 '0000.00.00'}
528 new_task = task.Task(task_config_reader.TaskInfo(
529 name=self.NAME,
530 suite=self.SUITE,
531 branch_specs=['>=tot-2'],
532 boards='coral',
533 firmware_ro_build_spec='firmware',
534 os_type=build_lib.OS_TYPE_CROS))
535 new_task.schedule(
536 [], (branch_builds, []), {}, self._fake_configs)
537 job_sec = json_format.Parse(
538 json.dumps(self.mock_bq_client.rows[0]['json']),
539 analytics_pb2.ScheduleJobSection())
540 self.assertEqual(len(job_sec.schedule_jobs), 1)
541 job = job_sec.schedule_jobs[0]
542 self.assertEqual(job.build_target.name, 'coral')
543 self.assertEqual(job.model.value, 'lava')
544 self.assertIn('No RO firmware ro build to run', job.justification)
545
546 def testScheduleJobFailedforBranchNotMaching(self):
547 """Test the dropped job due to branch spec is recorded."""
548 branch_builds = {('coral', 'lava', 'release', '38'):
549 '0000.00.00'}
550 new_task = task.Task(task_config_reader.TaskInfo(
551 name=self.NAME,
552 suite=self.SUITE,
553 branch_specs=['>=tot-1'],
554 boards='coral',
555 os_type=build_lib.OS_TYPE_CROS))
556 new_task.schedule(
557 [], (branch_builds, []), {}, self._fake_configs)
558 job_sec = json_format.Parse(
559 json.dumps(self.mock_bq_client.rows[0]['json']),
560 analytics_pb2.ScheduleJobSection())
561 self.assertEqual(len(job_sec.schedule_jobs), 1)
562 job = job_sec.schedule_jobs[0]
563 self.assertEqual(job.build_target.name, 'coral')
564 self.assertEqual(job.model.value, 'lava')
565 self.assertIn('branch_build spec', job.justification)
566
567 def testScheduleJobFailedforAnyModel(self):
568 """Test the dropped job due to any_model is recorded."""
569 branch_builds = {('coral', None, 'release', '38'):
570 '0000.00.00'}
571 new_task = task.Task(task_config_reader.TaskInfo(
572 name=self.NAME,
573 suite=self.SUITE,
574 branch_specs=['>=tot-2'],
575 boards='coral',
576 any_model=True,
577 exclude_models='coral_nasher',
578 os_type=build_lib.OS_TYPE_CROS))
579 new_task.schedule(
580 [], (branch_builds, []), {}, self._fake_configs)
581 job_sec = json_format.Parse(
582 json.dumps(self.mock_bq_client.rows[0]['json']),
583 analytics_pb2.ScheduleJobSection())
584 jobs = job_sec.schedule_jobs
Xinan Lin0673a182020-04-14 15:09:35 -0700585 # 'nasher' is excluded, hence there should be two jobs for the rest models
586 # 'robo', 'lava'.
587 self.assertEqual(2, len(jobs))
588 # The first job should be scheduled with empty model, as any_model is True.
589 self.assertEqual(jobs[0].build_target.name, 'coral')
590 self.assertEqual(jobs[0].model.value, '')
591 # The second job should be skipped and the justification is recorded.
Xinan Lindf0698a2020-02-05 22:38:11 -0800592 self.assertEqual(jobs[1].build_target.name, 'coral')
593 self.assertEqual(jobs[1].model.value, 'lava')
594 self.assertIn('Skip model lava as any_model enabled', jobs[1].justification)