blob: bce979d1422150b807a62f1a071cb2aef66435d5 [file] [log] [blame]
Xixuan Wu40998892017-08-29 14:32:26 -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 trigger_receiver unittests."""
Xixuan Wu09962902018-12-11 10:49:27 -08006# pylint: disable=g-missing-super-call
Xixuan Wu40998892017-08-29 14:32:26 -07007
8import datetime
9import os
10import unittest
11
Xixuan Wuc6819012019-05-23 11:34:59 -070012import build_lib
Xixuan Wu40998892017-08-29 14:32:26 -070013import cloud_sql_client
14import config_reader
15import datastore_client
16import file_getter
17import mock
Xixuan Wu51bb7102019-03-18 14:51:44 -070018import task_config_reader
Craig Bergstrom58263d32018-04-26 14:11:35 -060019import task_executor
Xixuan Wu40998892017-08-29 14:32:26 -070020import time_converter
21import trigger_receiver
22
Craig Bergstrom58263d32018-04-26 14:11:35 -060023from google.appengine.api import taskqueue
Xixuan Wu40998892017-08-29 14:32:26 -070024from google.appengine.ext import ndb
25from google.appengine.ext import testbed
26
27# Ensure that SUITE_SCHEDULER_CONFIG_FILE is read only once.
28_SUITE_CONFIG_READER = config_reader.ConfigReader(
Xixuan Wu26d06e02017-09-20 14:50:28 -070029 file_getter.TEST_SUITE_SCHEDULER_CONFIG_FILE)
Xixuan Wu40998892017-08-29 14:32:26 -070030
31
32def now_generator(start_time, interval_min=30, last_days=7):
33 """A datetime.datetime.now generator.
34
35 The generator will generate 'now' from start_time till start_time+last_days
36 for every interval_min.
37
38 Args:
39 start_time: A datetime.datetime object representing the initial value of
40 the 'now'.
41 interval_min: The interval minutes between current 'now' and next 'now.
42 last_days: Representing how many days this generator will last.
43
44 Yields:
45 a datetime.datetime object to mock the current time.
46 """
47 cur_time = start_time
48 end_time = start_time + datetime.timedelta(days=last_days)
49 while cur_time < end_time:
50 yield cur_time
51 cur_time += datetime.timedelta(minutes=interval_min)
52
53
Xixuan Wu09962902018-12-11 10:49:27 -080054def _should_schedule_timed_task(last_now, now):
55 """Check whether timed (weekly/nightly) task should be scheduled.
Xixuan Wu40998892017-08-29 14:32:26 -070056
Xixuan Wu09962902018-12-11 10:49:27 -080057 A timed task should be schduled when next hour is coming.
Xixuan Wu40998892017-08-29 14:32:26 -070058
59 Args:
Xixuan Wu09962902018-12-11 10:49:27 -080060 last_now: the last time to check if timed task should be scheduled
Xixuan Wu40998892017-08-29 14:32:26 -070061 or not.
Xixuan Wu09962902018-12-11 10:49:27 -080062 now: the current time to check if timed task should be scheduled.
Xixuan Wu40998892017-08-29 14:32:26 -070063
64 Returns:
65 a boolean indicating whether there will be nightly tasks scheduled.
66 """
67 if last_now is not None and last_now.hour != now.hour:
68 return True
69
70 return False
71
72
Xixuan Wu40998892017-08-29 14:32:26 -070073def _should_schedule_new_build_task(last_now, now):
74 """Check whether weekly task should be scheduled.
75
76 A new_build task should be schduled when there're new builds between last
77 check and this check.
78
79 Args:
80 last_now: the last time to check if new_build task should be scheduled.
81 now: the current time to check if new_build task should be scheduled.
82
83 Returns:
84 a boolean indicating whether there will be new_build tasks scheduled.
85 """
86 if last_now is not None and last_now != now:
87 return True
88
89 return False
90
91
Xixuan Wuc6819012019-05-23 11:34:59 -070092# TODO(xixuan): to be deprecated and deleted.
Xixuan Wu40998892017-08-29 14:32:26 -070093class FakeCIDBClient(object):
94 """Mock cloud_sql_client.CIDBClient."""
95
96 def get_passed_builds_since_date(self, since_date):
97 """Mock cloud_sql_client.CIDBClient.get_passed_builds_since_date."""
98 del since_date # unused
Xixuan Wua41efa22019-05-17 14:28:04 -070099 return [
100 cloud_sql_client.BuildInfo('link', None, '62', '9868.0.0',
101 'link-release'),
102 cloud_sql_client.BuildInfo('zako', None, '62', '9868.0.0',
103 'zako-release'),
104 cloud_sql_client.BuildInfo('samus-kernelnext', None, '62',
105 '9868.0.0', 'samus-kernelnext-release'),
106 cloud_sql_client.BuildInfo('reef', None, '62', '1234.0.0',
107 'reef-release'),
108 cloud_sql_client.BuildInfo('coral', 'santa', '62', '9868.0.0',
109 'coral-release'),
110 cloud_sql_client.BuildInfo('coral', 'astronaut', '62', '9868.0.0',
111 'coral-release'),
112 cloud_sql_client.BuildInfo('coral', 'lava', '62', '9868.0.0',
113 'coral-release'),
114 ]
Xixuan Wu40998892017-08-29 14:32:26 -0700115
116 def get_latest_passed_builds(self, build_config):
117 """Mock cloud_sql_client.CIDBClient.get_latest_passed_builds."""
118 del build_config # unused
119 return cloud_sql_client.BuildInfo('link', '62', '9868.0.0', build_config)
120
Craig Bergstrom58263d32018-04-26 14:11:35 -0600121 def get_relaxed_pased_builds_since_date(self, since_date):
122 """Mock cloud_sql_client.CIDBClient.get_relaxed_pased_builds_since_date."""
123 del since_date # unused
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700124 return [cloud_sql_client.BuildInfo('grunt', None, '63', '9968.0.0',
Craig Bergstrom58263d32018-04-26 14:11:35 -0600125 'grunt-release')]
126
Xixuan Wu40998892017-08-29 14:32:26 -0700127
Xixuan Wuc6819012019-05-23 11:34:59 -0700128class FakeBuildClient(object):
129 """Mock rest_client.BuildBucketBigqueryClient."""
130
131 def get_passed_builds_since_date(self, since_date):
132 """Mock cloud_sql_client.CIDBClient.get_passed_builds_since_date."""
133 del since_date # unused
134 return [
135 build_lib.BuildInfo(
136 'link', None, '62', '9868.0.0', 'link-release'),
137 build_lib.BuildInfo(
138 'zako', None, '62', '9868.0.0', 'zako-release'),
139 build_lib.BuildInfo('samus-kernelnext', None, '62',
140 '9868.0.0', 'samus-kernelnext-release'),
141 build_lib.BuildInfo(
142 'reef', None, '62', '1234.0.0', 'reef-release'),
143 build_lib.BuildInfo(
144 'coral', 'santa', '62', '9868.0.0', 'coral-release'),
145 build_lib.BuildInfo(
146 'coral', 'astronaut', '62', '9868.0.0', 'coral-release'),
147 build_lib.BuildInfo(
148 'coral', 'lava', '62', '9868.0.0', 'coral-release'),
149 ]
150
151 def get_latest_passed_builds(self, build_config):
152 """Mock cloud_sql_client.CIDBClient.get_latest_passed_builds."""
153 del build_config # unused
154 return build_lib.BuildInfo('link', '62', '9868.0.0', build_config)
155
156 def get_relaxed_passed_builds_since_date(self, since_date):
157 """Mock cloud_sql_client.CIDBClient.get_relaxed_pased_builds_since_date."""
158 del since_date # unused
159 return [build_lib.BuildInfo(
160 'grunt', None, '63', '9968.0.0', 'grunt-release')]
161
162
Xixuan Wu40998892017-08-29 14:32:26 -0700163class FakeAndroidBuildRestClient(object):
164 """Mock rest_client.AndroidBuildRestClient."""
165
166 def get_latest_build_id(self, branch, target):
167 """Mock rest_client.AndroidBuildRestClient.get_latest_build_id."""
168 del branch, target # unused
169 return '100'
170
171
172class FakeLabConfig(object):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700173 """Mock config_reader.LabConfig."""
Xixuan Wu40998892017-08-29 14:32:26 -0700174
175 def get_android_board_list(self):
176 """Mock config_reader.LabConfig.get_android_board_list."""
177 return ('android-angler', 'android-bullhead')
178
Xixuan Wu6fb16272017-10-19 13:16:00 -0700179 def get_cros_board_list(self):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700180 """Mock config_reader.LabConfig.get_cros_board_list."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700181 return ('grunt', 'link', 'peppy', 'daisy', 'zako', 'samus-kernelnext',
182 'coral', 'reef')
Xixuan Wu6fb16272017-10-19 13:16:00 -0700183
Xixuan Wu40998892017-08-29 14:32:26 -0700184 def get_firmware_ro_build_list(self, release_board):
185 """Mock config_reader.LabConfig.get_firmware_ro_build_list."""
186 del release_board # unused
187 return 'firmware1,firmware2'
188
C Shapiro7f24a002017-12-05 14:25:09 -0700189 def get_cros_model_map(self):
190 """Mock config_reader.LabConfig.get_cros_model_map."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700191 return {
192 'coral': ['santa', 'astronaut'],
193 'reef': ['electro'],
194 }
C Shapiro7f24a002017-12-05 14:25:09 -0700195
Xixuan Wu40998892017-08-29 14:32:26 -0700196
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700197class FakeMigrationConfig(object):
198 """Mock config_reader.MigrationConfig."""
199
Xixuan Wu1e42c752019-03-21 13:41:49 -0700200 def get_skylab_suites_dump(self):
Xixuan Wuee6b6a82019-03-21 14:28:26 -0700201 """Mock config_reader.MigrationConfig.get_skylab_suite_list."""
Xixuan Wu1e42c752019-03-21 13:41:49 -0700202 return {'suite:ent-nightly':
203 {'pool:suites':
Xixuan Wu028f6732019-04-11 14:47:42 -0700204 {'model:santa': {
205 'skylab': True,
206 'override_pool': '',
207 'override_qs_account': '',
208 },
209 'model:zako': {
210 'skylab': True,
211 'override_pool': 'QUOTA_POOL',
212 'override_qs_account': 'QUOTA_ACCOUNT',
213 }}}}
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700214
215
Xixuan Wu008ee832017-10-12 16:59:34 -0700216class TriggerReceiverBaseTestCase(unittest.TestCase):
Xixuan Wu40998892017-08-29 14:32:26 -0700217
218 def setUp(self):
219 self.testbed = testbed.Testbed()
220 self.testbed.activate()
221 self.addCleanup(self.testbed.deactivate)
222
223 self.testbed.init_datastore_v3_stub()
224 self.testbed.init_memcache_stub()
225 ndb.get_context().clear_cache()
226 self.testbed.init_taskqueue_stub(
227 root_path=os.path.join(os.path.dirname(__file__)))
228 self.taskqueue_stub = self.testbed.get_stub(
229 testbed.TASKQUEUE_SERVICE_NAME)
230
Xixuan Wuc6819012019-05-23 11:34:59 -0700231 # TODO(xixuan): to be deprecated and deleted.
Xixuan Wu40998892017-08-29 14:32:26 -0700232 mock_cidb_client = mock.patch('cloud_sql_client.CIDBClient')
233 self._mock_cidb_client = mock_cidb_client.start()
234 self.addCleanup(mock_cidb_client.stop)
235
Xixuan Wuc6819012019-05-23 11:34:59 -0700236 mock_build_client = mock.patch('rest_client.BuildBucketBigqueryClient')
237 self._mock_build_client = mock_build_client.start()
238 self.addCleanup(mock_build_client.stop)
239
Xixuan Wu40998892017-08-29 14:32:26 -0700240 mock_android_client = mock.patch('rest_client.AndroidBuildRestClient')
241 self._mock_android_client = mock_android_client.start()
242 self.addCleanup(mock_android_client.stop)
243
Xixuan Wu40998892017-08-29 14:32:26 -0700244 mock_lab_config = mock.patch('config_reader.LabConfig')
245 self._mock_lab_config = mock_lab_config.start()
246 self.addCleanup(mock_lab_config.stop)
247
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700248 mock_migration_config = mock.patch('config_reader.MigrationConfig')
249 self._mock_migration_config = mock_migration_config.start()
250 self.addCleanup(mock_migration_config.stop)
251
Xixuan Wu40998892017-08-29 14:32:26 -0700252 mock_utc_now = mock.patch('time_converter.utc_now')
253 self._mock_utc_now = mock_utc_now.start()
254 self.addCleanup(mock_utc_now.stop)
255
Xixuan Wuc6819012019-05-23 11:34:59 -0700256 # TODO(xixuan): to be deprecated and deleted.
Xixuan Wu40998892017-08-29 14:32:26 -0700257 self._mock_cidb_client.return_value = FakeCIDBClient()
Xixuan Wuc6819012019-05-23 11:34:59 -0700258 self._mock_build_client.return_value = FakeBuildClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700259 self._mock_android_client.return_value = FakeAndroidBuildRestClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700260 self._mock_lab_config.return_value = FakeLabConfig()
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700261 self._mock_migration_config.return_value = FakeMigrationConfig()
Xixuan Wu40998892017-08-29 14:32:26 -0700262
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700263 board_family_patcher = mock.patch(
264 'build_lib.get_board_family_mapping_from_gs')
265 board_family_getter = board_family_patcher.start()
266 board_family_getter.return_value = {
267 'nyan': ['nyan', 'nyan_blaze', 'nyan_big'],
268 'ivybridge': ['link', 'link_freon']}
269 self.addCleanup(board_family_patcher.stop)
270
Xixuan Wu008ee832017-10-12 16:59:34 -0700271
272class TriggerReceiverFakeConfigTestCase(TriggerReceiverBaseTestCase):
273
274 _TEST_PST_HOUR = 20
275 _TEST_PST_DAY = 4 # Friday
276 _TEST_EVENT_PST_HOUR = 13
277
278 _FAKE_NIGHTLY_TASK_NAME = 'fake_nightly_task'
279 _FAKE_WEEKLY_TASK_NAME = 'fake_weekly_task'
280
281 def setUp(self):
282 super(TriggerReceiverFakeConfigTestCase, self).setUp()
283
284 self.fake_config = config_reader.ConfigReader(None)
285 self._add_nightly_tasks(self.fake_config)
286 self._add_weekly_tasks(self.fake_config)
287
288 self.fake_config_with_settings = config_reader.ConfigReader(None)
289 self._add_weekly_tasks(self.fake_config_with_settings)
290 self._add_weekly_params(self.fake_config_with_settings)
291
292 mock_config_reader = mock.patch('config_reader.ConfigReader')
293 self._mock_config_reader = mock_config_reader.start()
294 self.addCleanup(mock_config_reader.stop)
295
296 def _add_nightly_tasks(self, fake_config):
297 fake_config.add_section(self._FAKE_NIGHTLY_TASK_NAME)
298 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'suite', 'fake_suite')
299 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'run_on', 'nightly')
300 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'hour',
301 str(self._TEST_PST_HOUR))
302
303 def _add_weekly_tasks(self, fake_config):
304 fake_config.add_section(self._FAKE_WEEKLY_TASK_NAME)
305 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'suite', 'fake_suite')
306 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'run_on', 'weekly')
307 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'day', str(self._TEST_PST_DAY))
308
309 def _add_weekly_params(self, fake_config):
Xixuan Wu51bb7102019-03-18 14:51:44 -0700310 weekly_section_name = task_config_reader.EVENT_CLASSES[
311 'weekly'].section_name()
Xixuan Wu008ee832017-10-12 16:59:34 -0700312 fake_config.add_section(weekly_section_name)
313 fake_config.set(weekly_section_name, 'hour', str(self._TEST_EVENT_PST_HOUR))
314
315 def testInitializeTriggerReceiverWithNightlyEvent(self):
316 """Test nightly event can be handled on right hour."""
317 # A task with hour=20 should be scheduled at 20:00 in PST everyday, which
318 # is 3:00/4:00 in UTC everyday.
319 self._mock_config_reader.return_value = self.fake_config
320 given_utc_hour = time_converter.convert_time_info(
321 time_converter.TimeInfo(None, self._TEST_PST_HOUR)).hour
322 utc_now = datetime.datetime(2017, 8, 6, given_utc_hour,
323 tzinfo=time_converter.UTC_TZ)
324 last_exec_client = datastore_client.LastExecutionRecordStore()
325 last_exec_client.set_last_execute_time(
326 'nightly', utc_now - datetime.timedelta(hours=1))
327 self._mock_utc_now.return_value = utc_now
328
329 suite_trigger = trigger_receiver.TriggerReceiver()
330 suite_trigger.cron()
331 self.assertTrue(suite_trigger.events['nightly'].should_handle)
332 self.assertEqual(len(suite_trigger.event_results['nightly']), 1)
333 self.assertEqual(suite_trigger.event_results['nightly'][0],
334 self._FAKE_NIGHTLY_TASK_NAME)
335
336 def testInitializeTriggerReceiverWithWeeklyEventWithoutEventHour(self):
337 """Test weekly event without event settings can be handled on right day."""
338 # A task with day=4 (Friday) and default event_hour (23) should be
339 # scheduled at Friday 23:00 in PST, which is Saturday 6:00 or 7:00 in UTC.
340 self._mock_config_reader.return_value = self.fake_config
341 given_utc_hour = time_converter.convert_time_info(
342 time_converter.TimeInfo(
343 self._TEST_PST_DAY,
Xixuan Wu51bb7102019-03-18 14:51:44 -0700344 task_config_reader.EVENT_CLASSES['weekly'].DEFAULT_PST_HOUR)).hour
Xixuan Wu008ee832017-10-12 16:59:34 -0700345 utc_now = datetime.datetime(2017, 10, 14, given_utc_hour,
346 tzinfo=time_converter.UTC_TZ)
347 last_exec_client = datastore_client.LastExecutionRecordStore()
348 last_exec_client.set_last_execute_time(
349 'weekly', utc_now - datetime.timedelta(days=1))
350 self._mock_utc_now.return_value = utc_now
351
352 suite_trigger = trigger_receiver.TriggerReceiver()
353 suite_trigger.cron()
354 self.assertTrue(suite_trigger.events['weekly'].should_handle)
355 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
356 self.assertEqual(suite_trigger.event_results['weekly'][0],
357 self._FAKE_WEEKLY_TASK_NAME)
358
359 def testInitializeTriggerReceiverWithWeeklyEventWithEventHour(self):
360 """Test weekly event with event settings can be handled on right day."""
361 # A task with day=4 (Friday) and event_hour=13 should be scheduled at
362 # Friday 13:00 in PST, which is Friday 20:00 or 21:00 in UTC.
363 self._mock_config_reader.return_value = self.fake_config_with_settings
364 given_utc_time_info = time_converter.convert_time_info(
365 time_converter.TimeInfo(self._TEST_PST_DAY, self._TEST_EVENT_PST_HOUR))
366
367 # Set the current time as a Friday 20:00 or 21:00 in UTC.
368 utc_now = datetime.datetime(2017, 10, 13, given_utc_time_info.hour,
369 tzinfo=time_converter.UTC_TZ)
370 last_exec_client = datastore_client.LastExecutionRecordStore()
371 last_exec_client.set_last_execute_time(
372 'weekly', utc_now - datetime.timedelta(days=1))
373 self._mock_utc_now.return_value = utc_now
374
375 suite_trigger = trigger_receiver.TriggerReceiver()
376 suite_trigger.cron()
377 self.assertTrue(suite_trigger.events['weekly'].should_handle)
378 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
379 self.assertEqual(suite_trigger.event_results['weekly'][0],
380 self._FAKE_WEEKLY_TASK_NAME)
381
382
Craig Bergstrom58263d32018-04-26 14:11:35 -0600383class TriggerReceiverFakeBuildTestCase(TriggerReceiverBaseTestCase):
384 """Test the new_build functionality."""
385
Craig Bergstrom58263d32018-04-26 14:11:35 -0600386 def setUp(self):
387 """Set up for a test."""
388 super(TriggerReceiverFakeBuildTestCase, self).setUp()
389
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700390 self._prepare()
391
392 def _prepare(self):
Craig Bergstrom58263d32018-04-26 14:11:35 -0600393 self.fake_config = config_reader.ConfigReader(None)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600394 mock_config_reader = mock.patch('config_reader.ConfigReader')
395 self._mock_config_reader = mock_config_reader.start()
396 self.addCleanup(mock_config_reader.stop)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600397
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700398 # Set last execution time for new_build events.
399 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600400 last_exec_client = datastore_client.LastExecutionRecordStore()
401 last_exec_client.set_last_execute_time(
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700402 'new_build', utc_now - datetime.timedelta(hours=1))
Craig Bergstrom58263d32018-04-26 14:11:35 -0600403 self._mock_utc_now.return_value = utc_now
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700404
405 def testNewBuildForHWTestSanityRequired(self):
406 """Test the new_build functionality."""
407 # Construct a fake config with only_hwtest_sanity_required.
408 fsnbt_name = 'FakeStrictNewBuildTask'
409 self.fake_config.add_section(fsnbt_name)
410 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
411 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700412 self.fake_config.set(fsnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700413 frnbt_name = 'FakeRelaxedNewBuildTask'
414 self.fake_config.add_section(frnbt_name)
415 self.fake_config.set(frnbt_name, 'run_on', 'new_build')
416 self.fake_config.set(frnbt_name, 'suite', 'fake_suite_relaxed')
417 self.fake_config.set(frnbt_name, 'only_hwtest_sanity_required', 'True')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700418 self.fake_config.set(frnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700419
420 self._mock_config_reader.return_value = self.fake_config
Craig Bergstrom58263d32018-04-26 14:11:35 -0600421
422 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600423 suite_trigger = trigger_receiver.TriggerReceiver()
424 suite_trigger.cron()
425
426 # Validate that the expected tests got kicked off.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600427 self.assertEqual(len(suite_trigger.event_results), 1)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600428 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000429 # 2 for strict passed builds, 3 for relaxed builds.
430 self.assertEqual(len(tasks), 5)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600431
432 # The number of builds that matched the base (success) Task.
433 count_base = 0
434 # The number of builds that matched the relaxed Task.
435 count_relaxed = 0
436 for task in tasks:
437 if 'fake_suite_base' in task.payload:
438 # Make sure it matched the expected build only.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600439 self.assertNotIn('grunt-release', task.payload)
440 count_base += 1
441
442 if 'fake_suite_relaxed' in task.payload:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600443 count_relaxed += 1
444
445 # Make each case matched precisely one event.
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000446 self.assertEqual(2, count_base)
447 self.assertEqual(3, count_relaxed)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600448
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700449 def testNewBuildWithExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700450 """Test the new_build suite with an existing board family."""
451 link_suite = 'FakeLinkNewBuildTask'
452 self.fake_config.add_section(link_suite)
453 self.fake_config.set(link_suite, 'run_on', 'new_build')
454 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700455 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700456 self._mock_config_reader.return_value = self.fake_config
457
458 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
459 suite_trigger = trigger_receiver.TriggerReceiver()
460 suite_trigger.cron()
461
462 self.assertEqual(len(suite_trigger.event_results), 1)
463 self.assertEqual(suite_trigger.event_results['new_build'],
464 [link_suite])
465 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
466 self.assertEqual(len(tasks), 1)
467 self.assertIn('link-release', tasks[0].payload)
468
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700469 def testNewBuildWithExistingBoardFamiliesAndBoards(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700470 """Test the new_build suite with an existing board family."""
471 link_suite = 'FakeLinkNewBuildTask'
472 self.fake_config.add_section(link_suite)
473 self.fake_config.set(link_suite, 'run_on', 'new_build')
474 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700475 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700476 self.fake_config.set(link_suite, 'boards', 'asuka, paine, banon')
477 self._mock_config_reader.return_value = self.fake_config
478
479 suite_trigger = trigger_receiver.TriggerReceiver()
480 suite_trigger.cron()
481
482 self.assertEqual(len(suite_trigger.event_results), 1)
483 self.assertEqual(suite_trigger.event_results['new_build'],
484 [link_suite])
485 boards = suite_trigger.events['new_build'].task_list[0].boards
486 self.assertIn('asuka', boards)
487 self.assertIn('link', boards)
488
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700489 def testNewBuildWithNonExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700490 """Test the new_build suite with an non-existing board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700491 nyan_suite = 'FakeNonExistBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700492 self.fake_config.add_section(nyan_suite)
493 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
494 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700495 self.fake_config.set(nyan_suite, 'board_families', 'nyan')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700496 self._mock_config_reader.return_value = self.fake_config
497
498 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
499 suite_trigger = trigger_receiver.TriggerReceiver()
500 suite_trigger.cron()
501
502 self.assertEqual(len(suite_trigger.event_results), 1)
503 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
504 self.assertEqual(len(tasks), 0)
505
506 def testNewBuildWithNonSpecifiedBoardFamily(self):
507 """Test the new_build suite with an non-specified board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700508 normal_suite = 'FakeBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700509 self.fake_config.add_section(normal_suite)
510 self.fake_config.set(normal_suite, 'run_on', 'new_build')
511 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700512 self.fake_config.set(normal_suite, 'boards', 'link, zako')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700513 self._mock_config_reader.return_value = self.fake_config
514
515 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
516 suite_trigger = trigger_receiver.TriggerReceiver()
517 suite_trigger.cron()
518
519 self.assertEqual(len(suite_trigger.event_results), 1)
520 self.assertEqual(suite_trigger.event_results['new_build'],
521 [normal_suite])
522 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000523 self.assertEqual(len(tasks), 2)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700524
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700525 def testNewBuildExcludingExistingBoardFamilies(self):
526 """Test the new_build suite excluding an existing board family."""
527 link_suite = 'FakeLinkNewBuildTask'
528 self.fake_config.add_section(link_suite)
529 self.fake_config.set(link_suite, 'run_on', 'new_build')
530 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
531 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700532 self.fake_config.set(link_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700533 self._mock_config_reader.return_value = self.fake_config
534
535 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
536 suite_trigger = trigger_receiver.TriggerReceiver()
537 suite_trigger.cron()
538
539 self.assertEqual(len(suite_trigger.event_results), 1)
540 self.assertEqual(suite_trigger.event_results['new_build'],
541 [link_suite])
542 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
543 self.assertEqual(len(tasks), 1)
544 self.assertNotIn('link-release', tasks[0].payload)
545 self.assertIn('zako-release', tasks[0].payload)
546
547 def testNewBuildExcludingExistingBoardFamiliesAndBoards(self):
548 """Test the new_build suite with an existing board family."""
549 link_suite = 'FakeLinkNewBuildTask'
550 self.fake_config.add_section(link_suite)
551 self.fake_config.set(link_suite, 'run_on', 'new_build')
552 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
553 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wua41efa22019-05-17 14:28:04 -0700554 self.fake_config.set(link_suite, 'exclude_boards',
555 'asuka, paine, banon, coral, reef')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700556 self._mock_config_reader.return_value = self.fake_config
557
558 suite_trigger = trigger_receiver.TriggerReceiver()
559 suite_trigger.cron()
560
561 self.assertEqual(len(suite_trigger.event_results), 1)
562 self.assertEqual(suite_trigger.event_results['new_build'],
563 [link_suite])
564 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
565 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
566 self.assertNotIn('link-release', tasks[0].payload)
567 self.assertNotIn('asuka-release', tasks[0].payload)
568 self.assertIn('zako-release', tasks[0].payload)
569
570 def testNewBuildExcludingNonExistingBoardFamilies(self):
571 """Test the new_build suite excluding an non-existing board family."""
572 nyan_suite = 'FakeNonExistExcludeBoardFamiliesNewBuildTask'
573 self.fake_config.add_section(nyan_suite)
574 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
575 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
576 self.fake_config.set(nyan_suite, 'exclude_board_families', 'nyan')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700577 self.fake_config.set(nyan_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700578 self._mock_config_reader.return_value = self.fake_config
579
580 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
581 suite_trigger = trigger_receiver.TriggerReceiver()
582 suite_trigger.cron()
583
584 self.assertEqual(len(suite_trigger.event_results), 1)
585 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
586 self.assertEqual(len(tasks), 2)
587
588 def testNewBuildWithBoardExcludeBoardCollision(self):
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700589 """Test the case that the same board in boards and exclude_boards."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700590 normal_suite = 'FakeBoardExludingBoardCollisionNewBuildTask'
591 self.fake_config.add_section(normal_suite)
592 self.fake_config.set(normal_suite, 'run_on', 'new_build')
593 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
594 self.fake_config.set(normal_suite, 'boards', 'zako, asuka')
595 self.fake_config.set(normal_suite, 'exclude_boards', 'asuka')
596 self._mock_config_reader.return_value = self.fake_config
597
598 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
599 suite_trigger = trigger_receiver.TriggerReceiver()
600 suite_trigger.cron()
601
602 self.assertEqual(len(suite_trigger.event_results), 1)
603 self.assertEqual(suite_trigger.event_results['new_build'],
604 [normal_suite])
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700605 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
606 self.assertEqual(len(tasks), 1)
607 self.assertNotIn('asuka-release', tasks[0].payload)
608 self.assertIn('zako-release', tasks[0].payload)
609
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700610 def testNewBuildWithSkylab(self):
611 """Test the case that suites run in skylab."""
612 normal_suite = 'FakeSkylabSuite'
613 self.fake_config.add_section(normal_suite)
614 self.fake_config.set(normal_suite, 'run_on', 'new_build')
615 self.fake_config.set(normal_suite, 'suite', 'ent-nightly')
Xixuan Wu1e42c752019-03-21 13:41:49 -0700616 self.fake_config.set(normal_suite, 'pool', 'suites')
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700617 self.fake_config.set(normal_suite, 'boards', 'zako, asuka')
618 self._mock_config_reader.return_value = self.fake_config
619
620 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
621 suite_trigger = trigger_receiver.TriggerReceiver()
622 suite_trigger.cron()
623
624 self.assertEqual(len(suite_trigger.event_results), 1)
625 self.assertEqual(suite_trigger.event_results['new_build'],
626 [normal_suite])
627 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
628 self.assertEqual(len(tasks), 1)
629 self.assertIn('is_skylab=True', tasks[0].payload)
Xixuan Wu028f6732019-04-11 14:47:42 -0700630 self.assertIn('override_pool=QUOTA_POOL', tasks[0].payload)
631 self.assertIn('override_qs_account=QUOTA_ACCOUNT', tasks[0].payload)
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700632
Xixuan Wub4b2f412019-05-03 11:22:31 -0700633 def testNewBuildWithKernelnext(self):
634 """Test the case that suites run with board-kernelnext build."""
635 normal_suite = 'FakeKernelnextSuite'
636 self.fake_config.add_section(normal_suite)
637 self.fake_config.set(normal_suite, 'run_on', 'new_build')
638 self.fake_config.set(normal_suite, 'suite', 'fake-suite')
639 self.fake_config.set(normal_suite, 'pool', 'suites')
640 self.fake_config.set(normal_suite, 'boards', 'samus-kernelnext')
641 self._mock_config_reader.return_value = self.fake_config
642
Xixuan Wub4b2f412019-05-03 11:22:31 -0700643 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
644 suite_trigger = trigger_receiver.TriggerReceiver()
645 suite_trigger.cron()
646
647 self.assertEqual(len(suite_trigger.event_results), 1)
648 self.assertEqual(suite_trigger.event_results['new_build'],
649 [normal_suite])
650 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
651 self.assertEqual(len(tasks), 1)
652 # Board should be 'samus'.
653 self.assertIn('&board=samus&', tasks[0].payload)
654 # Build should be 'samus-kernelnext-release***'.
655 self.assertIn('cros_version=samus-kernelnext-release', tasks[0].payload)
656
Xixuan Wua41efa22019-05-17 14:28:04 -0700657 def testNewBuildWithModels(self):
658 """Test the new_build suite with an existing models entry."""
659 normal_suite = 'FakeModelsNewBuildTask'
660 self.fake_config.add_section(normal_suite)
661 self.fake_config.set(normal_suite, 'run_on', 'new_build')
662 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
663 self.fake_config.set(normal_suite, 'models', 'coral_lava, coral_santa')
664 self.fake_config.set(normal_suite, 'boards', 'coral')
665 self._mock_config_reader.return_value = self.fake_config
666
667 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
668 suite_trigger = trigger_receiver.TriggerReceiver()
669 suite_trigger.cron()
670
671 self.assertEqual(len(suite_trigger.event_results), 1)
672 self.assertEqual(suite_trigger.event_results['new_build'],
673 [normal_suite])
674 self.assertIn('new_build', suite_trigger.event_results)
675 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
676 self.assertEqual(len(tasks), 1)
677 self.assertNotIn('model=astronaut', tasks[0].payload)
678 self.assertIn('model=santa', tasks[0].payload)
679
680 def testNewBuildWithExcludeModels(self):
681 """Test the new_build suite with an existing exclude_models entry."""
682 normal_suite = 'FakeExludingModelsNewBuildTask'
683 self.fake_config.add_section(normal_suite)
684 self.fake_config.set(normal_suite, 'run_on', 'new_build')
685 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
686 self.fake_config.set(normal_suite, 'exclude_models',
687 'coral_lava, coral_santa')
688 self.fake_config.set(normal_suite, 'boards', 'coral')
689 self._mock_config_reader.return_value = self.fake_config
690
691 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
692 suite_trigger = trigger_receiver.TriggerReceiver()
693 suite_trigger.cron()
694
695 self.assertEqual(len(suite_trigger.event_results), 1)
696 self.assertEqual(suite_trigger.event_results['new_build'],
697 [normal_suite])
698 self.assertIn('new_build', suite_trigger.event_results)
699 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
700 self.assertEqual(len(tasks), 1)
701 self.assertNotIn('model=santa', tasks[0].payload)
702 self.assertIn('model=astronaut', tasks[0].payload)
703
704 def testNewBuildWithModelsExcludeModels(self):
705 """Test the new_build suite with models and exclude_models entry."""
706 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
707 self.fake_config.add_section(normal_suite)
708 self.fake_config.set(normal_suite, 'run_on', 'new_build')
709 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
710 self.fake_config.set(normal_suite, 'models', 'coral_santa, coral_astronaut')
711 self.fake_config.set(normal_suite, 'exclude_models',
712 'coral_lava, coral_santa')
713 self.fake_config.set(normal_suite, 'boards', 'coral')
714 self._mock_config_reader.return_value = self.fake_config
715
716 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
717 suite_trigger = trigger_receiver.TriggerReceiver()
718 suite_trigger.cron()
719
720 self.assertEqual(len(suite_trigger.event_results), 1)
721 self.assertEqual(suite_trigger.event_results['new_build'],
722 [normal_suite])
723 self.assertIn('new_build', suite_trigger.event_results)
724 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
725 self.assertEqual(len(tasks), 1)
726 self.assertNotIn('model=santa', tasks[0].payload)
727 self.assertIn('model=astronaut', tasks[0].payload)
728
729 def testNewBuildWithNoModelListAndModelBuild(self):
730 """Test the new_build suite with models and empty board_model mapping."""
731 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
732 self.fake_config.add_section(normal_suite)
733 self.fake_config.set(normal_suite, 'run_on', 'new_build')
734 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
735 self.fake_config.set(normal_suite, 'boards', 'coral')
736 self._mock_config_reader.return_value = self.fake_config
737
738 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
739 suite_trigger = trigger_receiver.TriggerReceiver()
740 suite_trigger.cron()
741
742 self.assertIn('new_build', suite_trigger.event_results)
743 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
744 # Verify that coral-release is not kicked off on model lava as lava is not
745 # listed in cros_model_map.
746 self.assertEqual(len(tasks), 2)
747 self.assertNotIn('lava', tasks[0].payload)
748 self.assertNotIn('lava', tasks[1].payload)
749
750 def testNewBuildWithNoModelListAndNoModelBuild(self):
751 """Test the new_build suite with models and empty board_model mapping."""
752 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
753 self.fake_config.add_section(normal_suite)
754 self.fake_config.set(normal_suite, 'run_on', 'new_build')
755 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
756 self.fake_config.set(normal_suite, 'boards', 'reef')
757 self._mock_config_reader.return_value = self.fake_config
758
759 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
760 suite_trigger = trigger_receiver.TriggerReceiver()
761 suite_trigger.cron()
762
763 self.assertIn('new_build', suite_trigger.event_results)
764 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
765 # Verify that reef-release is kicked off on reef models.
766 self.assertEqual(len(tasks), 1)
767 self.assertIn('model=electro', tasks[0].payload)
768
Craig Bergstrom58263d32018-04-26 14:11:35 -0600769
Xixuan Wu008ee832017-10-12 16:59:34 -0700770class TriggerReceiverRealConfigTestCase(TriggerReceiverBaseTestCase):
771
772 def setUp(self):
773 super(TriggerReceiverRealConfigTestCase, self).setUp()
774 mock_config_reader = mock.patch('config_reader.ConfigReader')
775 self._mock_config_reader = mock_config_reader.start()
776 self.addCleanup(mock_config_reader.stop)
777 self._mock_config_reader.return_value = _SUITE_CONFIG_READER
778
779 def _get_ground_truth_task_list_from_config(self):
780 """Get the ground truth of to-be-scheduled task list from config file."""
781 self._mock_utc_now.return_value = datetime.datetime.now(
782 time_converter.UTC_TZ)
Xixuan Wu51bb7102019-03-18 14:51:44 -0700783 task_config = task_config_reader.TaskConfig(_SUITE_CONFIG_READER)
Xixuan Wu008ee832017-10-12 16:59:34 -0700784 tasks = {}
Xixuan Wu51bb7102019-03-18 14:51:44 -0700785 for keyword, klass in task_config_reader.EVENT_CLASSES.iteritems():
Xixuan Wu008ee832017-10-12 16:59:34 -0700786 new_event = klass(
787 task_config.get_event_setting(klass.section_name()), None)
788 new_event.set_task_list(
789 task_config.get_tasks_by_keyword(klass.KEYWORD)['tasks'])
790 tasks[keyword] = new_event.task_list
791
792 return tasks
793
Xixuan Wu40998892017-08-29 14:32:26 -0700794 def testCronWithoutLastExec(self):
795 """Test the first round of cron can be successfully executed."""
796 self._mock_utc_now.return_value = datetime.datetime.now(
797 time_converter.UTC_TZ)
798 suite_trigger = trigger_receiver.TriggerReceiver()
799 suite_trigger.cron()
800 self.assertFalse(suite_trigger.events['nightly'].should_handle)
801 self.assertFalse(suite_trigger.events['weekly'].should_handle)
802 self.assertFalse(suite_trigger.events['new_build'].should_handle)
803
804 self.assertEqual(suite_trigger.event_results, {})
805
806 def testCronTriggerNightly(self):
807 """Test nightly event is read with available nightly last_exec_time."""
808 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
809 last_exec_client = datastore_client.LastExecutionRecordStore()
810 last_exec_client.set_last_execute_time(
811 'nightly', utc_now - datetime.timedelta(hours=1))
812 self._mock_utc_now.return_value = utc_now
813 suite_trigger = trigger_receiver.TriggerReceiver()
814 self.assertTrue(suite_trigger.events['nightly'].should_handle)
815 self.assertFalse(suite_trigger.events['weekly'].should_handle)
816 self.assertFalse(suite_trigger.events['new_build'].should_handle)
817
Xixuan Wu33179672017-09-12 11:44:04 -0700818 def testCronTriggerNightlyOutdated(self):
819 """Test nightly event is read with available nightly last_exec_time."""
820 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
821 last_exec_client = datastore_client.LastExecutionRecordStore()
822 last_exec_client.set_last_execute_time(
823 'nightly', utc_now - datetime.timedelta(days=3))
824 self._mock_utc_now.return_value = utc_now
825 suite_trigger = trigger_receiver.TriggerReceiver()
826 self.assertFalse(suite_trigger.events['nightly'].should_handle)
827
828 def testCronTriggerWeeklyOutdated(self):
829 """Test weekly event is read with available weekly last_exec_time."""
830 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
831 last_exec_client = datastore_client.LastExecutionRecordStore()
832 last_exec_client.set_last_execute_time(
833 'weekly', utc_now - datetime.timedelta(days=8))
834 self._mock_utc_now.return_value = utc_now
835 suite_trigger = trigger_receiver.TriggerReceiver()
836 self.assertFalse(suite_trigger.events['weekly'].should_handle)
837
Xixuan Wu40998892017-08-29 14:32:26 -0700838 def testCronForWeeks(self):
839 """Ensure cron job can be successfully scheduled for several weeks."""
Xixuan Wu008ee832017-10-12 16:59:34 -0700840 all_tasks = self._get_ground_truth_task_list_from_config()
Xixuan Wu40998892017-08-29 14:32:26 -0700841 last_now = None
842
843 for now in now_generator(datetime.datetime.now(time_converter.UTC_TZ)):
844 self._mock_utc_now.return_value = now
845 suite_trigger = trigger_receiver.TriggerReceiver()
Xixuan Wu5451a662017-10-17 10:57:40 -0700846 with mock.patch('task.Task.schedule', return_value=True):
847 suite_trigger.cron()
Xixuan Wu40998892017-08-29 14:32:26 -0700848
Xixuan Wu40998892017-08-29 14:32:26 -0700849 should_scheduled_nightly_tasks = [
Xixuan Wu09962902018-12-11 10:49:27 -0800850 t.name for t in all_tasks['nightly'] if t.hour == now.hour]
Xixuan Wu008ee832017-10-12 16:59:34 -0700851
Xixuan Wu09962902018-12-11 10:49:27 -0800852 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700853 should_scheduled_nightly_tasks):
854 self.assertEqual(suite_trigger.event_results['nightly'],
855 should_scheduled_nightly_tasks)
856 else:
857 self.assertNotIn('nightly', suite_trigger.event_results.keys())
858
859 # Verify weekly tasks
860 should_scheduled_weekly_tasks = [
861 t.name for t in all_tasks['weekly']
Xixuan Wu09962902018-12-11 10:49:27 -0800862 if now.weekday() == t.day and now.hour == t.hour]
863 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700864 should_scheduled_weekly_tasks):
865 self.assertEqual(suite_trigger.event_results['weekly'],
866 should_scheduled_weekly_tasks)
867 else:
868 self.assertNotIn('weekly', suite_trigger.event_results.keys())
869
870 # Verify new_build tasks
871 should_scheduled_new_build_tasks = [
872 t.name for t in all_tasks['new_build']]
873 if (_should_schedule_new_build_task(last_now, now) and
874 should_scheduled_new_build_tasks):
875 self.assertEqual(suite_trigger.event_results['new_build'],
876 should_scheduled_new_build_tasks)
877 else:
878 self.assertNotIn('new_build', suite_trigger.event_results.keys())
879
880 last_now = now
881
882
883if __name__ == '__main__':
884 unittest.main()