blob: 4ba8d62b9277f53206ce32f1c54a54d74826690d [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
Xinan Lincfa41012020-04-08 13:22:03 -07008import constants
Xixuan Wu40998892017-08-29 14:32:26 -07009import datetime
10import os
11import unittest
12
Xixuan Wuc6819012019-05-23 11:34:59 -070013import build_lib
Xixuan Wu40998892017-08-29 14:32:26 -070014import 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
Xixuan Wu40998892017-08-29 14:32:26 -070031def now_generator(start_time, interval_min=30, last_days=7):
32 """A datetime.datetime.now generator.
33
34 The generator will generate 'now' from start_time till start_time+last_days
35 for every interval_min.
36
37 Args:
38 start_time: A datetime.datetime object representing the initial value of
39 the 'now'.
40 interval_min: The interval minutes between current 'now' and next 'now.
41 last_days: Representing how many days this generator will last.
42
43 Yields:
44 a datetime.datetime object to mock the current time.
45 """
46 cur_time = start_time
47 end_time = start_time + datetime.timedelta(days=last_days)
48 while cur_time < end_time:
49 yield cur_time
50 cur_time += datetime.timedelta(minutes=interval_min)
51
52
Xixuan Wu09962902018-12-11 10:49:27 -080053def _should_schedule_timed_task(last_now, now):
54 """Check whether timed (weekly/nightly) task should be scheduled.
Xixuan Wu40998892017-08-29 14:32:26 -070055
Xixuan Wu09962902018-12-11 10:49:27 -080056 A timed task should be schduled when next hour is coming.
Xixuan Wu40998892017-08-29 14:32:26 -070057
58 Args:
Xixuan Wu09962902018-12-11 10:49:27 -080059 last_now: the last time to check if timed task should be scheduled
Xixuan Wu40998892017-08-29 14:32:26 -070060 or not.
Xixuan Wu09962902018-12-11 10:49:27 -080061 now: the current time to check if timed task should be scheduled.
Xixuan Wu40998892017-08-29 14:32:26 -070062
63 Returns:
64 a boolean indicating whether there will be nightly tasks scheduled.
65 """
66 if last_now is not None and last_now.hour != now.hour:
67 return True
68
69 return False
70
71
Xixuan Wu40998892017-08-29 14:32:26 -070072def _should_schedule_new_build_task(last_now, now):
73 """Check whether weekly task should be scheduled.
74
75 A new_build task should be schduled when there're new builds between last
76 check and this check.
77
78 Args:
79 last_now: the last time to check if new_build task should be scheduled.
80 now: the current time to check if new_build task should be scheduled.
81
82 Returns:
83 a boolean indicating whether there will be new_build tasks scheduled.
84 """
85 if last_now is not None and last_now != now:
86 return True
87
88 return False
89
90
Xinan Lincfa41012020-04-08 13:22:03 -070091def _get_current_min(now):
92 """A helper to truncate the given time to minute."""
93 return datetime.datetime(
94 now.year,
95 now.month,
96 now.day,
97 now.hour,
98 now.minute,
99 tzinfo=time_converter.UTC_TZ)
100
101
Xixuan Wuc6819012019-05-23 11:34:59 -0700102class FakeBuildClient(object):
103 """Mock rest_client.BuildBucketBigqueryClient."""
104
Xinan Lin8b291982019-12-16 10:03:56 -0800105 def __init__(self):
106 self.firmware_builds_called = 0
107
Xinan Lin71eeeb02020-03-10 17:37:12 -0700108 def get_passed_builds(self, earliest, latest, event_type):
Xinan Linea1efcb2019-12-30 23:46:42 -0800109 """Mock get_passed_builds."""
110 del earliest # unused
111 del latest # unused
Xinan Lin71eeeb02020-03-10 17:37:12 -0700112 del event_type #unused
Xixuan Wuc6819012019-05-23 11:34:59 -0700113 return [
114 build_lib.BuildInfo(
115 'link', None, '62', '9868.0.0', 'link-release'),
116 build_lib.BuildInfo(
117 'zako', None, '62', '9868.0.0', 'zako-release'),
118 build_lib.BuildInfo('samus-kernelnext', None, '62',
119 '9868.0.0', 'samus-kernelnext-release'),
120 build_lib.BuildInfo(
121 'reef', None, '62', '1234.0.0', 'reef-release'),
122 build_lib.BuildInfo(
123 'coral', 'santa', '62', '9868.0.0', 'coral-release'),
124 build_lib.BuildInfo(
125 'coral', 'astronaut', '62', '9868.0.0', 'coral-release'),
126 build_lib.BuildInfo(
127 'coral', 'lava', '62', '9868.0.0', 'coral-release'),
128 ]
129
Xinan Lin71eeeb02020-03-10 17:37:12 -0700130 def get_relaxed_passed_builds(self, earliest, latest, event_type):
Xinan Linea1efcb2019-12-30 23:46:42 -0800131 """Mock get_relaxed_pased_builds."""
132 del earliest # unused
133 del latest # unused
Xinan Lin71eeeb02020-03-10 17:37:12 -0700134 del event_type #unused
Xinan Linae7d6372019-09-12 14:42:10 -0700135 return [
136 build_lib.BuildInfo('grunt', None, '63', '9968.0.0', 'grunt-release'),
137 build_lib.BuildInfo('nami', None, '62', '9867.0.0', 'nami-release'),
138 build_lib.BuildInfo('nami', 'akali', '62', '9868.0.0', 'nami-release'),
139 build_lib.BuildInfo('nami', 'bard', '62', '9866.0.0', 'nami-release'),
140 ]
Xixuan Wuc6819012019-05-23 11:34:59 -0700141
Xinan Lin028f9582019-12-11 10:55:33 -0800142 def get_latest_passed_firmware_builds(self):
143 """Mock get_passed_firmware_builds."""
Xinan Lin8b291982019-12-16 10:03:56 -0800144 self.firmware_builds_called += 1
Xinan Lin028f9582019-12-11 10:55:33 -0800145 return [
146 ['cros', 'fake_board', ('gs://chromeos-image-archive/'
147 'fake_board-release/R30-6182.0.0-rc2/'
148 'fake_board')],
149 ['firmware', 'fake_board', ('gs://chromeos-image-archive/'
150 'firmware-fake_board-12345.67.'
151 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin8b291982019-12-16 10:03:56 -0800152 ['firmware', 'zako', ('gs://chromeos-image-archive/'
153 'firmware-zako-12345.67.'
154 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin028f9582019-12-11 10:55:33 -0800155 ]
156
Xixuan Wuc6819012019-05-23 11:34:59 -0700157
Xixuan Wu40998892017-08-29 14:32:26 -0700158class FakeAndroidBuildRestClient(object):
159 """Mock rest_client.AndroidBuildRestClient."""
160
161 def get_latest_build_id(self, branch, target):
162 """Mock rest_client.AndroidBuildRestClient.get_latest_build_id."""
163 del branch, target # unused
164 return '100'
165
166
167class FakeLabConfig(object):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700168 """Mock config_reader.LabConfig."""
Xixuan Wu40998892017-08-29 14:32:26 -0700169
170 def get_android_board_list(self):
171 """Mock config_reader.LabConfig.get_android_board_list."""
172 return ('android-angler', 'android-bullhead')
173
Xixuan Wu6fb16272017-10-19 13:16:00 -0700174 def get_cros_board_list(self):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700175 """Mock config_reader.LabConfig.get_cros_board_list."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700176 return ('grunt', 'link', 'peppy', 'daisy', 'zako', 'samus-kernelnext',
Xinan Linae7d6372019-09-12 14:42:10 -0700177 'coral', 'reef', 'nami')
Xixuan Wu6fb16272017-10-19 13:16:00 -0700178
C Shapiro7f24a002017-12-05 14:25:09 -0700179 def get_cros_model_map(self):
180 """Mock config_reader.LabConfig.get_cros_model_map."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700181 return {
182 'coral': ['santa', 'astronaut'],
183 'reef': ['electro'],
Xinan Linae7d6372019-09-12 14:42:10 -0700184 'nami': ['akali', 'bard'],
Xixuan Wua41efa22019-05-17 14:28:04 -0700185 }
C Shapiro7f24a002017-12-05 14:25:09 -0700186
Xixuan Wu40998892017-08-29 14:32:26 -0700187
Xixuan Wu008ee832017-10-12 16:59:34 -0700188class TriggerReceiverBaseTestCase(unittest.TestCase):
Xixuan Wu40998892017-08-29 14:32:26 -0700189
190 def setUp(self):
191 self.testbed = testbed.Testbed()
192 self.testbed.activate()
193 self.addCleanup(self.testbed.deactivate)
194
195 self.testbed.init_datastore_v3_stub()
196 self.testbed.init_memcache_stub()
197 ndb.get_context().clear_cache()
198 self.testbed.init_taskqueue_stub(
199 root_path=os.path.join(os.path.dirname(__file__)))
200 self.taskqueue_stub = self.testbed.get_stub(
201 testbed.TASKQUEUE_SERVICE_NAME)
202
Xixuan Wuc6819012019-05-23 11:34:59 -0700203 mock_build_client = mock.patch('rest_client.BuildBucketBigqueryClient')
204 self._mock_build_client = mock_build_client.start()
205 self.addCleanup(mock_build_client.stop)
206
Xixuan Wu40998892017-08-29 14:32:26 -0700207 mock_android_client = mock.patch('rest_client.AndroidBuildRestClient')
208 self._mock_android_client = mock_android_client.start()
209 self.addCleanup(mock_android_client.stop)
210
Xixuan Wu40998892017-08-29 14:32:26 -0700211 mock_lab_config = mock.patch('config_reader.LabConfig')
212 self._mock_lab_config = mock_lab_config.start()
213 self.addCleanup(mock_lab_config.stop)
214
215 mock_utc_now = mock.patch('time_converter.utc_now')
216 self._mock_utc_now = mock_utc_now.start()
217 self.addCleanup(mock_utc_now.stop)
218
Xixuan Wuc6819012019-05-23 11:34:59 -0700219 self._mock_build_client.return_value = FakeBuildClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700220 self._mock_android_client.return_value = FakeAndroidBuildRestClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700221 self._mock_lab_config.return_value = FakeLabConfig()
222
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700223 board_family_patcher = mock.patch(
224 'build_lib.get_board_family_mapping_from_gs')
225 board_family_getter = board_family_patcher.start()
226 board_family_getter.return_value = {
227 'nyan': ['nyan', 'nyan_blaze', 'nyan_big'],
228 'ivybridge': ['link', 'link_freon']}
229 self.addCleanup(board_family_patcher.stop)
230
Xixuan Wu008ee832017-10-12 16:59:34 -0700231
232class TriggerReceiverFakeConfigTestCase(TriggerReceiverBaseTestCase):
233
234 _TEST_PST_HOUR = 20
235 _TEST_PST_DAY = 4 # Friday
236 _TEST_EVENT_PST_HOUR = 13
237
238 _FAKE_NIGHTLY_TASK_NAME = 'fake_nightly_task'
239 _FAKE_WEEKLY_TASK_NAME = 'fake_weekly_task'
240
241 def setUp(self):
242 super(TriggerReceiverFakeConfigTestCase, self).setUp()
243
244 self.fake_config = config_reader.ConfigReader(None)
245 self._add_nightly_tasks(self.fake_config)
246 self._add_weekly_tasks(self.fake_config)
247
248 self.fake_config_with_settings = config_reader.ConfigReader(None)
249 self._add_weekly_tasks(self.fake_config_with_settings)
250 self._add_weekly_params(self.fake_config_with_settings)
251
252 mock_config_reader = mock.patch('config_reader.ConfigReader')
253 self._mock_config_reader = mock_config_reader.start()
254 self.addCleanup(mock_config_reader.stop)
255
256 def _add_nightly_tasks(self, fake_config):
257 fake_config.add_section(self._FAKE_NIGHTLY_TASK_NAME)
258 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'suite', 'fake_suite')
259 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'run_on', 'nightly')
260 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'hour',
261 str(self._TEST_PST_HOUR))
262
263 def _add_weekly_tasks(self, fake_config):
264 fake_config.add_section(self._FAKE_WEEKLY_TASK_NAME)
265 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'suite', 'fake_suite')
266 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'run_on', 'weekly')
267 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'day', str(self._TEST_PST_DAY))
268
269 def _add_weekly_params(self, fake_config):
Xixuan Wu51bb7102019-03-18 14:51:44 -0700270 weekly_section_name = task_config_reader.EVENT_CLASSES[
271 'weekly'].section_name()
Xixuan Wu008ee832017-10-12 16:59:34 -0700272 fake_config.add_section(weekly_section_name)
273 fake_config.set(weekly_section_name, 'hour', str(self._TEST_EVENT_PST_HOUR))
274
275 def testInitializeTriggerReceiverWithNightlyEvent(self):
276 """Test nightly event can be handled on right hour."""
277 # A task with hour=20 should be scheduled at 20:00 in PST everyday, which
278 # is 3:00/4:00 in UTC everyday.
279 self._mock_config_reader.return_value = self.fake_config
280 given_utc_hour = time_converter.convert_time_info(
281 time_converter.TimeInfo(None, self._TEST_PST_HOUR)).hour
282 utc_now = datetime.datetime(2017, 8, 6, given_utc_hour,
283 tzinfo=time_converter.UTC_TZ)
284 last_exec_client = datastore_client.LastExecutionRecordStore()
285 last_exec_client.set_last_execute_time(
286 'nightly', utc_now - datetime.timedelta(hours=1))
287 self._mock_utc_now.return_value = utc_now
288
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600289 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700290 suite_trigger.cron()
291 self.assertTrue(suite_trigger.events['nightly'].should_handle)
292 self.assertEqual(len(suite_trigger.event_results['nightly']), 1)
293 self.assertEqual(suite_trigger.event_results['nightly'][0],
294 self._FAKE_NIGHTLY_TASK_NAME)
295
296 def testInitializeTriggerReceiverWithWeeklyEventWithoutEventHour(self):
297 """Test weekly event without event settings can be handled on right day."""
298 # A task with day=4 (Friday) and default event_hour (23) should be
299 # scheduled at Friday 23:00 in PST, which is Saturday 6:00 or 7:00 in UTC.
300 self._mock_config_reader.return_value = self.fake_config
301 given_utc_hour = time_converter.convert_time_info(
302 time_converter.TimeInfo(
303 self._TEST_PST_DAY,
Xixuan Wu51bb7102019-03-18 14:51:44 -0700304 task_config_reader.EVENT_CLASSES['weekly'].DEFAULT_PST_HOUR)).hour
Xixuan Wu008ee832017-10-12 16:59:34 -0700305 utc_now = datetime.datetime(2017, 10, 14, given_utc_hour,
306 tzinfo=time_converter.UTC_TZ)
307 last_exec_client = datastore_client.LastExecutionRecordStore()
308 last_exec_client.set_last_execute_time(
309 'weekly', utc_now - datetime.timedelta(days=1))
310 self._mock_utc_now.return_value = utc_now
311
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600312 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700313 suite_trigger.cron()
314 self.assertTrue(suite_trigger.events['weekly'].should_handle)
315 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
316 self.assertEqual(suite_trigger.event_results['weekly'][0],
317 self._FAKE_WEEKLY_TASK_NAME)
318
319 def testInitializeTriggerReceiverWithWeeklyEventWithEventHour(self):
320 """Test weekly event with event settings can be handled on right day."""
321 # A task with day=4 (Friday) and event_hour=13 should be scheduled at
322 # Friday 13:00 in PST, which is Friday 20:00 or 21:00 in UTC.
323 self._mock_config_reader.return_value = self.fake_config_with_settings
324 given_utc_time_info = time_converter.convert_time_info(
325 time_converter.TimeInfo(self._TEST_PST_DAY, self._TEST_EVENT_PST_HOUR))
326
327 # Set the current time as a Friday 20:00 or 21:00 in UTC.
328 utc_now = datetime.datetime(2017, 10, 13, given_utc_time_info.hour,
329 tzinfo=time_converter.UTC_TZ)
330 last_exec_client = datastore_client.LastExecutionRecordStore()
331 last_exec_client.set_last_execute_time(
332 'weekly', utc_now - datetime.timedelta(days=1))
333 self._mock_utc_now.return_value = utc_now
334
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600335 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700336 suite_trigger.cron()
337 self.assertTrue(suite_trigger.events['weekly'].should_handle)
338 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
339 self.assertEqual(suite_trigger.event_results['weekly'][0],
340 self._FAKE_WEEKLY_TASK_NAME)
341
342
Craig Bergstrom58263d32018-04-26 14:11:35 -0600343class TriggerReceiverFakeBuildTestCase(TriggerReceiverBaseTestCase):
344 """Test the new_build functionality."""
345
Craig Bergstrom58263d32018-04-26 14:11:35 -0600346 def setUp(self):
347 """Set up for a test."""
348 super(TriggerReceiverFakeBuildTestCase, self).setUp()
349
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700350 self._prepare()
351
352 def _prepare(self):
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600353 self.reader = config_reader.ConfigReader(None)
354 self.fake_config = self.reader
Craig Bergstrom58263d32018-04-26 14:11:35 -0600355 mock_config_reader = mock.patch('config_reader.ConfigReader')
356 self._mock_config_reader = mock_config_reader.start()
357 self.addCleanup(mock_config_reader.stop)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600358
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700359 # Set last execution time for new_build events.
360 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600361 last_exec_client = datastore_client.LastExecutionRecordStore()
362 last_exec_client.set_last_execute_time(
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700363 'new_build', utc_now - datetime.timedelta(hours=1))
Craig Bergstrom58263d32018-04-26 14:11:35 -0600364 self._mock_utc_now.return_value = utc_now
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700365
366 def testNewBuildForHWTestSanityRequired(self):
367 """Test the new_build functionality."""
368 # Construct a fake config with only_hwtest_sanity_required.
369 fsnbt_name = 'FakeStrictNewBuildTask'
370 self.fake_config.add_section(fsnbt_name)
371 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
372 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700373 self.fake_config.set(fsnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700374 frnbt_name = 'FakeRelaxedNewBuildTask'
375 self.fake_config.add_section(frnbt_name)
376 self.fake_config.set(frnbt_name, 'run_on', 'new_build')
377 self.fake_config.set(frnbt_name, 'suite', 'fake_suite_relaxed')
378 self.fake_config.set(frnbt_name, 'only_hwtest_sanity_required', 'True')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700379 self.fake_config.set(frnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700380
381 self._mock_config_reader.return_value = self.fake_config
Craig Bergstrom58263d32018-04-26 14:11:35 -0600382
383 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600384 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600385 suite_trigger.cron()
386
387 # Validate that the expected tests got kicked off.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600388 self.assertEqual(len(suite_trigger.event_results), 1)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600389 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000390 # 2 for strict passed builds, 3 for relaxed builds.
391 self.assertEqual(len(tasks), 5)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600392
393 # The number of builds that matched the base (success) Task.
394 count_base = 0
395 # The number of builds that matched the relaxed Task.
396 count_relaxed = 0
397 for task in tasks:
398 if 'fake_suite_base' in task.payload:
399 # Make sure it matched the expected build only.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600400 self.assertNotIn('grunt-release', task.payload)
401 count_base += 1
402
403 if 'fake_suite_relaxed' in task.payload:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600404 count_relaxed += 1
405
406 # Make each case matched precisely one event.
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000407 self.assertEqual(2, count_base)
408 self.assertEqual(3, count_relaxed)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600409
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700410 def testNewBuildWithExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700411 """Test the new_build suite with an existing board family."""
412 link_suite = 'FakeLinkNewBuildTask'
413 self.fake_config.add_section(link_suite)
414 self.fake_config.set(link_suite, 'run_on', 'new_build')
415 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700416 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700417 self._mock_config_reader.return_value = self.fake_config
418
419 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600420 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700421 suite_trigger.cron()
422
423 self.assertEqual(len(suite_trigger.event_results), 1)
424 self.assertEqual(suite_trigger.event_results['new_build'],
425 [link_suite])
426 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
427 self.assertEqual(len(tasks), 1)
428 self.assertIn('link-release', tasks[0].payload)
429
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700430 def testNewBuildWithExistingBoardFamiliesAndBoards(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700431 """Test the new_build suite with an existing board family."""
432 link_suite = 'FakeLinkNewBuildTask'
433 self.fake_config.add_section(link_suite)
434 self.fake_config.set(link_suite, 'run_on', 'new_build')
435 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700436 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700437 self.fake_config.set(link_suite, 'boards', 'asuka, paine, banon')
438 self._mock_config_reader.return_value = self.fake_config
439
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600440 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700441 suite_trigger.cron()
442
443 self.assertEqual(len(suite_trigger.event_results), 1)
444 self.assertEqual(suite_trigger.event_results['new_build'],
445 [link_suite])
446 boards = suite_trigger.events['new_build'].task_list[0].boards
447 self.assertIn('asuka', boards)
448 self.assertIn('link', boards)
449
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700450 def testNewBuildWithNonExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700451 """Test the new_build suite with an non-existing board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700452 nyan_suite = 'FakeNonExistBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700453 self.fake_config.add_section(nyan_suite)
454 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
455 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700456 self.fake_config.set(nyan_suite, 'board_families', 'nyan')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700457 self._mock_config_reader.return_value = self.fake_config
458
459 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600460 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700461 suite_trigger.cron()
462
463 self.assertEqual(len(suite_trigger.event_results), 1)
464 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
465 self.assertEqual(len(tasks), 0)
466
467 def testNewBuildWithNonSpecifiedBoardFamily(self):
468 """Test the new_build suite with an non-specified board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700469 normal_suite = 'FakeBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700470 self.fake_config.add_section(normal_suite)
471 self.fake_config.set(normal_suite, 'run_on', 'new_build')
472 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700473 self.fake_config.set(normal_suite, 'boards', 'link, zako')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700474 self._mock_config_reader.return_value = self.fake_config
475
476 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600477 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700478 suite_trigger.cron()
479
480 self.assertEqual(len(suite_trigger.event_results), 1)
481 self.assertEqual(suite_trigger.event_results['new_build'],
482 [normal_suite])
483 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000484 self.assertEqual(len(tasks), 2)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700485
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700486 def testNewBuildExcludingExistingBoardFamilies(self):
487 """Test the new_build suite excluding an existing board family."""
488 link_suite = 'FakeLinkNewBuildTask'
489 self.fake_config.add_section(link_suite)
490 self.fake_config.set(link_suite, 'run_on', 'new_build')
491 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
492 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700493 self.fake_config.set(link_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700494 self._mock_config_reader.return_value = self.fake_config
495
496 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600497 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700498 suite_trigger.cron()
499
500 self.assertEqual(len(suite_trigger.event_results), 1)
501 self.assertEqual(suite_trigger.event_results['new_build'],
502 [link_suite])
503 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
504 self.assertEqual(len(tasks), 1)
505 self.assertNotIn('link-release', tasks[0].payload)
506 self.assertIn('zako-release', tasks[0].payload)
507
508 def testNewBuildExcludingExistingBoardFamiliesAndBoards(self):
509 """Test the new_build suite with an existing board family."""
510 link_suite = 'FakeLinkNewBuildTask'
511 self.fake_config.add_section(link_suite)
512 self.fake_config.set(link_suite, 'run_on', 'new_build')
513 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
514 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wua41efa22019-05-17 14:28:04 -0700515 self.fake_config.set(link_suite, 'exclude_boards',
Xinan Lin09a628a2019-11-01 17:20:27 -0700516 'asuka, paine, banon, coral, reef, nami, samus-kernelnext')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700517 self._mock_config_reader.return_value = self.fake_config
518
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600519 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700520 suite_trigger.cron()
521
522 self.assertEqual(len(suite_trigger.event_results), 1)
523 self.assertEqual(suite_trigger.event_results['new_build'],
524 [link_suite])
525 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
526 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Xinan Lin09a628a2019-11-01 17:20:27 -0700527 self.assertEqual(len(tasks), 1)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700528 self.assertNotIn('link-release', tasks[0].payload)
529 self.assertNotIn('asuka-release', tasks[0].payload)
530 self.assertIn('zako-release', tasks[0].payload)
531
532 def testNewBuildExcludingNonExistingBoardFamilies(self):
533 """Test the new_build suite excluding an non-existing board family."""
534 nyan_suite = 'FakeNonExistExcludeBoardFamiliesNewBuildTask'
535 self.fake_config.add_section(nyan_suite)
536 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
537 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
538 self.fake_config.set(nyan_suite, 'exclude_board_families', 'nyan')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700539 self.fake_config.set(nyan_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700540 self._mock_config_reader.return_value = self.fake_config
541
542 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600543 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700544 suite_trigger.cron()
545
546 self.assertEqual(len(suite_trigger.event_results), 1)
547 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
548 self.assertEqual(len(tasks), 2)
549
550 def testNewBuildWithBoardExcludeBoardCollision(self):
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700551 """Test the case that the same board in boards and exclude_boards."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700552 normal_suite = 'FakeBoardExludingBoardCollisionNewBuildTask'
553 self.fake_config.add_section(normal_suite)
554 self.fake_config.set(normal_suite, 'run_on', 'new_build')
555 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
556 self.fake_config.set(normal_suite, 'boards', 'zako, asuka')
557 self.fake_config.set(normal_suite, 'exclude_boards', 'asuka')
558 self._mock_config_reader.return_value = self.fake_config
559
560 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600561 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700562 suite_trigger.cron()
563
564 self.assertEqual(len(suite_trigger.event_results), 1)
565 self.assertEqual(suite_trigger.event_results['new_build'],
566 [normal_suite])
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700567 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
568 self.assertEqual(len(tasks), 1)
569 self.assertNotIn('asuka-release', tasks[0].payload)
570 self.assertIn('zako-release', tasks[0].payload)
571
Xixuan Wub4b2f412019-05-03 11:22:31 -0700572 def testNewBuildWithKernelnext(self):
573 """Test the case that suites run with board-kernelnext build."""
574 normal_suite = 'FakeKernelnextSuite'
575 self.fake_config.add_section(normal_suite)
576 self.fake_config.set(normal_suite, 'run_on', 'new_build')
577 self.fake_config.set(normal_suite, 'suite', 'fake-suite')
578 self.fake_config.set(normal_suite, 'pool', 'suites')
579 self.fake_config.set(normal_suite, 'boards', 'samus-kernelnext')
580 self._mock_config_reader.return_value = self.fake_config
581
Xixuan Wub4b2f412019-05-03 11:22:31 -0700582 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600583 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wub4b2f412019-05-03 11:22:31 -0700584 suite_trigger.cron()
585
586 self.assertEqual(len(suite_trigger.event_results), 1)
587 self.assertEqual(suite_trigger.event_results['new_build'],
588 [normal_suite])
589 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
590 self.assertEqual(len(tasks), 1)
591 # Board should be 'samus'.
592 self.assertIn('&board=samus&', tasks[0].payload)
593 # Build should be 'samus-kernelnext-release***'.
594 self.assertIn('cros_version=samus-kernelnext-release', tasks[0].payload)
595
Xixuan Wua41efa22019-05-17 14:28:04 -0700596 def testNewBuildWithModels(self):
597 """Test the new_build suite with an existing models entry."""
598 normal_suite = 'FakeModelsNewBuildTask'
599 self.fake_config.add_section(normal_suite)
600 self.fake_config.set(normal_suite, 'run_on', 'new_build')
601 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
602 self.fake_config.set(normal_suite, 'models', 'coral_lava, coral_santa')
603 self.fake_config.set(normal_suite, 'boards', 'coral')
604 self._mock_config_reader.return_value = self.fake_config
605
606 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600607 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700608 suite_trigger.cron()
609
610 self.assertEqual(len(suite_trigger.event_results), 1)
611 self.assertEqual(suite_trigger.event_results['new_build'],
612 [normal_suite])
613 self.assertIn('new_build', suite_trigger.event_results)
614 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
615 self.assertEqual(len(tasks), 1)
616 self.assertNotIn('model=astronaut', tasks[0].payload)
617 self.assertIn('model=santa', tasks[0].payload)
618
Xinan Linae7d6372019-09-12 14:42:10 -0700619 def testNewBuildWithModelsForHWTestSanityRequired(self):
620 """Test the new_build suite with an existing models entry."""
621 normal_suite = 'FakeModelsNewBuildTask'
622 self.fake_config.add_section(normal_suite)
623 self.fake_config.set(normal_suite, 'run_on', 'new_build')
624 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
625 self.fake_config.set(normal_suite, 'models', 'nami_akali, nami_bard')
626 self.fake_config.set(normal_suite, 'boards', 'nami')
627 self.fake_config.set(normal_suite, 'only_hwtest_sanity_required', 'True')
628 self._mock_config_reader.return_value = self.fake_config
629
630 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600631 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Linae7d6372019-09-12 14:42:10 -0700632 suite_trigger.cron()
633
634 self.assertEqual(len(suite_trigger.event_results), 1)
635 self.assertEqual(suite_trigger.event_results['new_build'],
636 [normal_suite])
637 self.assertIn('new_build', suite_trigger.event_results)
638 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
639 self.assertEqual(len(tasks), 2)
640 self.assertIn('model=akali', tasks[0].payload)
641 self.assertIn('9868.0.0', tasks[0].payload)
642 self.assertIn('model=bard', tasks[1].payload)
643 self.assertIn('9867.0.0', tasks[1].payload)
644
Xixuan Wua41efa22019-05-17 14:28:04 -0700645 def testNewBuildWithExcludeModels(self):
646 """Test the new_build suite with an existing exclude_models entry."""
647 normal_suite = 'FakeExludingModelsNewBuildTask'
648 self.fake_config.add_section(normal_suite)
649 self.fake_config.set(normal_suite, 'run_on', 'new_build')
650 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
651 self.fake_config.set(normal_suite, 'exclude_models',
652 'coral_lava, coral_santa')
653 self.fake_config.set(normal_suite, 'boards', 'coral')
654 self._mock_config_reader.return_value = self.fake_config
655
656 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600657 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700658 suite_trigger.cron()
659
660 self.assertEqual(len(suite_trigger.event_results), 1)
661 self.assertEqual(suite_trigger.event_results['new_build'],
662 [normal_suite])
663 self.assertIn('new_build', suite_trigger.event_results)
664 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
665 self.assertEqual(len(tasks), 1)
666 self.assertNotIn('model=santa', tasks[0].payload)
667 self.assertIn('model=astronaut', tasks[0].payload)
668
669 def testNewBuildWithModelsExcludeModels(self):
670 """Test the new_build suite with models and exclude_models entry."""
671 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
672 self.fake_config.add_section(normal_suite)
673 self.fake_config.set(normal_suite, 'run_on', 'new_build')
674 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
675 self.fake_config.set(normal_suite, 'models', 'coral_santa, coral_astronaut')
676 self.fake_config.set(normal_suite, 'exclude_models',
677 'coral_lava, coral_santa')
678 self.fake_config.set(normal_suite, 'boards', 'coral')
679 self._mock_config_reader.return_value = self.fake_config
680
681 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600682 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700683 suite_trigger.cron()
684
685 self.assertEqual(len(suite_trigger.event_results), 1)
686 self.assertEqual(suite_trigger.event_results['new_build'],
687 [normal_suite])
688 self.assertIn('new_build', suite_trigger.event_results)
689 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
690 self.assertEqual(len(tasks), 1)
691 self.assertNotIn('model=santa', tasks[0].payload)
692 self.assertIn('model=astronaut', tasks[0].payload)
693
694 def testNewBuildWithNoModelListAndModelBuild(self):
695 """Test the new_build suite with models and empty board_model mapping."""
696 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
697 self.fake_config.add_section(normal_suite)
698 self.fake_config.set(normal_suite, 'run_on', 'new_build')
699 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
700 self.fake_config.set(normal_suite, 'boards', 'coral')
701 self._mock_config_reader.return_value = self.fake_config
702
703 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600704 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700705 suite_trigger.cron()
706
707 self.assertIn('new_build', suite_trigger.event_results)
708 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
709 # Verify that coral-release is not kicked off on model lava as lava is not
710 # listed in cros_model_map.
711 self.assertEqual(len(tasks), 2)
712 self.assertNotIn('lava', tasks[0].payload)
713 self.assertNotIn('lava', tasks[1].payload)
714
715 def testNewBuildWithNoModelListAndNoModelBuild(self):
716 """Test the new_build suite with models and empty board_model mapping."""
717 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
718 self.fake_config.add_section(normal_suite)
719 self.fake_config.set(normal_suite, 'run_on', 'new_build')
720 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
721 self.fake_config.set(normal_suite, 'boards', 'reef')
722 self._mock_config_reader.return_value = self.fake_config
723
724 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600725 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700726 suite_trigger.cron()
727
728 self.assertIn('new_build', suite_trigger.event_results)
729 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
730 # Verify that reef-release is kicked off on reef models.
731 self.assertEqual(len(tasks), 1)
732 self.assertIn('model=electro', tasks[0].payload)
733
C Shapiro09108252019-08-01 14:52:52 -0500734 def testNewBuildWithAnyModel(self):
735 """Test the new_build suite with any_model option set."""
736 normal_suite = 'FakeAnyModelNewBuildTask'
737 self.fake_config.add_section(normal_suite)
738 self.fake_config.set(normal_suite, 'run_on', 'new_build')
739 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
740 self.fake_config.set(normal_suite, 'any_model', 'True')
741 self.fake_config.set(normal_suite, 'boards', 'coral')
742 self._mock_config_reader.return_value = self.fake_config
743
744 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600745 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
C Shapiro09108252019-08-01 14:52:52 -0500746 suite_trigger.cron()
747
748 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
749 self.assertEqual(len(tasks), 1)
750 self.assertIn('model=None', tasks[0].payload)
751
Xinan Lin8b291982019-12-16 10:03:56 -0800752 def testNewBuildWithFirmwareTask(self):
753 """Test the new_build suite with firmware option set."""
754 # Construct a fake config with firmware build.
755 fsnbt_name = 'FakeStrictNewBuildTask'
756 self.fake_config.add_section(fsnbt_name)
757 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
758 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
759 self.fake_config.set(fsnbt_name, 'boards', 'zako')
760 self.fake_config.set(fsnbt_name, 'firmware_ro_build_spec', 'firmware')
761 self.fake_config.set(fsnbt_name, 'test_source', 'cros')
762 self._mock_config_reader.return_value = self.fake_config
763
764 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600765 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800766 some_event = suite_trigger.events['new_build']
767 suite_trigger.cron()
768
769 # The firmware query has run for once.
770 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 1)
771 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
772 self.assertEqual(len(tasks), 1)
773 self.assertIn('firmware-zako-12345.67', tasks[0].payload)
774
775
776 def testNewBuildWithoutFirmwareTask(self):
777 """Test the event skips fetch the firmware builds."""
778 # Construct a fake config without firmware build.
779 fsnbt_name = 'FakeStrictNewBuildTask'
780 self.fake_config.add_section(fsnbt_name)
781 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
782 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
783 self.fake_config.set(fsnbt_name, 'boards', 'zako')
784 self._mock_config_reader.return_value = self.fake_config
785
786 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600787 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800788 suite_trigger.cron()
789
790 # The firmware query was not called.
791 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 0)
792 # Validate that the expected tests got kicked off.
793 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
794 self.assertEqual(len(tasks), 1)
795
Craig Bergstrom58263d32018-04-26 14:11:35 -0600796
Xixuan Wu008ee832017-10-12 16:59:34 -0700797class TriggerReceiverRealConfigTestCase(TriggerReceiverBaseTestCase):
798
799 def setUp(self):
800 super(TriggerReceiverRealConfigTestCase, self).setUp()
801 mock_config_reader = mock.patch('config_reader.ConfigReader')
802 self._mock_config_reader = mock_config_reader.start()
803 self.addCleanup(mock_config_reader.stop)
804 self._mock_config_reader.return_value = _SUITE_CONFIG_READER
805
806 def _get_ground_truth_task_list_from_config(self):
807 """Get the ground truth of to-be-scheduled task list from config file."""
808 self._mock_utc_now.return_value = datetime.datetime.now(
809 time_converter.UTC_TZ)
Xixuan Wu51bb7102019-03-18 14:51:44 -0700810 task_config = task_config_reader.TaskConfig(_SUITE_CONFIG_READER)
Xixuan Wu008ee832017-10-12 16:59:34 -0700811 tasks = {}
Xixuan Wu51bb7102019-03-18 14:51:44 -0700812 for keyword, klass in task_config_reader.EVENT_CLASSES.iteritems():
Xixuan Wu008ee832017-10-12 16:59:34 -0700813 new_event = klass(
814 task_config.get_event_setting(klass.section_name()), None)
815 new_event.set_task_list(
816 task_config.get_tasks_by_keyword(klass.KEYWORD)['tasks'])
817 tasks[keyword] = new_event.task_list
818
819 return tasks
820
Xinan Lincfa41012020-04-08 13:22:03 -0700821 def testEventShouldScanNewBuildFromSinceDateToTargetDate(self):
822 """Test the event should scan new builds from last_exec to target_exec."""
823 _utc_now = datetime.datetime.now(time_converter.UTC_TZ)
824 # utc_now() should be called only 3 times for the creation of Weekly,
825 # Nightly or New_Build event.
826 self._mock_utc_now.side_effect = [_utc_now, _utc_now, _utc_now]
827 target_exec_utc = _get_current_min(_utc_now)
828 since_date = target_exec_utc - datetime.timedelta(hours=1)
829 last_exec_client = datastore_client.LastExecutionRecordStore()
830 last_exec_client.set_last_execute_time('new_build', since_date)
831 delay_minutes = datetime.timedelta(
832 minutes=constants.BaseEvent.DELAY_MINUTES)
833 with mock.patch(
834 'build_lib.get_cros_builds',
835 return_value=({}, {})) as mock_get_cros_builds:
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600836 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lincfa41012020-04-08 13:22:03 -0700837 suite_trigger.cron()
838 # The new CrOS builds we fetched should be created within
839 # the specified time span.
840 mock_get_cros_builds.assert_called_once_with(
841 mock.ANY, mock.ANY, since_date - delay_minutes,
842 target_exec_utc - delay_minutes, 'new_build')
843
Xixuan Wu40998892017-08-29 14:32:26 -0700844 def testCronWithoutLastExec(self):
845 """Test the first round of cron can be successfully executed."""
846 self._mock_utc_now.return_value = datetime.datetime.now(
847 time_converter.UTC_TZ)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600848 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700849 suite_trigger.cron()
850 self.assertFalse(suite_trigger.events['nightly'].should_handle)
851 self.assertFalse(suite_trigger.events['weekly'].should_handle)
852 self.assertFalse(suite_trigger.events['new_build'].should_handle)
853
854 self.assertEqual(suite_trigger.event_results, {})
855
856 def testCronTriggerNightly(self):
857 """Test nightly event is read with available nightly last_exec_time."""
858 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
859 last_exec_client = datastore_client.LastExecutionRecordStore()
860 last_exec_client.set_last_execute_time(
861 'nightly', utc_now - datetime.timedelta(hours=1))
862 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600863 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700864 self.assertTrue(suite_trigger.events['nightly'].should_handle)
865 self.assertFalse(suite_trigger.events['weekly'].should_handle)
866 self.assertFalse(suite_trigger.events['new_build'].should_handle)
867
Xixuan Wu33179672017-09-12 11:44:04 -0700868 def testCronTriggerNightlyOutdated(self):
869 """Test nightly event is read with available nightly last_exec_time."""
870 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
871 last_exec_client = datastore_client.LastExecutionRecordStore()
872 last_exec_client.set_last_execute_time(
873 'nightly', utc_now - datetime.timedelta(days=3))
874 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600875 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu33179672017-09-12 11:44:04 -0700876 self.assertFalse(suite_trigger.events['nightly'].should_handle)
877
878 def testCronTriggerWeeklyOutdated(self):
879 """Test weekly event is read with available weekly last_exec_time."""
880 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
881 last_exec_client = datastore_client.LastExecutionRecordStore()
882 last_exec_client.set_last_execute_time(
883 'weekly', utc_now - datetime.timedelta(days=8))
884 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600885 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu33179672017-09-12 11:44:04 -0700886 self.assertFalse(suite_trigger.events['weekly'].should_handle)
887
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000888 def testCronForADay(self):
889 """Ensure cron job can be successfully scheduled for a day."""
Xixuan Wu008ee832017-10-12 16:59:34 -0700890 all_tasks = self._get_ground_truth_task_list_from_config()
Xixuan Wu40998892017-08-29 14:32:26 -0700891 last_now = None
892
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000893 for now in now_generator(datetime.datetime.now(time_converter.UTC_TZ),
894 last_days=1):
Xixuan Wu40998892017-08-29 14:32:26 -0700895 self._mock_utc_now.return_value = now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600896 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu5451a662017-10-17 10:57:40 -0700897 with mock.patch('task.Task.schedule', return_value=True):
898 suite_trigger.cron()
Xixuan Wu40998892017-08-29 14:32:26 -0700899
Xixuan Wu40998892017-08-29 14:32:26 -0700900 should_scheduled_nightly_tasks = [
Xixuan Wu09962902018-12-11 10:49:27 -0800901 t.name for t in all_tasks['nightly'] if t.hour == now.hour]
Xixuan Wu008ee832017-10-12 16:59:34 -0700902
Xixuan Wu09962902018-12-11 10:49:27 -0800903 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700904 should_scheduled_nightly_tasks):
905 self.assertEqual(suite_trigger.event_results['nightly'],
906 should_scheduled_nightly_tasks)
907 else:
908 self.assertNotIn('nightly', suite_trigger.event_results.keys())
909
910 # Verify weekly tasks
911 should_scheduled_weekly_tasks = [
912 t.name for t in all_tasks['weekly']
Xixuan Wu09962902018-12-11 10:49:27 -0800913 if now.weekday() == t.day and now.hour == t.hour]
914 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700915 should_scheduled_weekly_tasks):
916 self.assertEqual(suite_trigger.event_results['weekly'],
917 should_scheduled_weekly_tasks)
918 else:
919 self.assertNotIn('weekly', suite_trigger.event_results.keys())
920
921 # Verify new_build tasks
922 should_scheduled_new_build_tasks = [
923 t.name for t in all_tasks['new_build']]
924 if (_should_schedule_new_build_task(last_now, now) and
925 should_scheduled_new_build_tasks):
926 self.assertEqual(suite_trigger.event_results['new_build'],
927 should_scheduled_new_build_tasks)
928 else:
929 self.assertNotIn('new_build', suite_trigger.event_results.keys())
930
931 last_now = now
932
933
934if __name__ == '__main__':
935 unittest.main()