blob: 39c6386efcc1c7eaf32527fc62c2e81999b1ef74 [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."""
6
7import re
8import unittest
9
Xixuan Wu5451a662017-10-17 10:57:40 -070010import build_lib
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070011import cloud_sql_client
12import config_reader
13import mock
14import MySQLdb
15import task
16import tot_manager
17
18
19class FakeTotMilestoneManager(tot_manager.TotMilestoneManager):
20 """Mock class for tot_manager.TotMilestoneManager."""
21
22 def __init__(self, is_sanity):
23 self.is_sanity = is_sanity
24 self.storage_client = None
25 self.tot = self._tot_milestone()
26
27
28class FakeCIDBClient(object):
29 """Mock class for cloud_sql_client.CIDBClient."""
30
31 def __init__(self, success=True):
32 self.success = success
33
34 def get_latest_passed_builds(self, build_config):
35 if not self.success:
36 raise MySQLdb.OperationalError('Failed to connect to db')
37
38 return cloud_sql_client.BuildInfo(board=build_config.split('-')[0],
39 milestone=TaskTestCase.MILESTONE,
40 platform=TaskTestCase.PLATFORM,
41 build_config=build_config)
42
43
Xixuan Wu5451a662017-10-17 10:57:40 -070044class TaskBaseTestCase(unittest.TestCase):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070045
46 BOARD = 'fake_board'
Po-Hsien Wang6d589732018-05-15 17:19:34 -070047 EXCLUDE_BOARD = 'exclude_fake_board'
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070048 NAME = 'fake_name'
49 SUITE = 'fake_suite'
50 POOL = 'fake_pool'
51 PLATFORM = '6182.0.0-rc2'
52 MILESTONE = '30'
53 NUM = 1
54 PRIORITY = 50
55 TIMEOUT = 600
56
57 def setUp(self):
58 tot_patcher = mock.patch('tot_manager.TotMilestoneManager')
59 self._mock_tot = tot_patcher.start()
60 self.addCleanup(tot_patcher.stop)
61 # Can't pass in False since storage_client is not mocked.
62 self._mock_tot.return_value = FakeTotMilestoneManager(True)
63 self.task = task.Task(config_reader.TaskInfo(
64 name=self.NAME,
65 suite=self.SUITE,
66 branch_specs=[],
67 pool=self.POOL,
68 num=self.NUM,
69 boards=self.BOARD,
Po-Hsien Wang6d589732018-05-15 17:19:34 -070070 exclude_boards=self.EXCLUDE_BOARD,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070071 priority=self.PRIORITY,
72 timeout=self.TIMEOUT))
73
Xixuan Wu5451a662017-10-17 10:57:40 -070074
75class TaskTestCase(TaskBaseTestCase):
76
77 def setUp(self):
78 super(TaskTestCase, self).setUp()
79
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070080 mock_push = mock.patch('task.Task._push_suite')
81 self._mock_push = mock_push.start()
82 self.addCleanup(mock_push.stop)
83
84 def testSetSpecCompareInfoEqual(self):
85 """Test compare info setting for specs that equals to a milestone."""
86 self.task.branch_specs = re.split(r'\s*,\s*', '==tot-2')
87 self.task._set_spec_compare_info()
88 self.assertTrue(self.task._version_equal_constraint)
89 self.assertFalse(self.task._version_gte_constraint)
90 self.assertFalse(self.task._version_lte_constraint)
91 self.assertEqual(self.task._bare_branches, [])
92
93 def testSetSpecCompareInfoLess(self):
94 """Test compare info setting for specs that is less than a milestone."""
95 self.task.branch_specs = re.split(r'\s*,\s*', '<=tot')
96 self.task._set_spec_compare_info()
97 self.assertFalse(self.task._version_equal_constraint)
98 self.assertFalse(self.task._version_gte_constraint)
99 self.assertTrue(self.task._version_lte_constraint)
100 self.assertEqual(self.task._bare_branches, [])
101
102 def testSetSpecCompareInfoGreater(self):
103 """Test compare info setting for specs that is greater than a milestone."""
104 self.task.branch_specs = re.split(r'\s*,\s*', '>=tot-2')
105 self.task._set_spec_compare_info()
106 self.assertFalse(self.task._version_equal_constraint)
107 self.assertTrue(self.task._version_gte_constraint)
108 self.assertFalse(self.task._version_lte_constraint)
109 self.assertEqual(self.task._bare_branches, [])
110
111 def testFitsSpecEqual(self):
112 """Test milestone check for specs that equals to a milestone."""
113 self.task.branch_specs = re.split(r'\s*,\s*', '==tot-1')
114 self.task._set_spec_compare_info()
115 self.assertFalse(self.task._fits_spec('40'))
116 self.assertTrue(self.task._fits_spec('39'))
117 self.assertFalse(self.task._fits_spec('38'))
118
119 def testFitsSpecLess(self):
120 """Test milestone check for specs that is less than a milestone."""
121 self.task.branch_specs = re.split(r'\s*,\s*', '<=tot-1')
122 self.task._set_spec_compare_info()
123 self.assertFalse(self.task._fits_spec('40'))
124 self.assertTrue(self.task._fits_spec('39'))
125 self.assertTrue(self.task._fits_spec('38'))
126
127 def testFitsSpecGreater(self):
128 """Test milestone check for specs that is greater than a milestone."""
129 self.task.branch_specs = re.split(r'\s*,\s*', '>=tot-2')
130 self.task._set_spec_compare_info()
131 self.assertTrue(self.task._fits_spec('39'))
132 self.assertTrue(self.task._fits_spec('38'))
133 self.assertFalse(self.task._fits_spec('37'))
134
135 def testGetFirmwareFromLabConfig(self):
136 """Test get firmware from lab config successfully."""
137 with mock.patch('config_reader.LabConfig.get_firmware_ro_build_list',
138 return_value='build1,build2'):
139 firmware = self.task._get_firmware_build(
140 'released_ro_2', self.BOARD, config_reader.LabConfig(None), None)
141 self.assertEqual(firmware, 'build2')
142
143 def testGetFirmwareFromLabConfigOutofIndex(self):
144 """Test get firmware from lab config when firmware index is invalid."""
145 with mock.patch('config_reader.LabConfig.get_firmware_ro_build_list',
146 return_value='build1,build2'):
147 self.assertRaises(ValueError,
148 self.task._get_latest_firmware_build_from_lab_config,
149 'released_ro_3',
150 self.BOARD,
151 config_reader.LabConfig(None))
152 self.assertIsNone(self.task._get_firmware_build(
153 'released_ro_3', self.BOARD, config_reader.LabConfig(None), None))
154
155 def testGetFirmwareFromDB(self):
156 """Test get firmware from DB successfully."""
157 firmware = self.task._get_firmware_build(
158 'firmware', self.BOARD, None, FakeCIDBClient())
159 self.assertEqual(
160 firmware,
161 '%s-firmware/R%s-%s' % (self.BOARD, self.MILESTONE, self.PLATFORM))
162
163 def testGetFirmwareFromDBConnectionError(self):
164 """Test get firmware from DB when DB connection is failed."""
165 self.assertIsNone(self.task._get_firmware_build(
166 'firmware', self.BOARD, None, FakeCIDBClient(success=False)))
167
168 def testScheduleCrosSuccessfully(self):
169 """Test schedule cros builds successfully."""
170 branch_builds = {(self.BOARD, 'release', '56'): '0000.00.00'}
171 self.task._schedule_cros_builds(branch_builds,
172 config_reader.LabConfig(None),
173 FakeCIDBClient())
174 self.assertEqual(self._mock_push.call_count, 1)
175
176 def testScheduleCrosNonvalidBoard(self):
177 """Test schedule no cros builds due to non-allowed board."""
178 branch_builds = {('%s_2' % self.BOARD, 'release', '56'): '0000.00.00'}
179 self.task._schedule_cros_builds(branch_builds,
180 config_reader.LabConfig(None),
181 FakeCIDBClient())
182 self.assertEqual(self._mock_push.call_count, 0)
183
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700184 def testScheduleCrosExcludeBoard(self):
185 """Test schedule no cros builds due to board is excluded."""
186 branch_builds = {(self.EXCLUDE_BOARD, 'release', '56'): '0000.00.00'}
187 self.task._schedule_cros_builds(branch_builds,
188 config_reader.LabConfig(None),
189 FakeCIDBClient())
190 self.assertEqual(self._mock_push.call_count, 0)
191
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700192 def testScheduleCrosNonValidSpec(self):
193 """Test schedule no cros builds due to non-allowed branch milestone."""
194 branch_builds = {(self.BOARD, 'release', '56'): '0000.00.00'}
195 # Only run tasks whose milestone = tot (R40)
196 self.task.branch_specs = re.split(r'\s*,\s*', '==tot')
197 self.task._set_spec_compare_info()
198 self.task._schedule_cros_builds(branch_builds,
199 config_reader.LabConfig(None),
200 FakeCIDBClient())
201 self.assertEqual(self._mock_push.call_count, 0)
202
203 def testScheduleCrosSuccessfullyWithValidFirmware(self):
204 """Test schedule cros builds successfully with valid firmware."""
205 branch_builds = {(self.BOARD, 'release', '56'): '0000.00.00'}
206 self.task.firmware_ro_build_spec = 'firmware'
207 self.task._schedule_cros_builds(branch_builds,
208 config_reader.LabConfig(None),
209 FakeCIDBClient())
210 self.assertEqual(self._mock_push.call_count, 1)
211
212 def testScheduleCrosWithNonValidFirmware(self):
213 """Test schedule no cros builds due to non-existent firmware."""
214 branch_builds = {(self.BOARD, 'release', '56'): '0000.00.00'}
215 self.task.firmware_ro_build_spec = 'firmware'
216 self.task._schedule_cros_builds(branch_builds,
217 config_reader.LabConfig(None),
218 FakeCIDBClient(success=False))
219 self.assertEqual(self._mock_push.call_count, 0)
220
221 def testScheduleLaunchControlWithFullBranches(self):
222 """Test schedule all launch control builds successfully."""
223 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
224 'git_nyc-mr1-release/shamu-userdebug/3783920']}
225 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
226 self.task.launch_control_branches = [
227 t.lstrip() for t in lc_branches.split(',')]
228 self.task._schedule_launch_control_builds(lc_builds)
229 self.assertEqual(self._mock_push.call_count, 2)
230
231 def testScheduleLaunchControlWithPartlyBranches(self):
232 """Test schedule part of launch control builds due to branch check."""
233 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
234 'git_nyc-mr1-release/shamu-userdebug/3783920']}
235 lc_branches = 'git_nyc-mr1-release'
236 self.task.launch_control_branches = [
237 t.lstrip() for t in lc_branches.split(',')]
238 self.task._schedule_launch_control_builds(lc_builds)
239 self.assertEqual(self._mock_push.call_count, 1)
240
241 def testScheduleLaunchControlWithNoBranches(self):
242 """Test schedule none of launch control builds due to branch check."""
243 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
244 'git_nyc-mr1-release/shamu-userdebug/3783920']}
245 self.task.launch_control_branches = []
246 self.task._schedule_launch_control_builds(lc_builds)
247 self.assertEqual(self._mock_push.call_count, 0)
248
249 def testScheduleLaunchControlNonvalidBoard(self):
250 """Test schedule none of launch control builds due to board check."""
251 lc_builds = {'%s_2' % self.BOARD:
252 ['git_nyc-mr2-release/shamu-userdebug/3844975',
253 'git_nyc-mr1-release/shamu-userdebug/3783920']}
254 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
255 self.task.launch_control_branches = [
256 t.lstrip() for t in lc_branches.split(',')]
257 self.task._schedule_launch_control_builds(lc_builds)
258 self.assertEqual(self._mock_push.call_count, 0)
Xixuan Wu5451a662017-10-17 10:57:40 -0700259
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700260 def testScheduleLaunchControlExcludeBoard(self):
261 """Test schedule none of launch control builds due to board check."""
262 lc_builds = {self.EXCLUDE_BOARD:
263 ['git_nyc-mr2-release/shamu-userdebug/3844975',
264 'git_nyc-mr1-release/shamu-userdebug/3783920']}
265 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
266 self.task.launch_control_branches = [
267 t.lstrip() for t in lc_branches.split(',')]
268 self.task._schedule_launch_control_builds(lc_builds)
269 self.assertEqual(self._mock_push.call_count, 0)
270
Xixuan Wu5451a662017-10-17 10:57:40 -0700271
272class TaskPushTestCase(TaskBaseTestCase):
273
274 def setUp(self):
275 super(TaskPushTestCase, self).setUp()
276 mock_push = mock.patch('task_executor.push')
277 self._mock_push = mock_push.start()
278 self.addCleanup(mock_push.stop)
279
280 def testScheduleCrOSIsPushSuccessfully(self):
281 """Test IS_PUSHED is changed if some CrOS suites are scheduled."""
282 branch_builds = {(self.BOARD, 'release', '56'): '0000.00.00'}
283 self.task.os_type = build_lib.OS_TYPE_CROS
284 self.assertTrue(self.task.schedule(
Craig Bergstrom58263d32018-04-26 14:11:35 -0600285 [], (branch_builds, []), config_reader.LabConfig(None),
286 FakeCIDBClient()))
Xixuan Wu5451a662017-10-17 10:57:40 -0700287
288 def testScheduleLaunchControlIsPushSuccessfully(self):
289 """Test IS_PUSHED is changed if some launch control suites are scheduled."""
290 lc_builds = {self.BOARD: ['git_nyc-mr2-release/shamu-userdebug/3844975',
291 'git_nyc-mr1-release/shamu-userdebug/3783920']}
292 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
293 self.task.launch_control_branches = [
294 t.lstrip() for t in lc_branches.split(',')]
295 self.task.os_type = build_lib.OS_TYPES_LAUNCH_CONTROL
296 self.assertTrue(self.task.schedule(
Craig Bergstrom58263d32018-04-26 14:11:35 -0600297 lc_builds, ([], []), config_reader.LabConfig(None), FakeCIDBClient()))
Xixuan Wu5451a662017-10-17 10:57:40 -0700298
299 def testScheduleCrosIsPushInvalidBoard(self):
300 """Test schedule no cros builds due to non-allowed board."""
Craig Bergstrom58263d32018-04-26 14:11:35 -0600301 branch_builds = (
302 {('%s_2' % self.BOARD, 'release', '56'): '0000.00.00'}, {},
303 )
Xixuan Wu5451a662017-10-17 10:57:40 -0700304 self.task.os_type = build_lib.OS_TYPE_CROS
305 self.assertFalse(self.task.schedule(
306 [], branch_builds, config_reader.LabConfig(None), FakeCIDBClient()))
307
308 def testScheduleLaunchControlIsPushInvalidBoard(self):
309 """Test schedule none of launch control builds due to board check."""
310 lc_builds = {'%s_2' % self.BOARD:
311 ['git_nyc-mr2-release/shamu-userdebug/3844975',
312 'git_nyc-mr1-release/shamu-userdebug/3783920']}
313 lc_branches = 'git_nyc-mr1-release,git_nyc-mr2-release'
314 self.task.launch_control_branches = [
315 t.lstrip() for t in lc_branches.split(',')]
316 self.task.os_type = build_lib.OS_TYPES_LAUNCH_CONTROL
317 self.task._schedule_launch_control_builds(lc_builds)
318 self.assertFalse(self.task.schedule(
Craig Bergstrom58263d32018-04-26 14:11:35 -0600319 lc_builds, ([], []), config_reader.LabConfig(None), FakeCIDBClient()))