• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2#
3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Unit tests for site_utils/deduping_scheduler.py."""
8
9import mox
10import unittest
11
12# driver must be imported first due to circular imports in base_event and task
13import driver  # pylint: disable-msg=W0611
14import deduping_scheduler
15
16import common
17from autotest_lib.client.common_lib import error
18from autotest_lib.client.common_lib import priorities
19from autotest_lib.server import frontend, site_utils
20from autotest_lib.server.cros.dynamic_suite import reporting
21
22
23class DedupingSchedulerTest(mox.MoxTestBase):
24    """Unit tests for DedupingScheduler
25
26    @var _BUILD: fake build
27    @var _BOARD: fake board to reimage
28    @var _SUITE: fake suite name
29    @var _POOL: fake machine pool name
30    """
31
32    _BUILD = 'build'
33    _BUILDS = {'cros-version': 'build'}
34    _BOARD = 'board'
35    _SUITE = 'suite'
36    _POOL = 'pool'
37    _NUM = 2
38    _PRIORITY = priorities.Priority.POSTBUILD
39    _TIMEOUT = 24
40    _TIMEOUT_MINS = 1440
41
42
43    def setUp(self):
44        super(DedupingSchedulerTest, self).setUp()
45        self.afe = self.mox.CreateMock(frontend.AFE)
46        self.scheduler = deduping_scheduler.DedupingScheduler(afe=self.afe)
47        self.mox.StubOutWithMock(site_utils, 'check_lab_status')
48
49
50    def _SetupLabStatus(self, build, message=None):
51        """Set up to mock one call to `site_utils.check_lab_status()`.
52
53        @param build    The build to expect to be passed to
54                        `check_lab_status()`.
55        @param message  `None` if the mocked call should return that
56                        the lab status is up.  Otherwise, a string for
57                        the exception message.
58
59        """
60        if message is None:
61            site_utils.check_lab_status(build)
62        else:
63            site_utils.check_lab_status(build).AndRaise(
64                site_utils.TestLabException(message))
65
66
67    def testScheduleSuite(self):
68        """Test a successful de-dup and suite schedule."""
69        # Lab is UP!
70        self._SetupLabStatus(self._BUILD)
71        # A similar suite has not already been scheduled.
72        self.afe.get_jobs(name__istartswith=self._BUILD,
73                          name__iendswith='control.'+self._SUITE,
74                          created_on__gte=mox.IgnoreArg(),
75                          min_rpc_timeout=mox.IgnoreArg()).AndReturn([])
76        # Expect an attempt to schedule; allow it to succeed.
77        self.afe.run('create_suite_job',
78                     name=self._SUITE,
79                     board=self._BOARD,
80                     builds=self._BUILDS,
81                     check_hosts=False,
82                     pool=self._POOL,
83                     num=self._NUM,
84                     priority=self._PRIORITY,
85                     test_source_build=None,
86                     timeout=self._TIMEOUT,
87                     max_runtime_mins=self._TIMEOUT_MINS,
88                     timeout_mins=self._TIMEOUT_MINS,
89                     file_bugs=False,
90                     wait_for_results=False,
91                     job_retry=False,
92                     delay_minutes=0,
93                     run_prod_code=False,
94                     min_rpc_timeout=mox.IgnoreArg()).AndReturn(7)
95        self.mox.ReplayAll()
96        self.assertTrue(self.scheduler.ScheduleSuite(self._SUITE,
97                                                     self._BOARD,
98                                                     self._BUILD,
99                                                     self._POOL,
100                                                     self._NUM,
101                                                     self._PRIORITY,
102                                                     self._TIMEOUT))
103
104
105    def testShouldNotScheduleSuite(self):
106        """Test a successful de-dup and avoiding scheduling the suite."""
107        # Lab is UP!
108        self._SetupLabStatus(self._BUILD)
109        # A similar suite has already been scheduled.
110        self.afe.get_jobs(
111            name__istartswith=self._BUILD,
112            name__iendswith='control.'+self._SUITE,
113            created_on__gte=mox.IgnoreArg(),
114            min_rpc_timeout=mox.IgnoreArg()).AndReturn(['42'])
115        self.mox.ReplayAll()
116        self.assertFalse(self.scheduler.ScheduleSuite(self._SUITE,
117                                                      self._BOARD,
118                                                      self._BUILD,
119                                                      self._POOL,
120                                                      None,
121                                                      self._PRIORITY,
122                                                      self._TIMEOUT))
123
124
125    def testShouldNotScheduleSuiteLabClosed(self):
126        """Test that we don't schedule when the lab is closed."""
127        # Lab is down.  :-(
128        self._SetupLabStatus(self._BUILD, 'Lab closed due to sheep.')
129        self.mox.ReplayAll()
130        self.assertFalse(self.scheduler.ScheduleSuite(self._SUITE,
131                                                      self._BOARD,
132                                                      self._BUILD,
133                                                      self._POOL,
134                                                      None,
135                                                      self._PRIORITY,
136                                                      self._TIMEOUT))
137
138
139    def testForceScheduleSuite(self):
140        """Test a successful de-dup, but force scheduling the suite."""
141        # Expect an attempt to schedule; allow it to succeed.
142        self.afe.run('create_suite_job',
143                     name=self._SUITE,
144                     board=self._BOARD,
145                     builds=self._BUILDS,
146                     check_hosts=False,
147                     num=None,
148                     pool=self._POOL,
149                     priority=self._PRIORITY,
150                     test_source_build=None,
151                     timeout=self._TIMEOUT,
152                     max_runtime_mins=self._TIMEOUT_MINS,
153                     timeout_mins=self._TIMEOUT_MINS,
154                     file_bugs=False,
155                     wait_for_results=False,
156                     job_retry=False,
157                     delay_minutes=0,
158                     run_prod_code=False,
159                     min_rpc_timeout=mox.IgnoreArg()).AndReturn(7)
160        self.mox.ReplayAll()
161        self.assertTrue(self.scheduler.ScheduleSuite(self._SUITE,
162                                                     self._BOARD,
163                                                     self._BUILD,
164                                                     self._POOL,
165                                                     None,
166                                                     self._PRIORITY,
167                                                     self._TIMEOUT,
168                                                     force=True))
169
170
171    def testShouldScheduleSuiteExplodes(self):
172        """Test a failure to de-dup."""
173        # Lab is UP!
174        self._SetupLabStatus(self._BUILD)
175        # Barf while checking for similar suites.
176        self.afe.get_jobs(
177            name__istartswith=self._BUILD,
178            name__iendswith='control.'+self._SUITE,
179            created_on__gte=mox.IgnoreArg(),
180            min_rpc_timeout=mox.IgnoreArg()).AndRaise(Exception())
181        self.mox.ReplayAll()
182        self.assertRaises(deduping_scheduler.DedupException,
183                          self.scheduler.ScheduleSuite,
184                          self._SUITE,
185                          self._BOARD,
186                          self._BUILD,
187                          self._POOL,
188                          self._NUM,
189                          self._PRIORITY,
190                          self._TIMEOUT)
191
192
193    def testScheduleFail(self):
194        """Test a successful de-dup and failure to schedule the suite."""
195        # Lab is UP!
196        self._SetupLabStatus(self._BUILD)
197        # A similar suite has not already been scheduled.
198        self.afe.get_jobs(name__istartswith=self._BUILD,
199                          name__iendswith='control.'+self._SUITE,
200                          created_on__gte=mox.IgnoreArg(),
201                          min_rpc_timeout=mox.IgnoreArg()).AndReturn([])
202        # Expect an attempt to create a job for the suite; fail it.
203        self.afe.run('create_suite_job',
204                     name=self._SUITE,
205                     board=self._BOARD,
206                     builds=self._BUILDS,
207                     check_hosts=False,
208                     num=None,
209                     pool=None,
210                     priority=self._PRIORITY,
211                     test_source_build=None,
212                     timeout=self._TIMEOUT,
213                     max_runtime_mins=self._TIMEOUT_MINS,
214                     timeout_mins=self._TIMEOUT_MINS,
215                     file_bugs=False,
216                     wait_for_results=False,
217                     run_prod_code=False,
218                     min_rpc_timeout=mox.IgnoreArg()).AndReturn(None)
219        self.mox.ReplayAll()
220        self.assertRaises(deduping_scheduler.ScheduleException,
221                          self.scheduler.ScheduleSuite,
222                          self._SUITE,
223                          self._BOARD,
224                          self._BUILD,
225                          None,
226                          None,
227                          self._PRIORITY,
228                          self._TIMEOUT)
229
230
231    def testScheduleExplodes(self):
232        """Test a successful de-dup and barf while scheduling the suite."""
233        # Lab is UP!
234        self._SetupLabStatus(self._BUILD)
235        # A similar suite has not already been scheduled.
236        self.afe.get_jobs(name__istartswith=self._BUILD,
237                          name__iendswith='control.'+self._SUITE,
238                          created_on__gte=mox.IgnoreArg(),
239                          min_rpc_timeout=mox.IgnoreArg()).AndReturn([])
240        # Expect an attempt to create a job for the suite; barf on it.
241        self.afe.run('create_suite_job',
242                     name=self._SUITE,
243                     board=self._BOARD,
244                     builds=self._BUILDS,
245                     check_hosts=False,
246                     num=None,
247                     pool=None,
248                     priority=self._PRIORITY,
249                     test_source_build=None,
250                     timeout=self._TIMEOUT,
251                     max_runtime_mins=self._TIMEOUT_MINS,
252                     timeout_mins=self._TIMEOUT_MINS,
253                     file_bugs=False,
254                     wait_for_results=False,
255                     run_prod_code=False,
256                     min_rpc_timeout=mox.IgnoreArg()).AndRaise(Exception())
257        self.mox.ReplayAll()
258        self.assertRaises(deduping_scheduler.ScheduleException,
259                          self.scheduler.ScheduleSuite,
260                          self._SUITE,
261                          self._BOARD,
262                          self._BUILD,
263                          None,
264                          None,
265                          self._PRIORITY,
266                          self._TIMEOUT)
267
268
269    def _SetupScheduleSuiteMocks(self, mock_bug_id):
270        """Setup mocks needed for SuiteSchedulerBug testing.
271
272        @param mock_bug_id: An integer representing a bug id that should be
273                            returned by Reporter._create_bug_report
274                            None if _create_bug_report is supposed to
275                            fail.
276        """
277        self.mox.StubOutWithMock(reporting.Reporter, '__init__')
278        self.mox.StubOutWithMock(reporting.Reporter, '_create_bug_report')
279        self.mox.StubOutWithMock(reporting.Reporter, '_check_tracker')
280        self.mox.StubOutWithMock(reporting.Reporter, '_find_issue_by_marker')
281        self.mox.StubOutWithMock(site_utils, 'get_sheriffs')
282        self.scheduler._file_bug = True
283        # Lab is UP!
284        self._SetupLabStatus(self._BUILD)
285        # A similar suite has not already been scheduled.
286        self.afe.get_jobs(name__istartswith=self._BUILD,
287                          name__iendswith='control.'+self._SUITE,
288                          created_on__gte=mox.IgnoreArg(),
289                          min_rpc_timeout=mox.IgnoreArg()).AndReturn([])
290        message = 'Control file not found.'
291        exception = error.ControlFileNotFound(message)
292        site_utils.get_sheriffs(lab_only=True).AndReturn(['deputy1', 'deputy2'])
293        self.afe.run('create_suite_job',
294                     name=self._SUITE,
295                     board=self._BOARD,
296                     builds=self._BUILDS,
297                     check_hosts=False,
298                     pool=self._POOL,
299                     num=self._NUM,
300                     priority=self._PRIORITY,
301                     test_source_build=None,
302                     timeout=self._TIMEOUT,
303                     max_runtime_mins=self._TIMEOUT_MINS,
304                     timeout_mins=self._TIMEOUT_MINS,
305                     file_bugs=False,
306                     wait_for_results=False,
307                     job_retry=False,
308                     delay_minutes=0,
309                     run_prod_code=False,
310                     min_rpc_timeout=mox.IgnoreArg()).AndRaise(exception)
311        reporting.Reporter.__init__()
312        reporting.Reporter._check_tracker().AndReturn(True)
313        (reporting.Reporter._find_issue_by_marker(mox.IgnoreArg())
314         .AndReturn(None))
315        reporting.Reporter._create_bug_report(
316                mox.IgnoreArg(), {}, []).AndReturn(mock_bug_id)
317
318
319    def testScheduleReportsBugSuccess(self):
320        """Test that the scheduler file a bug."""
321        self._SetupScheduleSuiteMocks(1158)
322        self.mox.ReplayAll()
323        self.assertFalse(self.scheduler.ScheduleSuite(
324                    self._SUITE, self._BOARD, self._BUILD, self._POOL,
325                    self._NUM, self._PRIORITY, self._TIMEOUT))
326        self.mox.VerifyAll()
327
328
329    def testScheduleReportsBugFalse(self):
330        """Test that the scheduler failed to file a bug."""
331        self._SetupScheduleSuiteMocks(None)
332        self.mox.ReplayAll()
333        self.assertRaises(
334                deduping_scheduler.ScheduleException,
335                self.scheduler.ScheduleSuite,
336                self._SUITE, self._BOARD, self._BUILD, self._POOL,
337                self._NUM, self._PRIORITY, self._TIMEOUT)
338        self.mox.VerifyAll()
339
340
341if __name__ == '__main__':
342    unittest.main()
343