blob: 2f8f351bd9f556705635bf9073cfd68930254746 [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'),
Jack Neus8f0edb42022-03-17 20:21:39 +0000128 build_lib.BuildInfo(
Jack Neus2cbdc432022-06-24 20:21:30 +0000129 'atlas-kernelnext', None, '60', '8500.0.0', 'atlas-kernelnext-release'),
130 build_lib.BuildInfo(
Jack Neus8f0edb42022-03-17 20:21:39 +0000131 'atlas-kernelnext', None, '62', '9868.0.0', 'atlas-kernelnext-release'),
132 ]
133
134 def get_passed_rubik_builds(self, earliest, latest, event_type):
135 """Mock get_passed_rubik_builds."""
136 del earliest # unused
137 del latest # unused
138 del event_type #unused
139 return [
140 build_lib.BuildInfo(
Jack Neus2cbdc432022-06-24 20:21:30 +0000141 'atlas-kernelnext', None, '60', '8501.0.0', 'atlas-kernelnext-release'),
142 build_lib.BuildInfo(
Jack Neus8f0edb42022-03-17 20:21:39 +0000143 'atlas-kernelnext', None, '62', '9869.0.0', 'atlas-kernelnext-release'),
144 build_lib.BuildInfo(
145 'coral', 'lava', '62', '9869.0.0', 'coral-release'),
Xixuan Wuc6819012019-05-23 11:34:59 -0700146 ]
147
Xinan Lin71eeeb02020-03-10 17:37:12 -0700148 def get_relaxed_passed_builds(self, earliest, latest, event_type):
Xinan Linea1efcb2019-12-30 23:46:42 -0800149 """Mock get_relaxed_pased_builds."""
150 del earliest # unused
151 del latest # unused
Xinan Lin71eeeb02020-03-10 17:37:12 -0700152 del event_type #unused
Xinan Linae7d6372019-09-12 14:42:10 -0700153 return [
154 build_lib.BuildInfo('grunt', None, '63', '9968.0.0', 'grunt-release'),
155 build_lib.BuildInfo('nami', None, '62', '9867.0.0', 'nami-release'),
156 build_lib.BuildInfo('nami', 'akali', '62', '9868.0.0', 'nami-release'),
157 build_lib.BuildInfo('nami', 'bard', '62', '9866.0.0', 'nami-release'),
158 ]
Xixuan Wuc6819012019-05-23 11:34:59 -0700159
Xinan Lin028f9582019-12-11 10:55:33 -0800160 def get_latest_passed_firmware_builds(self):
161 """Mock get_passed_firmware_builds."""
Xinan Lin8b291982019-12-16 10:03:56 -0800162 self.firmware_builds_called += 1
Xinan Lin028f9582019-12-11 10:55:33 -0800163 return [
164 ['cros', 'fake_board', ('gs://chromeos-image-archive/'
165 'fake_board-release/R30-6182.0.0-rc2/'
166 'fake_board')],
167 ['firmware', 'fake_board', ('gs://chromeos-image-archive/'
168 'firmware-fake_board-12345.67.'
169 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin8b291982019-12-16 10:03:56 -0800170 ['firmware', 'zako', ('gs://chromeos-image-archive/'
171 'firmware-zako-12345.67.'
172 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin028f9582019-12-11 10:55:33 -0800173 ]
174
Xixuan Wuc6819012019-05-23 11:34:59 -0700175
Xixuan Wu40998892017-08-29 14:32:26 -0700176class FakeAndroidBuildRestClient(object):
177 """Mock rest_client.AndroidBuildRestClient."""
178
179 def get_latest_build_id(self, branch, target):
180 """Mock rest_client.AndroidBuildRestClient.get_latest_build_id."""
181 del branch, target # unused
182 return '100'
183
184
185class FakeLabConfig(object):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700186 """Mock config_reader.LabConfig."""
Xixuan Wu40998892017-08-29 14:32:26 -0700187
188 def get_android_board_list(self):
189 """Mock config_reader.LabConfig.get_android_board_list."""
190 return ('android-angler', 'android-bullhead')
191
Xixuan Wu6fb16272017-10-19 13:16:00 -0700192 def get_cros_board_list(self):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700193 """Mock config_reader.LabConfig.get_cros_board_list."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700194 return ('grunt', 'link', 'peppy', 'daisy', 'zako', 'samus-kernelnext',
Jack Neus8f0edb42022-03-17 20:21:39 +0000195 'coral', 'reef', 'nami', 'atlas-kernelnext', 'kevin-kernelnext')
Xixuan Wu6fb16272017-10-19 13:16:00 -0700196
C Shapiro7f24a002017-12-05 14:25:09 -0700197 def get_cros_model_map(self):
198 """Mock config_reader.LabConfig.get_cros_model_map."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700199 return {
200 'coral': ['santa', 'astronaut'],
201 'reef': ['electro'],
Xinan Linae7d6372019-09-12 14:42:10 -0700202 'nami': ['akali', 'bard'],
Xixuan Wua41efa22019-05-17 14:28:04 -0700203 }
C Shapiro7f24a002017-12-05 14:25:09 -0700204
Xixuan Wu40998892017-08-29 14:32:26 -0700205
Jack Neus8f0edb42022-03-17 20:21:39 +0000206class FakeRubikConfig(object):
207 """Mock config_reader.Rubik_Config."""
208
Jack Neus2cbdc432022-06-24 20:21:30 +0000209 def get_stable_rubik_milestones(self):
Jack Neus8f0edb42022-03-17 20:21:39 +0000210 """Mock config_reader.LabConfig.get_cros_board_list."""
Jack Neus2cbdc432022-06-24 20:21:30 +0000211 return {'atlas-kernelnext': 62, 'kevin-kernelnext': 61}
Jack Neus8f0edb42022-03-17 20:21:39 +0000212
213
Xixuan Wu008ee832017-10-12 16:59:34 -0700214class TriggerReceiverBaseTestCase(unittest.TestCase):
Xixuan Wu40998892017-08-29 14:32:26 -0700215
216 def setUp(self):
217 self.testbed = testbed.Testbed()
218 self.testbed.activate()
219 self.addCleanup(self.testbed.deactivate)
220
221 self.testbed.init_datastore_v3_stub()
222 self.testbed.init_memcache_stub()
223 ndb.get_context().clear_cache()
224 self.testbed.init_taskqueue_stub(
225 root_path=os.path.join(os.path.dirname(__file__)))
226 self.taskqueue_stub = self.testbed.get_stub(
227 testbed.TASKQUEUE_SERVICE_NAME)
228
Xixuan Wuc6819012019-05-23 11:34:59 -0700229 mock_build_client = mock.patch('rest_client.BuildBucketBigqueryClient')
230 self._mock_build_client = mock_build_client.start()
231 self.addCleanup(mock_build_client.stop)
232
Xixuan Wu40998892017-08-29 14:32:26 -0700233 mock_android_client = mock.patch('rest_client.AndroidBuildRestClient')
234 self._mock_android_client = mock_android_client.start()
235 self.addCleanup(mock_android_client.stop)
236
Xixuan Wu40998892017-08-29 14:32:26 -0700237 mock_lab_config = mock.patch('config_reader.LabConfig')
238 self._mock_lab_config = mock_lab_config.start()
239 self.addCleanup(mock_lab_config.stop)
240
Jack Neus8f0edb42022-03-17 20:21:39 +0000241 mock_rubik_config = mock.patch('config_reader.RubikConfig')
242 self._mock_rubik_config = mock_rubik_config.start()
243 self.addCleanup(mock_rubik_config.stop)
244
Xixuan Wu40998892017-08-29 14:32:26 -0700245 mock_utc_now = mock.patch('time_converter.utc_now')
246 self._mock_utc_now = mock_utc_now.start()
247 self.addCleanup(mock_utc_now.stop)
248
Xixuan Wuc6819012019-05-23 11:34:59 -0700249 self._mock_build_client.return_value = FakeBuildClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700250 self._mock_android_client.return_value = FakeAndroidBuildRestClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700251 self._mock_lab_config.return_value = FakeLabConfig()
Jack Neus8f0edb42022-03-17 20:21:39 +0000252 self._mock_rubik_config.return_value = FakeRubikConfig()
Xixuan Wu40998892017-08-29 14:32:26 -0700253
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700254 board_family_patcher = mock.patch(
255 'build_lib.get_board_family_mapping_from_gs')
256 board_family_getter = board_family_patcher.start()
257 board_family_getter.return_value = {
258 'nyan': ['nyan', 'nyan_blaze', 'nyan_big'],
259 'ivybridge': ['link', 'link_freon']}
260 self.addCleanup(board_family_patcher.stop)
261
Xixuan Wu008ee832017-10-12 16:59:34 -0700262
263class TriggerReceiverFakeConfigTestCase(TriggerReceiverBaseTestCase):
264
265 _TEST_PST_HOUR = 20
266 _TEST_PST_DAY = 4 # Friday
267 _TEST_EVENT_PST_HOUR = 13
268
269 _FAKE_NIGHTLY_TASK_NAME = 'fake_nightly_task'
270 _FAKE_WEEKLY_TASK_NAME = 'fake_weekly_task'
271
272 def setUp(self):
273 super(TriggerReceiverFakeConfigTestCase, self).setUp()
274
275 self.fake_config = config_reader.ConfigReader(None)
276 self._add_nightly_tasks(self.fake_config)
277 self._add_weekly_tasks(self.fake_config)
278
279 self.fake_config_with_settings = config_reader.ConfigReader(None)
280 self._add_weekly_tasks(self.fake_config_with_settings)
281 self._add_weekly_params(self.fake_config_with_settings)
282
283 mock_config_reader = mock.patch('config_reader.ConfigReader')
284 self._mock_config_reader = mock_config_reader.start()
285 self.addCleanup(mock_config_reader.stop)
286
287 def _add_nightly_tasks(self, fake_config):
288 fake_config.add_section(self._FAKE_NIGHTLY_TASK_NAME)
289 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'suite', 'fake_suite')
290 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'run_on', 'nightly')
291 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'hour',
292 str(self._TEST_PST_HOUR))
293
294 def _add_weekly_tasks(self, fake_config):
295 fake_config.add_section(self._FAKE_WEEKLY_TASK_NAME)
296 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'suite', 'fake_suite')
297 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'run_on', 'weekly')
298 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'day', str(self._TEST_PST_DAY))
299
300 def _add_weekly_params(self, fake_config):
Xixuan Wu51bb7102019-03-18 14:51:44 -0700301 weekly_section_name = task_config_reader.EVENT_CLASSES[
302 'weekly'].section_name()
Xixuan Wu008ee832017-10-12 16:59:34 -0700303 fake_config.add_section(weekly_section_name)
304 fake_config.set(weekly_section_name, 'hour', str(self._TEST_EVENT_PST_HOUR))
305
306 def testInitializeTriggerReceiverWithNightlyEvent(self):
307 """Test nightly event can be handled on right hour."""
308 # A task with hour=20 should be scheduled at 20:00 in PST everyday, which
309 # is 3:00/4:00 in UTC everyday.
310 self._mock_config_reader.return_value = self.fake_config
311 given_utc_hour = time_converter.convert_time_info(
312 time_converter.TimeInfo(None, self._TEST_PST_HOUR)).hour
313 utc_now = datetime.datetime(2017, 8, 6, given_utc_hour,
314 tzinfo=time_converter.UTC_TZ)
315 last_exec_client = datastore_client.LastExecutionRecordStore()
316 last_exec_client.set_last_execute_time(
317 'nightly', utc_now - datetime.timedelta(hours=1))
318 self._mock_utc_now.return_value = utc_now
319
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600320 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700321 suite_trigger.cron()
322 self.assertTrue(suite_trigger.events['nightly'].should_handle)
323 self.assertEqual(len(suite_trigger.event_results['nightly']), 1)
324 self.assertEqual(suite_trigger.event_results['nightly'][0],
325 self._FAKE_NIGHTLY_TASK_NAME)
326
327 def testInitializeTriggerReceiverWithWeeklyEventWithoutEventHour(self):
328 """Test weekly event without event settings can be handled on right day."""
329 # A task with day=4 (Friday) and default event_hour (23) should be
330 # scheduled at Friday 23:00 in PST, which is Saturday 6:00 or 7:00 in UTC.
331 self._mock_config_reader.return_value = self.fake_config
332 given_utc_hour = time_converter.convert_time_info(
333 time_converter.TimeInfo(
334 self._TEST_PST_DAY,
Xixuan Wu51bb7102019-03-18 14:51:44 -0700335 task_config_reader.EVENT_CLASSES['weekly'].DEFAULT_PST_HOUR)).hour
Xixuan Wu008ee832017-10-12 16:59:34 -0700336 utc_now = datetime.datetime(2017, 10, 14, given_utc_hour,
337 tzinfo=time_converter.UTC_TZ)
338 last_exec_client = datastore_client.LastExecutionRecordStore()
339 last_exec_client.set_last_execute_time(
340 'weekly', utc_now - datetime.timedelta(days=1))
341 self._mock_utc_now.return_value = utc_now
342
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600343 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700344 suite_trigger.cron()
345 self.assertTrue(suite_trigger.events['weekly'].should_handle)
346 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
347 self.assertEqual(suite_trigger.event_results['weekly'][0],
348 self._FAKE_WEEKLY_TASK_NAME)
349
350 def testInitializeTriggerReceiverWithWeeklyEventWithEventHour(self):
351 """Test weekly event with event settings can be handled on right day."""
352 # A task with day=4 (Friday) and event_hour=13 should be scheduled at
353 # Friday 13:00 in PST, which is Friday 20:00 or 21:00 in UTC.
354 self._mock_config_reader.return_value = self.fake_config_with_settings
355 given_utc_time_info = time_converter.convert_time_info(
356 time_converter.TimeInfo(self._TEST_PST_DAY, self._TEST_EVENT_PST_HOUR))
357
358 # Set the current time as a Friday 20:00 or 21:00 in UTC.
359 utc_now = datetime.datetime(2017, 10, 13, given_utc_time_info.hour,
360 tzinfo=time_converter.UTC_TZ)
361 last_exec_client = datastore_client.LastExecutionRecordStore()
362 last_exec_client.set_last_execute_time(
363 'weekly', utc_now - datetime.timedelta(days=1))
364 self._mock_utc_now.return_value = utc_now
365
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600366 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700367 suite_trigger.cron()
368 self.assertTrue(suite_trigger.events['weekly'].should_handle)
369 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
370 self.assertEqual(suite_trigger.event_results['weekly'][0],
371 self._FAKE_WEEKLY_TASK_NAME)
372
373
Craig Bergstrom58263d32018-04-26 14:11:35 -0600374class TriggerReceiverFakeBuildTestCase(TriggerReceiverBaseTestCase):
375 """Test the new_build functionality."""
376
Craig Bergstrom58263d32018-04-26 14:11:35 -0600377 def setUp(self):
378 """Set up for a test."""
379 super(TriggerReceiverFakeBuildTestCase, self).setUp()
380
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700381 self._prepare()
382
383 def _prepare(self):
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600384 self.reader = config_reader.ConfigReader(None)
385 self.fake_config = self.reader
Craig Bergstrom58263d32018-04-26 14:11:35 -0600386 mock_config_reader = mock.patch('config_reader.ConfigReader')
387 self._mock_config_reader = mock_config_reader.start()
388 self.addCleanup(mock_config_reader.stop)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600389
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700390 # Set last execution time for new_build events.
391 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600392 last_exec_client = datastore_client.LastExecutionRecordStore()
393 last_exec_client.set_last_execute_time(
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700394 'new_build', utc_now - datetime.timedelta(hours=1))
Craig Bergstrom58263d32018-04-26 14:11:35 -0600395 self._mock_utc_now.return_value = utc_now
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700396
Jared Loucks7068d8b2022-04-28 09:41:33 -0600397 def testNewBuildForOnlySuccessfulBuildRequired(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700398 """Test the new_build functionality."""
Jared Loucks7068d8b2022-04-28 09:41:33 -0600399 # Construct a fake config with only_successful_build_required.
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700400 fsnbt_name = 'FakeStrictNewBuildTask'
401 self.fake_config.add_section(fsnbt_name)
402 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
403 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700404 self.fake_config.set(fsnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700405 frnbt_name = 'FakeRelaxedNewBuildTask'
406 self.fake_config.add_section(frnbt_name)
407 self.fake_config.set(frnbt_name, 'run_on', 'new_build')
408 self.fake_config.set(frnbt_name, 'suite', 'fake_suite_relaxed')
Jared Loucks7068d8b2022-04-28 09:41:33 -0600409 self.fake_config.set(frnbt_name, 'only_successful_build_required', 'True')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700410 self.fake_config.set(frnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700411
412 self._mock_config_reader.return_value = self.fake_config
Craig Bergstrom58263d32018-04-26 14:11:35 -0600413
414 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600415 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600416 suite_trigger.cron()
417
418 # Validate that the expected tests got kicked off.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600419 self.assertEqual(len(suite_trigger.event_results), 1)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600420 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000421 # 2 for strict passed builds, 3 for relaxed builds.
422 self.assertEqual(len(tasks), 5)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600423
424 # The number of builds that matched the base (success) Task.
425 count_base = 0
426 # The number of builds that matched the relaxed Task.
427 count_relaxed = 0
428 for task in tasks:
429 if 'fake_suite_base' in task.payload:
430 # Make sure it matched the expected build only.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600431 self.assertNotIn('grunt-release', task.payload)
432 count_base += 1
433
434 if 'fake_suite_relaxed' in task.payload:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600435 count_relaxed += 1
436
437 # Make each case matched precisely one event.
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000438 self.assertEqual(2, count_base)
439 self.assertEqual(3, count_relaxed)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600440
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700441 def testNewBuildWithExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700442 """Test the new_build suite with an existing board family."""
443 link_suite = 'FakeLinkNewBuildTask'
444 self.fake_config.add_section(link_suite)
445 self.fake_config.set(link_suite, 'run_on', 'new_build')
446 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700447 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700448 self._mock_config_reader.return_value = self.fake_config
449
450 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600451 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700452 suite_trigger.cron()
453
454 self.assertEqual(len(suite_trigger.event_results), 1)
455 self.assertEqual(suite_trigger.event_results['new_build'],
456 [link_suite])
457 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
458 self.assertEqual(len(tasks), 1)
459 self.assertIn('link-release', tasks[0].payload)
460
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700461 def testNewBuildWithExistingBoardFamiliesAndBoards(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700462 """Test the new_build suite with an existing board family."""
463 link_suite = 'FakeLinkNewBuildTask'
464 self.fake_config.add_section(link_suite)
465 self.fake_config.set(link_suite, 'run_on', 'new_build')
466 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700467 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700468 self.fake_config.set(link_suite, 'boards', 'asuka, paine, banon')
469 self._mock_config_reader.return_value = self.fake_config
470
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600471 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700472 suite_trigger.cron()
473
474 self.assertEqual(len(suite_trigger.event_results), 1)
475 self.assertEqual(suite_trigger.event_results['new_build'],
476 [link_suite])
477 boards = suite_trigger.events['new_build'].task_list[0].boards
478 self.assertIn('asuka', boards)
479 self.assertIn('link', boards)
480
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700481 def testNewBuildWithNonExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700482 """Test the new_build suite with an non-existing board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700483 nyan_suite = 'FakeNonExistBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700484 self.fake_config.add_section(nyan_suite)
485 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
486 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700487 self.fake_config.set(nyan_suite, 'board_families', 'nyan')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700488 self._mock_config_reader.return_value = self.fake_config
489
490 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600491 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700492 suite_trigger.cron()
493
494 self.assertEqual(len(suite_trigger.event_results), 1)
495 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
496 self.assertEqual(len(tasks), 0)
497
498 def testNewBuildWithNonSpecifiedBoardFamily(self):
499 """Test the new_build suite with an non-specified board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700500 normal_suite = 'FakeBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700501 self.fake_config.add_section(normal_suite)
502 self.fake_config.set(normal_suite, 'run_on', 'new_build')
503 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700504 self.fake_config.set(normal_suite, 'boards', 'link, zako')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700505 self._mock_config_reader.return_value = self.fake_config
506
507 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600508 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700509 suite_trigger.cron()
510
511 self.assertEqual(len(suite_trigger.event_results), 1)
512 self.assertEqual(suite_trigger.event_results['new_build'],
513 [normal_suite])
514 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000515 self.assertEqual(len(tasks), 2)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700516
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700517 def testNewBuildExcludingExistingBoardFamilies(self):
518 """Test the new_build suite excluding an existing board family."""
519 link_suite = 'FakeLinkNewBuildTask'
520 self.fake_config.add_section(link_suite)
521 self.fake_config.set(link_suite, 'run_on', 'new_build')
522 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
523 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700524 self.fake_config.set(link_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700525 self._mock_config_reader.return_value = self.fake_config
526
527 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600528 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700529 suite_trigger.cron()
530
531 self.assertEqual(len(suite_trigger.event_results), 1)
532 self.assertEqual(suite_trigger.event_results['new_build'],
533 [link_suite])
534 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
535 self.assertEqual(len(tasks), 1)
536 self.assertNotIn('link-release', tasks[0].payload)
537 self.assertIn('zako-release', tasks[0].payload)
538
539 def testNewBuildExcludingExistingBoardFamiliesAndBoards(self):
540 """Test the new_build suite with an existing board family."""
541 link_suite = 'FakeLinkNewBuildTask'
542 self.fake_config.add_section(link_suite)
543 self.fake_config.set(link_suite, 'run_on', 'new_build')
544 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
545 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wua41efa22019-05-17 14:28:04 -0700546 self.fake_config.set(link_suite, 'exclude_boards',
Xinan Lin09a628a2019-11-01 17:20:27 -0700547 'asuka, paine, banon, coral, reef, nami, samus-kernelnext')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700548 self._mock_config_reader.return_value = self.fake_config
549
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600550 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700551 suite_trigger.cron()
552
553 self.assertEqual(len(suite_trigger.event_results), 1)
554 self.assertEqual(suite_trigger.event_results['new_build'],
555 [link_suite])
556 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
557 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Jack Neus2cbdc432022-06-24 20:21:30 +0000558 self.assertEqual(len(tasks), 3)
Jack Neus8f0edb42022-03-17 20:21:39 +0000559 tasks = sorted(tasks, key = lambda task: task.payload)
Jack Neus2cbdc432022-06-24 20:21:30 +0000560 # We have a Rubik build for kernelnext-release at 8501.0, and a Legacy
561 # build for kernelnext-release at 8500.0. Verify that we're scheduling
562 # for the Legacy build and not for the Rubik build on R60.
563 self.assertNotIn('8501', tasks[0].payload)
564 self.assertIn('8500', tasks[0].payload)
565 self.assertIn('atlas-kernelnext-release', tasks[0].payload)
Jack Neus8f0edb42022-03-17 20:21:39 +0000566 # We have a Rubik build for kernelnext-release at 9869.0, and a Legacy
567 # build for kernelnext-release at 9868.0. Verify that we're scheduling
Jack Neus2cbdc432022-06-24 20:21:30 +0000568 # for the Rubik build and not for the Legacy build on R62.
569 self.assertNotIn('9868', tasks[1].payload)
570 self.assertIn('9869', tasks[1].payload)
571 self.assertIn('atlas-kernelnext-release', tasks[1].payload)
572 self.assertNotIn('link-release', tasks[2].payload)
573 self.assertNotIn('asuka-release', tasks[2].payload)
574 self.assertNotIn('atlas-kernelnext-release', tasks[2].payload)
575 self.assertIn('zako-release', tasks[2].payload)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700576
577 def testNewBuildExcludingNonExistingBoardFamilies(self):
578 """Test the new_build suite excluding an non-existing board family."""
579 nyan_suite = 'FakeNonExistExcludeBoardFamiliesNewBuildTask'
580 self.fake_config.add_section(nyan_suite)
581 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
582 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
583 self.fake_config.set(nyan_suite, 'exclude_board_families', 'nyan')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700584 self.fake_config.set(nyan_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700585 self._mock_config_reader.return_value = self.fake_config
586
587 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600588 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700589 suite_trigger.cron()
590
591 self.assertEqual(len(suite_trigger.event_results), 1)
592 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
593 self.assertEqual(len(tasks), 2)
594
595 def testNewBuildWithBoardExcludeBoardCollision(self):
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700596 """Test the case that the same board in boards and exclude_boards."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700597 normal_suite = 'FakeBoardExludingBoardCollisionNewBuildTask'
598 self.fake_config.add_section(normal_suite)
599 self.fake_config.set(normal_suite, 'run_on', 'new_build')
600 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
601 self.fake_config.set(normal_suite, 'boards', 'zako, asuka')
602 self.fake_config.set(normal_suite, 'exclude_boards', 'asuka')
603 self._mock_config_reader.return_value = self.fake_config
604
605 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600606 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700607 suite_trigger.cron()
608
609 self.assertEqual(len(suite_trigger.event_results), 1)
610 self.assertEqual(suite_trigger.event_results['new_build'],
611 [normal_suite])
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700612 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
613 self.assertEqual(len(tasks), 1)
614 self.assertNotIn('asuka-release', tasks[0].payload)
615 self.assertIn('zako-release', tasks[0].payload)
616
Xixuan Wub4b2f412019-05-03 11:22:31 -0700617 def testNewBuildWithKernelnext(self):
618 """Test the case that suites run with board-kernelnext build."""
619 normal_suite = 'FakeKernelnextSuite'
620 self.fake_config.add_section(normal_suite)
621 self.fake_config.set(normal_suite, 'run_on', 'new_build')
622 self.fake_config.set(normal_suite, 'suite', 'fake-suite')
623 self.fake_config.set(normal_suite, 'pool', 'suites')
624 self.fake_config.set(normal_suite, 'boards', 'samus-kernelnext')
625 self._mock_config_reader.return_value = self.fake_config
626
Xixuan Wub4b2f412019-05-03 11:22:31 -0700627 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600628 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wub4b2f412019-05-03 11:22:31 -0700629 suite_trigger.cron()
630
631 self.assertEqual(len(suite_trigger.event_results), 1)
632 self.assertEqual(suite_trigger.event_results['new_build'],
633 [normal_suite])
634 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
635 self.assertEqual(len(tasks), 1)
636 # Board should be 'samus'.
637 self.assertIn('&board=samus&', tasks[0].payload)
638 # Build should be 'samus-kernelnext-release***'.
639 self.assertIn('cros_version=samus-kernelnext-release', tasks[0].payload)
640
Xixuan Wua41efa22019-05-17 14:28:04 -0700641 def testNewBuildWithModels(self):
642 """Test the new_build suite with an existing models entry."""
643 normal_suite = 'FakeModelsNewBuildTask'
644 self.fake_config.add_section(normal_suite)
645 self.fake_config.set(normal_suite, 'run_on', 'new_build')
646 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
647 self.fake_config.set(normal_suite, 'models', 'coral_lava, coral_santa')
648 self.fake_config.set(normal_suite, 'boards', 'coral')
649 self._mock_config_reader.return_value = self.fake_config
650
651 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600652 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700653 suite_trigger.cron()
654
655 self.assertEqual(len(suite_trigger.event_results), 1)
656 self.assertEqual(suite_trigger.event_results['new_build'],
657 [normal_suite])
658 self.assertIn('new_build', suite_trigger.event_results)
659 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
660 self.assertEqual(len(tasks), 1)
661 self.assertNotIn('model=astronaut', tasks[0].payload)
662 self.assertIn('model=santa', tasks[0].payload)
663
Jared Loucks7068d8b2022-04-28 09:41:33 -0600664 def testNewBuildWithModelsForOnlySuccessfulBuildRequired(self):
Xinan Linae7d6372019-09-12 14:42:10 -0700665 """Test the new_build suite with an existing models entry."""
666 normal_suite = 'FakeModelsNewBuildTask'
667 self.fake_config.add_section(normal_suite)
668 self.fake_config.set(normal_suite, 'run_on', 'new_build')
669 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
670 self.fake_config.set(normal_suite, 'models', 'nami_akali, nami_bard')
671 self.fake_config.set(normal_suite, 'boards', 'nami')
Jared Loucks7068d8b2022-04-28 09:41:33 -0600672 self.fake_config.set(normal_suite, 'only_successful_build_required', 'True')
Xinan Linae7d6372019-09-12 14:42:10 -0700673 self._mock_config_reader.return_value = self.fake_config
674
675 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600676 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Linae7d6372019-09-12 14:42:10 -0700677 suite_trigger.cron()
678
679 self.assertEqual(len(suite_trigger.event_results), 1)
680 self.assertEqual(suite_trigger.event_results['new_build'],
681 [normal_suite])
682 self.assertIn('new_build', suite_trigger.event_results)
683 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
684 self.assertEqual(len(tasks), 2)
Jack Neus8f0edb42022-03-17 20:21:39 +0000685 tasks = sorted(tasks, key = lambda task: task.payload)
686 self.assertIn('model=bard', tasks[0].payload)
687 self.assertIn('9867.0.0', tasks[0].payload)
688 self.assertIn('model=akali', tasks[1].payload)
689 self.assertIn('9868.0.0', tasks[1].payload)
Xinan Linae7d6372019-09-12 14:42:10 -0700690
Xixuan Wua41efa22019-05-17 14:28:04 -0700691 def testNewBuildWithExcludeModels(self):
692 """Test the new_build suite with an existing exclude_models entry."""
693 normal_suite = 'FakeExludingModelsNewBuildTask'
694 self.fake_config.add_section(normal_suite)
695 self.fake_config.set(normal_suite, 'run_on', 'new_build')
696 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
697 self.fake_config.set(normal_suite, 'exclude_models',
698 'coral_lava, coral_santa')
699 self.fake_config.set(normal_suite, 'boards', 'coral')
700 self._mock_config_reader.return_value = self.fake_config
701
702 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600703 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700704 suite_trigger.cron()
705
706 self.assertEqual(len(suite_trigger.event_results), 1)
707 self.assertEqual(suite_trigger.event_results['new_build'],
708 [normal_suite])
709 self.assertIn('new_build', suite_trigger.event_results)
710 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
711 self.assertEqual(len(tasks), 1)
712 self.assertNotIn('model=santa', tasks[0].payload)
713 self.assertIn('model=astronaut', tasks[0].payload)
714
715 def testNewBuildWithModelsExcludeModels(self):
716 """Test the new_build suite with models and exclude_models entry."""
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, 'models', 'coral_santa, coral_astronaut')
722 self.fake_config.set(normal_suite, 'exclude_models',
723 'coral_lava, coral_santa')
724 self.fake_config.set(normal_suite, 'boards', 'coral')
725 self._mock_config_reader.return_value = self.fake_config
726
727 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600728 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700729 suite_trigger.cron()
730
731 self.assertEqual(len(suite_trigger.event_results), 1)
732 self.assertEqual(suite_trigger.event_results['new_build'],
733 [normal_suite])
734 self.assertIn('new_build', suite_trigger.event_results)
735 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
736 self.assertEqual(len(tasks), 1)
737 self.assertNotIn('model=santa', tasks[0].payload)
738 self.assertIn('model=astronaut', tasks[0].payload)
739
740 def testNewBuildWithNoModelListAndModelBuild(self):
741 """Test the new_build suite with models and empty board_model mapping."""
742 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
743 self.fake_config.add_section(normal_suite)
744 self.fake_config.set(normal_suite, 'run_on', 'new_build')
745 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
746 self.fake_config.set(normal_suite, 'boards', 'coral')
747 self._mock_config_reader.return_value = self.fake_config
748
749 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600750 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700751 suite_trigger.cron()
752
753 self.assertIn('new_build', suite_trigger.event_results)
754 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
755 # Verify that coral-release is not kicked off on model lava as lava is not
756 # listed in cros_model_map.
757 self.assertEqual(len(tasks), 2)
758 self.assertNotIn('lava', tasks[0].payload)
759 self.assertNotIn('lava', tasks[1].payload)
760
761 def testNewBuildWithNoModelListAndNoModelBuild(self):
762 """Test the new_build suite with models and empty board_model mapping."""
763 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
764 self.fake_config.add_section(normal_suite)
765 self.fake_config.set(normal_suite, 'run_on', 'new_build')
766 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
767 self.fake_config.set(normal_suite, 'boards', 'reef')
768 self._mock_config_reader.return_value = self.fake_config
769
770 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600771 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700772 suite_trigger.cron()
773
774 self.assertIn('new_build', suite_trigger.event_results)
775 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
776 # Verify that reef-release is kicked off on reef models.
777 self.assertEqual(len(tasks), 1)
778 self.assertIn('model=electro', tasks[0].payload)
779
C Shapiro09108252019-08-01 14:52:52 -0500780 def testNewBuildWithAnyModel(self):
781 """Test the new_build suite with any_model option set."""
782 normal_suite = 'FakeAnyModelNewBuildTask'
783 self.fake_config.add_section(normal_suite)
784 self.fake_config.set(normal_suite, 'run_on', 'new_build')
785 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
786 self.fake_config.set(normal_suite, 'any_model', 'True')
787 self.fake_config.set(normal_suite, 'boards', 'coral')
788 self._mock_config_reader.return_value = self.fake_config
789
790 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600791 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
C Shapiro09108252019-08-01 14:52:52 -0500792 suite_trigger.cron()
793
794 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
795 self.assertEqual(len(tasks), 1)
796 self.assertIn('model=None', tasks[0].payload)
797
Xinan Lin8b291982019-12-16 10:03:56 -0800798 def testNewBuildWithFirmwareTask(self):
799 """Test the new_build suite with firmware option set."""
800 # Construct a fake config with firmware build.
801 fsnbt_name = 'FakeStrictNewBuildTask'
802 self.fake_config.add_section(fsnbt_name)
803 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
804 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
805 self.fake_config.set(fsnbt_name, 'boards', 'zako')
806 self.fake_config.set(fsnbt_name, 'firmware_ro_build_spec', 'firmware')
807 self.fake_config.set(fsnbt_name, 'test_source', 'cros')
808 self._mock_config_reader.return_value = self.fake_config
809
810 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600811 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800812 some_event = suite_trigger.events['new_build']
813 suite_trigger.cron()
814
815 # The firmware query has run for once.
816 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 1)
817 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
818 self.assertEqual(len(tasks), 1)
819 self.assertIn('firmware-zako-12345.67', tasks[0].payload)
820
821
822 def testNewBuildWithoutFirmwareTask(self):
823 """Test the event skips fetch the firmware builds."""
824 # Construct a fake config without firmware build.
825 fsnbt_name = 'FakeStrictNewBuildTask'
826 self.fake_config.add_section(fsnbt_name)
827 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
828 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
829 self.fake_config.set(fsnbt_name, 'boards', 'zako')
830 self._mock_config_reader.return_value = self.fake_config
831
832 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600833 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800834 suite_trigger.cron()
835
836 # The firmware query was not called.
837 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 0)
838 # Validate that the expected tests got kicked off.
839 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
840 self.assertEqual(len(tasks), 1)
841
Craig Bergstrom58263d32018-04-26 14:11:35 -0600842
Xixuan Wu008ee832017-10-12 16:59:34 -0700843class TriggerReceiverRealConfigTestCase(TriggerReceiverBaseTestCase):
844
845 def setUp(self):
846 super(TriggerReceiverRealConfigTestCase, self).setUp()
847 mock_config_reader = mock.patch('config_reader.ConfigReader')
848 self._mock_config_reader = mock_config_reader.start()
849 self.addCleanup(mock_config_reader.stop)
850 self._mock_config_reader.return_value = _SUITE_CONFIG_READER
851
852 def _get_ground_truth_task_list_from_config(self):
853 """Get the ground truth of to-be-scheduled task list from config file."""
854 self._mock_utc_now.return_value = datetime.datetime.now(
855 time_converter.UTC_TZ)
Xixuan Wu51bb7102019-03-18 14:51:44 -0700856 task_config = task_config_reader.TaskConfig(_SUITE_CONFIG_READER)
Xixuan Wu008ee832017-10-12 16:59:34 -0700857 tasks = {}
Xixuan Wu51bb7102019-03-18 14:51:44 -0700858 for keyword, klass in task_config_reader.EVENT_CLASSES.iteritems():
Xixuan Wu008ee832017-10-12 16:59:34 -0700859 new_event = klass(
860 task_config.get_event_setting(klass.section_name()), None)
861 new_event.set_task_list(
862 task_config.get_tasks_by_keyword(klass.KEYWORD)['tasks'])
863 tasks[keyword] = new_event.task_list
864
865 return tasks
866
Xinan Lincfa41012020-04-08 13:22:03 -0700867 def testEventShouldScanNewBuildFromSinceDateToTargetDate(self):
868 """Test the event should scan new builds from last_exec to target_exec."""
869 _utc_now = datetime.datetime.now(time_converter.UTC_TZ)
870 # utc_now() should be called only 3 times for the creation of Weekly,
871 # Nightly or New_Build event.
872 self._mock_utc_now.side_effect = [_utc_now, _utc_now, _utc_now]
873 target_exec_utc = _get_current_min(_utc_now)
874 since_date = target_exec_utc - datetime.timedelta(hours=1)
875 last_exec_client = datastore_client.LastExecutionRecordStore()
876 last_exec_client.set_last_execute_time('new_build', since_date)
877 delay_minutes = datetime.timedelta(
878 minutes=constants.BaseEvent.DELAY_MINUTES)
879 with mock.patch(
880 'build_lib.get_cros_builds',
881 return_value=({}, {})) as mock_get_cros_builds:
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600882 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lincfa41012020-04-08 13:22:03 -0700883 suite_trigger.cron()
884 # The new CrOS builds we fetched should be created within
885 # the specified time span.
Garry Wangdce77572021-07-18 19:33:35 -0700886 mock_get_cros_builds.assert_any_call(
Xinan Lincfa41012020-04-08 13:22:03 -0700887 mock.ANY, mock.ANY, since_date - delay_minutes,
Jack Neus8f0edb42022-03-17 20:21:39 +0000888 target_exec_utc - delay_minutes, 'new_build',
Jack Neus2cbdc432022-06-24 20:21:30 +0000889 stable_rubik_milestones=mock.ANY)
Xinan Lincfa41012020-04-08 13:22:03 -0700890
Xixuan Wu40998892017-08-29 14:32:26 -0700891 def testCronWithoutLastExec(self):
892 """Test the first round of cron can be successfully executed."""
893 self._mock_utc_now.return_value = datetime.datetime.now(
894 time_converter.UTC_TZ)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600895 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700896 suite_trigger.cron()
897 self.assertFalse(suite_trigger.events['nightly'].should_handle)
898 self.assertFalse(suite_trigger.events['weekly'].should_handle)
899 self.assertFalse(suite_trigger.events['new_build'].should_handle)
900
901 self.assertEqual(suite_trigger.event_results, {})
902
903 def testCronTriggerNightly(self):
904 """Test nightly event is read with available nightly last_exec_time."""
905 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
906 last_exec_client = datastore_client.LastExecutionRecordStore()
907 last_exec_client.set_last_execute_time(
908 'nightly', utc_now - datetime.timedelta(hours=1))
909 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600910 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700911 self.assertTrue(suite_trigger.events['nightly'].should_handle)
912 self.assertFalse(suite_trigger.events['weekly'].should_handle)
913 self.assertFalse(suite_trigger.events['new_build'].should_handle)
914
Xixuan Wu33179672017-09-12 11:44:04 -0700915 def testCronTriggerNightlyOutdated(self):
916 """Test nightly event is read with available nightly last_exec_time."""
917 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
918 last_exec_client = datastore_client.LastExecutionRecordStore()
919 last_exec_client.set_last_execute_time(
920 'nightly', utc_now - datetime.timedelta(days=3))
921 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600922 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu33179672017-09-12 11:44:04 -0700923 self.assertFalse(suite_trigger.events['nightly'].should_handle)
924
925 def testCronTriggerWeeklyOutdated(self):
926 """Test weekly event is read with available weekly last_exec_time."""
927 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
928 last_exec_client = datastore_client.LastExecutionRecordStore()
929 last_exec_client.set_last_execute_time(
930 'weekly', utc_now - datetime.timedelta(days=8))
931 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600932 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu33179672017-09-12 11:44:04 -0700933 self.assertFalse(suite_trigger.events['weekly'].should_handle)
934
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000935 def testCronForADay(self):
936 """Ensure cron job can be successfully scheduled for a day."""
Xixuan Wu008ee832017-10-12 16:59:34 -0700937 all_tasks = self._get_ground_truth_task_list_from_config()
Xixuan Wu40998892017-08-29 14:32:26 -0700938 last_now = None
939
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000940 for now in now_generator(datetime.datetime.now(time_converter.UTC_TZ),
941 last_days=1):
Xixuan Wu40998892017-08-29 14:32:26 -0700942 self._mock_utc_now.return_value = now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600943 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu5451a662017-10-17 10:57:40 -0700944 with mock.patch('task.Task.schedule', return_value=True):
945 suite_trigger.cron()
Xixuan Wu40998892017-08-29 14:32:26 -0700946
Xixuan Wu40998892017-08-29 14:32:26 -0700947 should_scheduled_nightly_tasks = [
Xixuan Wu09962902018-12-11 10:49:27 -0800948 t.name for t in all_tasks['nightly'] if t.hour == now.hour]
Xixuan Wu008ee832017-10-12 16:59:34 -0700949
Xixuan Wu09962902018-12-11 10:49:27 -0800950 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700951 should_scheduled_nightly_tasks):
952 self.assertEqual(suite_trigger.event_results['nightly'],
953 should_scheduled_nightly_tasks)
954 else:
955 self.assertNotIn('nightly', suite_trigger.event_results.keys())
956
957 # Verify weekly tasks
958 should_scheduled_weekly_tasks = [
959 t.name for t in all_tasks['weekly']
Xixuan Wu09962902018-12-11 10:49:27 -0800960 if now.weekday() == t.day and now.hour == t.hour]
961 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700962 should_scheduled_weekly_tasks):
963 self.assertEqual(suite_trigger.event_results['weekly'],
964 should_scheduled_weekly_tasks)
965 else:
966 self.assertNotIn('weekly', suite_trigger.event_results.keys())
967
968 # Verify new_build tasks
969 should_scheduled_new_build_tasks = [
970 t.name for t in all_tasks['new_build']]
971 if (_should_schedule_new_build_task(last_now, now) and
972 should_scheduled_new_build_tasks):
973 self.assertEqual(suite_trigger.event_results['new_build'],
974 should_scheduled_new_build_tasks)
975 else:
976 self.assertNotIn('new_build', suite_trigger.event_results.keys())
977
978 last_now = now
979
980
981if __name__ == '__main__':
982 unittest.main()