blob: faae2cac58e5cd0ace10aef00e49cda383c93c56 [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(
129 'atlas-kernelnext', None, '62', '9868.0.0', 'atlas-kernelnext-release'),
130 ]
131
132 def get_passed_rubik_builds(self, earliest, latest, event_type):
133 """Mock get_passed_rubik_builds."""
134 del earliest # unused
135 del latest # unused
136 del event_type #unused
137 return [
138 build_lib.BuildInfo(
139 'atlas-kernelnext', None, '62', '9869.0.0', 'atlas-kernelnext-release'),
140 build_lib.BuildInfo(
141 'coral', 'lava', '62', '9869.0.0', 'coral-release'),
Xixuan Wuc6819012019-05-23 11:34:59 -0700142 ]
143
Xinan Lin71eeeb02020-03-10 17:37:12 -0700144 def get_relaxed_passed_builds(self, earliest, latest, event_type):
Xinan Linea1efcb2019-12-30 23:46:42 -0800145 """Mock get_relaxed_pased_builds."""
146 del earliest # unused
147 del latest # unused
Xinan Lin71eeeb02020-03-10 17:37:12 -0700148 del event_type #unused
Xinan Linae7d6372019-09-12 14:42:10 -0700149 return [
150 build_lib.BuildInfo('grunt', None, '63', '9968.0.0', 'grunt-release'),
151 build_lib.BuildInfo('nami', None, '62', '9867.0.0', 'nami-release'),
152 build_lib.BuildInfo('nami', 'akali', '62', '9868.0.0', 'nami-release'),
153 build_lib.BuildInfo('nami', 'bard', '62', '9866.0.0', 'nami-release'),
154 ]
Xixuan Wuc6819012019-05-23 11:34:59 -0700155
Xinan Lin028f9582019-12-11 10:55:33 -0800156 def get_latest_passed_firmware_builds(self):
157 """Mock get_passed_firmware_builds."""
Xinan Lin8b291982019-12-16 10:03:56 -0800158 self.firmware_builds_called += 1
Xinan Lin028f9582019-12-11 10:55:33 -0800159 return [
160 ['cros', 'fake_board', ('gs://chromeos-image-archive/'
161 'fake_board-release/R30-6182.0.0-rc2/'
162 'fake_board')],
163 ['firmware', 'fake_board', ('gs://chromeos-image-archive/'
164 'firmware-fake_board-12345.67.'
165 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin8b291982019-12-16 10:03:56 -0800166 ['firmware', 'zako', ('gs://chromeos-image-archive/'
167 'firmware-zako-12345.67.'
168 'A-firmwarebranch/RFoo-1.0.0-b1e234567')],
Xinan Lin028f9582019-12-11 10:55:33 -0800169 ]
170
Xixuan Wuc6819012019-05-23 11:34:59 -0700171
Xixuan Wu40998892017-08-29 14:32:26 -0700172class FakeAndroidBuildRestClient(object):
173 """Mock rest_client.AndroidBuildRestClient."""
174
175 def get_latest_build_id(self, branch, target):
176 """Mock rest_client.AndroidBuildRestClient.get_latest_build_id."""
177 del branch, target # unused
178 return '100'
179
180
181class FakeLabConfig(object):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700182 """Mock config_reader.LabConfig."""
Xixuan Wu40998892017-08-29 14:32:26 -0700183
184 def get_android_board_list(self):
185 """Mock config_reader.LabConfig.get_android_board_list."""
186 return ('android-angler', 'android-bullhead')
187
Xixuan Wu6fb16272017-10-19 13:16:00 -0700188 def get_cros_board_list(self):
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700189 """Mock config_reader.LabConfig.get_cros_board_list."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700190 return ('grunt', 'link', 'peppy', 'daisy', 'zako', 'samus-kernelnext',
Jack Neus8f0edb42022-03-17 20:21:39 +0000191 'coral', 'reef', 'nami', 'atlas-kernelnext', 'kevin-kernelnext')
Xixuan Wu6fb16272017-10-19 13:16:00 -0700192
C Shapiro7f24a002017-12-05 14:25:09 -0700193 def get_cros_model_map(self):
194 """Mock config_reader.LabConfig.get_cros_model_map."""
Xixuan Wua41efa22019-05-17 14:28:04 -0700195 return {
196 'coral': ['santa', 'astronaut'],
197 'reef': ['electro'],
Xinan Linae7d6372019-09-12 14:42:10 -0700198 'nami': ['akali', 'bard'],
Xixuan Wua41efa22019-05-17 14:28:04 -0700199 }
C Shapiro7f24a002017-12-05 14:25:09 -0700200
Xixuan Wu40998892017-08-29 14:32:26 -0700201
Jack Neus8f0edb42022-03-17 20:21:39 +0000202class FakeRubikConfig(object):
203 """Mock config_reader.Rubik_Config."""
204
205 def get_build_target_list(self):
206 """Mock config_reader.LabConfig.get_cros_board_list."""
207 return ('atlas-kernelnext', 'kevin-kernelnext')
208
209
Xixuan Wu008ee832017-10-12 16:59:34 -0700210class TriggerReceiverBaseTestCase(unittest.TestCase):
Xixuan Wu40998892017-08-29 14:32:26 -0700211
212 def setUp(self):
213 self.testbed = testbed.Testbed()
214 self.testbed.activate()
215 self.addCleanup(self.testbed.deactivate)
216
217 self.testbed.init_datastore_v3_stub()
218 self.testbed.init_memcache_stub()
219 ndb.get_context().clear_cache()
220 self.testbed.init_taskqueue_stub(
221 root_path=os.path.join(os.path.dirname(__file__)))
222 self.taskqueue_stub = self.testbed.get_stub(
223 testbed.TASKQUEUE_SERVICE_NAME)
224
Xixuan Wuc6819012019-05-23 11:34:59 -0700225 mock_build_client = mock.patch('rest_client.BuildBucketBigqueryClient')
226 self._mock_build_client = mock_build_client.start()
227 self.addCleanup(mock_build_client.stop)
228
Xixuan Wu40998892017-08-29 14:32:26 -0700229 mock_android_client = mock.patch('rest_client.AndroidBuildRestClient')
230 self._mock_android_client = mock_android_client.start()
231 self.addCleanup(mock_android_client.stop)
232
Xixuan Wu40998892017-08-29 14:32:26 -0700233 mock_lab_config = mock.patch('config_reader.LabConfig')
234 self._mock_lab_config = mock_lab_config.start()
235 self.addCleanup(mock_lab_config.stop)
236
Jack Neus8f0edb42022-03-17 20:21:39 +0000237 mock_rubik_config = mock.patch('config_reader.RubikConfig')
238 self._mock_rubik_config = mock_rubik_config.start()
239 self.addCleanup(mock_rubik_config.stop)
240
Xixuan Wu40998892017-08-29 14:32:26 -0700241 mock_utc_now = mock.patch('time_converter.utc_now')
242 self._mock_utc_now = mock_utc_now.start()
243 self.addCleanup(mock_utc_now.stop)
244
Xixuan Wuc6819012019-05-23 11:34:59 -0700245 self._mock_build_client.return_value = FakeBuildClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700246 self._mock_android_client.return_value = FakeAndroidBuildRestClient()
Xixuan Wu40998892017-08-29 14:32:26 -0700247 self._mock_lab_config.return_value = FakeLabConfig()
Jack Neus8f0edb42022-03-17 20:21:39 +0000248 self._mock_rubik_config.return_value = FakeRubikConfig()
Xixuan Wu40998892017-08-29 14:32:26 -0700249
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700250 board_family_patcher = mock.patch(
251 'build_lib.get_board_family_mapping_from_gs')
252 board_family_getter = board_family_patcher.start()
253 board_family_getter.return_value = {
254 'nyan': ['nyan', 'nyan_blaze', 'nyan_big'],
255 'ivybridge': ['link', 'link_freon']}
256 self.addCleanup(board_family_patcher.stop)
257
Xixuan Wu008ee832017-10-12 16:59:34 -0700258
259class TriggerReceiverFakeConfigTestCase(TriggerReceiverBaseTestCase):
260
261 _TEST_PST_HOUR = 20
262 _TEST_PST_DAY = 4 # Friday
263 _TEST_EVENT_PST_HOUR = 13
264
265 _FAKE_NIGHTLY_TASK_NAME = 'fake_nightly_task'
266 _FAKE_WEEKLY_TASK_NAME = 'fake_weekly_task'
267
268 def setUp(self):
269 super(TriggerReceiverFakeConfigTestCase, self).setUp()
270
271 self.fake_config = config_reader.ConfigReader(None)
272 self._add_nightly_tasks(self.fake_config)
273 self._add_weekly_tasks(self.fake_config)
274
275 self.fake_config_with_settings = config_reader.ConfigReader(None)
276 self._add_weekly_tasks(self.fake_config_with_settings)
277 self._add_weekly_params(self.fake_config_with_settings)
278
279 mock_config_reader = mock.patch('config_reader.ConfigReader')
280 self._mock_config_reader = mock_config_reader.start()
281 self.addCleanup(mock_config_reader.stop)
282
283 def _add_nightly_tasks(self, fake_config):
284 fake_config.add_section(self._FAKE_NIGHTLY_TASK_NAME)
285 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'suite', 'fake_suite')
286 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'run_on', 'nightly')
287 fake_config.set(self._FAKE_NIGHTLY_TASK_NAME, 'hour',
288 str(self._TEST_PST_HOUR))
289
290 def _add_weekly_tasks(self, fake_config):
291 fake_config.add_section(self._FAKE_WEEKLY_TASK_NAME)
292 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'suite', 'fake_suite')
293 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'run_on', 'weekly')
294 fake_config.set(self._FAKE_WEEKLY_TASK_NAME, 'day', str(self._TEST_PST_DAY))
295
296 def _add_weekly_params(self, fake_config):
Xixuan Wu51bb7102019-03-18 14:51:44 -0700297 weekly_section_name = task_config_reader.EVENT_CLASSES[
298 'weekly'].section_name()
Xixuan Wu008ee832017-10-12 16:59:34 -0700299 fake_config.add_section(weekly_section_name)
300 fake_config.set(weekly_section_name, 'hour', str(self._TEST_EVENT_PST_HOUR))
301
302 def testInitializeTriggerReceiverWithNightlyEvent(self):
303 """Test nightly event can be handled on right hour."""
304 # A task with hour=20 should be scheduled at 20:00 in PST everyday, which
305 # is 3:00/4:00 in UTC everyday.
306 self._mock_config_reader.return_value = self.fake_config
307 given_utc_hour = time_converter.convert_time_info(
308 time_converter.TimeInfo(None, self._TEST_PST_HOUR)).hour
309 utc_now = datetime.datetime(2017, 8, 6, given_utc_hour,
310 tzinfo=time_converter.UTC_TZ)
311 last_exec_client = datastore_client.LastExecutionRecordStore()
312 last_exec_client.set_last_execute_time(
313 'nightly', utc_now - datetime.timedelta(hours=1))
314 self._mock_utc_now.return_value = utc_now
315
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600316 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700317 suite_trigger.cron()
318 self.assertTrue(suite_trigger.events['nightly'].should_handle)
319 self.assertEqual(len(suite_trigger.event_results['nightly']), 1)
320 self.assertEqual(suite_trigger.event_results['nightly'][0],
321 self._FAKE_NIGHTLY_TASK_NAME)
322
323 def testInitializeTriggerReceiverWithWeeklyEventWithoutEventHour(self):
324 """Test weekly event without event settings can be handled on right day."""
325 # A task with day=4 (Friday) and default event_hour (23) should be
326 # scheduled at Friday 23:00 in PST, which is Saturday 6:00 or 7:00 in UTC.
327 self._mock_config_reader.return_value = self.fake_config
328 given_utc_hour = time_converter.convert_time_info(
329 time_converter.TimeInfo(
330 self._TEST_PST_DAY,
Xixuan Wu51bb7102019-03-18 14:51:44 -0700331 task_config_reader.EVENT_CLASSES['weekly'].DEFAULT_PST_HOUR)).hour
Xixuan Wu008ee832017-10-12 16:59:34 -0700332 utc_now = datetime.datetime(2017, 10, 14, given_utc_hour,
333 tzinfo=time_converter.UTC_TZ)
334 last_exec_client = datastore_client.LastExecutionRecordStore()
335 last_exec_client.set_last_execute_time(
336 'weekly', utc_now - datetime.timedelta(days=1))
337 self._mock_utc_now.return_value = utc_now
338
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600339 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700340 suite_trigger.cron()
341 self.assertTrue(suite_trigger.events['weekly'].should_handle)
342 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
343 self.assertEqual(suite_trigger.event_results['weekly'][0],
344 self._FAKE_WEEKLY_TASK_NAME)
345
346 def testInitializeTriggerReceiverWithWeeklyEventWithEventHour(self):
347 """Test weekly event with event settings can be handled on right day."""
348 # A task with day=4 (Friday) and event_hour=13 should be scheduled at
349 # Friday 13:00 in PST, which is Friday 20:00 or 21:00 in UTC.
350 self._mock_config_reader.return_value = self.fake_config_with_settings
351 given_utc_time_info = time_converter.convert_time_info(
352 time_converter.TimeInfo(self._TEST_PST_DAY, self._TEST_EVENT_PST_HOUR))
353
354 # Set the current time as a Friday 20:00 or 21:00 in UTC.
355 utc_now = datetime.datetime(2017, 10, 13, given_utc_time_info.hour,
356 tzinfo=time_converter.UTC_TZ)
357 last_exec_client = datastore_client.LastExecutionRecordStore()
358 last_exec_client.set_last_execute_time(
359 'weekly', utc_now - datetime.timedelta(days=1))
360 self._mock_utc_now.return_value = utc_now
361
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600362 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu008ee832017-10-12 16:59:34 -0700363 suite_trigger.cron()
364 self.assertTrue(suite_trigger.events['weekly'].should_handle)
365 self.assertEqual(len(suite_trigger.event_results['weekly']), 1)
366 self.assertEqual(suite_trigger.event_results['weekly'][0],
367 self._FAKE_WEEKLY_TASK_NAME)
368
369
Craig Bergstrom58263d32018-04-26 14:11:35 -0600370class TriggerReceiverFakeBuildTestCase(TriggerReceiverBaseTestCase):
371 """Test the new_build functionality."""
372
Craig Bergstrom58263d32018-04-26 14:11:35 -0600373 def setUp(self):
374 """Set up for a test."""
375 super(TriggerReceiverFakeBuildTestCase, self).setUp()
376
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700377 self._prepare()
378
379 def _prepare(self):
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600380 self.reader = config_reader.ConfigReader(None)
381 self.fake_config = self.reader
Craig Bergstrom58263d32018-04-26 14:11:35 -0600382 mock_config_reader = mock.patch('config_reader.ConfigReader')
383 self._mock_config_reader = mock_config_reader.start()
384 self.addCleanup(mock_config_reader.stop)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600385
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700386 # Set last execution time for new_build events.
387 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600388 last_exec_client = datastore_client.LastExecutionRecordStore()
389 last_exec_client.set_last_execute_time(
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700390 'new_build', utc_now - datetime.timedelta(hours=1))
Craig Bergstrom58263d32018-04-26 14:11:35 -0600391 self._mock_utc_now.return_value = utc_now
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700392
393 def testNewBuildForHWTestSanityRequired(self):
394 """Test the new_build functionality."""
395 # Construct a fake config with only_hwtest_sanity_required.
396 fsnbt_name = 'FakeStrictNewBuildTask'
397 self.fake_config.add_section(fsnbt_name)
398 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
399 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700400 self.fake_config.set(fsnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700401 frnbt_name = 'FakeRelaxedNewBuildTask'
402 self.fake_config.add_section(frnbt_name)
403 self.fake_config.set(frnbt_name, 'run_on', 'new_build')
404 self.fake_config.set(frnbt_name, 'suite', 'fake_suite_relaxed')
405 self.fake_config.set(frnbt_name, 'only_hwtest_sanity_required', 'True')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700406 self.fake_config.set(frnbt_name, 'boards', 'link, zako, grunt')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700407
408 self._mock_config_reader.return_value = self.fake_config
Craig Bergstrom58263d32018-04-26 14:11:35 -0600409
410 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600411 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600412 suite_trigger.cron()
413
414 # Validate that the expected tests got kicked off.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600415 self.assertEqual(len(suite_trigger.event_results), 1)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600416 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000417 # 2 for strict passed builds, 3 for relaxed builds.
418 self.assertEqual(len(tasks), 5)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600419
420 # The number of builds that matched the base (success) Task.
421 count_base = 0
422 # The number of builds that matched the relaxed Task.
423 count_relaxed = 0
424 for task in tasks:
425 if 'fake_suite_base' in task.payload:
426 # Make sure it matched the expected build only.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600427 self.assertNotIn('grunt-release', task.payload)
428 count_base += 1
429
430 if 'fake_suite_relaxed' in task.payload:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600431 count_relaxed += 1
432
433 # Make each case matched precisely one event.
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000434 self.assertEqual(2, count_base)
435 self.assertEqual(3, count_relaxed)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600436
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700437 def testNewBuildWithExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700438 """Test the new_build suite with an existing board family."""
439 link_suite = 'FakeLinkNewBuildTask'
440 self.fake_config.add_section(link_suite)
441 self.fake_config.set(link_suite, 'run_on', 'new_build')
442 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700443 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700444 self._mock_config_reader.return_value = self.fake_config
445
446 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600447 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700448 suite_trigger.cron()
449
450 self.assertEqual(len(suite_trigger.event_results), 1)
451 self.assertEqual(suite_trigger.event_results['new_build'],
452 [link_suite])
453 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
454 self.assertEqual(len(tasks), 1)
455 self.assertIn('link-release', tasks[0].payload)
456
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700457 def testNewBuildWithExistingBoardFamiliesAndBoards(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700458 """Test the new_build suite with an existing board family."""
459 link_suite = 'FakeLinkNewBuildTask'
460 self.fake_config.add_section(link_suite)
461 self.fake_config.set(link_suite, 'run_on', 'new_build')
462 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700463 self.fake_config.set(link_suite, 'board_families', 'ivybridge')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700464 self.fake_config.set(link_suite, 'boards', 'asuka, paine, banon')
465 self._mock_config_reader.return_value = self.fake_config
466
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600467 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700468 suite_trigger.cron()
469
470 self.assertEqual(len(suite_trigger.event_results), 1)
471 self.assertEqual(suite_trigger.event_results['new_build'],
472 [link_suite])
473 boards = suite_trigger.events['new_build'].task_list[0].boards
474 self.assertIn('asuka', boards)
475 self.assertIn('link', boards)
476
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700477 def testNewBuildWithNonExistingBoardFamilies(self):
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700478 """Test the new_build suite with an non-existing board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700479 nyan_suite = 'FakeNonExistBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700480 self.fake_config.add_section(nyan_suite)
481 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
482 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700483 self.fake_config.set(nyan_suite, 'board_families', 'nyan')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700484 self._mock_config_reader.return_value = self.fake_config
485
486 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600487 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700488 suite_trigger.cron()
489
490 self.assertEqual(len(suite_trigger.event_results), 1)
491 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
492 self.assertEqual(len(tasks), 0)
493
494 def testNewBuildWithNonSpecifiedBoardFamily(self):
495 """Test the new_build suite with an non-specified board family."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700496 normal_suite = 'FakeBoardFamiliesNewBuildTask'
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700497 self.fake_config.add_section(normal_suite)
498 self.fake_config.set(normal_suite, 'run_on', 'new_build')
499 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700500 self.fake_config.set(normal_suite, 'boards', 'link, zako')
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700501 self._mock_config_reader.return_value = self.fake_config
502
503 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600504 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700505 suite_trigger.cron()
506
507 self.assertEqual(len(suite_trigger.event_results), 1)
508 self.assertEqual(suite_trigger.event_results['new_build'],
509 [normal_suite])
510 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000511 self.assertEqual(len(tasks), 2)
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700512
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700513 def testNewBuildExcludingExistingBoardFamilies(self):
514 """Test the new_build suite excluding an existing board family."""
515 link_suite = 'FakeLinkNewBuildTask'
516 self.fake_config.add_section(link_suite)
517 self.fake_config.set(link_suite, 'run_on', 'new_build')
518 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
519 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700520 self.fake_config.set(link_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700521 self._mock_config_reader.return_value = self.fake_config
522
523 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600524 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700525 suite_trigger.cron()
526
527 self.assertEqual(len(suite_trigger.event_results), 1)
528 self.assertEqual(suite_trigger.event_results['new_build'],
529 [link_suite])
530 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
531 self.assertEqual(len(tasks), 1)
532 self.assertNotIn('link-release', tasks[0].payload)
533 self.assertIn('zako-release', tasks[0].payload)
534
535 def testNewBuildExcludingExistingBoardFamiliesAndBoards(self):
536 """Test the new_build suite with an existing board family."""
537 link_suite = 'FakeLinkNewBuildTask'
538 self.fake_config.add_section(link_suite)
539 self.fake_config.set(link_suite, 'run_on', 'new_build')
540 self.fake_config.set(link_suite, 'suite', 'fake_suite_base')
541 self.fake_config.set(link_suite, 'exclude_board_families', 'ivybridge')
Xixuan Wua41efa22019-05-17 14:28:04 -0700542 self.fake_config.set(link_suite, 'exclude_boards',
Xinan Lin09a628a2019-11-01 17:20:27 -0700543 'asuka, paine, banon, coral, reef, nami, samus-kernelnext')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700544 self._mock_config_reader.return_value = self.fake_config
545
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600546 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700547 suite_trigger.cron()
548
549 self.assertEqual(len(suite_trigger.event_results), 1)
550 self.assertEqual(suite_trigger.event_results['new_build'],
551 [link_suite])
552 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
553 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
Jack Neus8f0edb42022-03-17 20:21:39 +0000554 self.assertEqual(len(tasks), 2)
555 tasks = sorted(tasks, key = lambda task: task.payload)
556 # We have a Rubik build for kernelnext-release at 9869.0, and a Legacy
557 # build for kernelnext-release at 9868.0. Verify that we're scheduling
558 # for the Rubik build and not for the Legacy build.
559 self.assertNotIn('9868', tasks[0].payload)
560 self.assertIn('9869', tasks[0].payload)
561 self.assertIn('atlas-kernelnext-release', tasks[0].payload)
562 self.assertNotIn('link-release', tasks[1].payload)
563 self.assertNotIn('asuka-release', tasks[1].payload)
564 self.assertNotIn('atlas-kernelnext-release', tasks[1].payload)
565 self.assertIn('zako-release', tasks[1].payload)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700566
567 def testNewBuildExcludingNonExistingBoardFamilies(self):
568 """Test the new_build suite excluding an non-existing board family."""
569 nyan_suite = 'FakeNonExistExcludeBoardFamiliesNewBuildTask'
570 self.fake_config.add_section(nyan_suite)
571 self.fake_config.set(nyan_suite, 'run_on', 'new_build')
572 self.fake_config.set(nyan_suite, 'suite', 'fake_suite_base')
573 self.fake_config.set(nyan_suite, 'exclude_board_families', 'nyan')
Xixuan Wub4b2f412019-05-03 11:22:31 -0700574 self.fake_config.set(nyan_suite, 'boards', 'link, zako')
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700575 self._mock_config_reader.return_value = self.fake_config
576
577 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600578 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700579 suite_trigger.cron()
580
581 self.assertEqual(len(suite_trigger.event_results), 1)
582 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
583 self.assertEqual(len(tasks), 2)
584
585 def testNewBuildWithBoardExcludeBoardCollision(self):
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700586 """Test the case that the same board in boards and exclude_boards."""
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700587 normal_suite = 'FakeBoardExludingBoardCollisionNewBuildTask'
588 self.fake_config.add_section(normal_suite)
589 self.fake_config.set(normal_suite, 'run_on', 'new_build')
590 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
591 self.fake_config.set(normal_suite, 'boards', 'zako, asuka')
592 self.fake_config.set(normal_suite, 'exclude_boards', 'asuka')
593 self._mock_config_reader.return_value = self.fake_config
594
595 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600596 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700597 suite_trigger.cron()
598
599 self.assertEqual(len(suite_trigger.event_results), 1)
600 self.assertEqual(suite_trigger.event_results['new_build'],
601 [normal_suite])
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700602 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
603 self.assertEqual(len(tasks), 1)
604 self.assertNotIn('asuka-release', tasks[0].payload)
605 self.assertIn('zako-release', tasks[0].payload)
606
Xixuan Wub4b2f412019-05-03 11:22:31 -0700607 def testNewBuildWithKernelnext(self):
608 """Test the case that suites run with board-kernelnext build."""
609 normal_suite = 'FakeKernelnextSuite'
610 self.fake_config.add_section(normal_suite)
611 self.fake_config.set(normal_suite, 'run_on', 'new_build')
612 self.fake_config.set(normal_suite, 'suite', 'fake-suite')
613 self.fake_config.set(normal_suite, 'pool', 'suites')
614 self.fake_config.set(normal_suite, 'boards', 'samus-kernelnext')
615 self._mock_config_reader.return_value = self.fake_config
616
Xixuan Wub4b2f412019-05-03 11:22:31 -0700617 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600618 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wub4b2f412019-05-03 11:22:31 -0700619 suite_trigger.cron()
620
621 self.assertEqual(len(suite_trigger.event_results), 1)
622 self.assertEqual(suite_trigger.event_results['new_build'],
623 [normal_suite])
624 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
625 self.assertEqual(len(tasks), 1)
626 # Board should be 'samus'.
627 self.assertIn('&board=samus&', tasks[0].payload)
628 # Build should be 'samus-kernelnext-release***'.
629 self.assertIn('cros_version=samus-kernelnext-release', tasks[0].payload)
630
Xixuan Wua41efa22019-05-17 14:28:04 -0700631 def testNewBuildWithModels(self):
632 """Test the new_build suite with an existing models entry."""
633 normal_suite = 'FakeModelsNewBuildTask'
634 self.fake_config.add_section(normal_suite)
635 self.fake_config.set(normal_suite, 'run_on', 'new_build')
636 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
637 self.fake_config.set(normal_suite, 'models', 'coral_lava, coral_santa')
638 self.fake_config.set(normal_suite, 'boards', 'coral')
639 self._mock_config_reader.return_value = self.fake_config
640
641 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600642 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700643 suite_trigger.cron()
644
645 self.assertEqual(len(suite_trigger.event_results), 1)
646 self.assertEqual(suite_trigger.event_results['new_build'],
647 [normal_suite])
648 self.assertIn('new_build', suite_trigger.event_results)
649 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
650 self.assertEqual(len(tasks), 1)
651 self.assertNotIn('model=astronaut', tasks[0].payload)
652 self.assertIn('model=santa', tasks[0].payload)
653
Xinan Linae7d6372019-09-12 14:42:10 -0700654 def testNewBuildWithModelsForHWTestSanityRequired(self):
655 """Test the new_build suite with an existing models entry."""
656 normal_suite = 'FakeModelsNewBuildTask'
657 self.fake_config.add_section(normal_suite)
658 self.fake_config.set(normal_suite, 'run_on', 'new_build')
659 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
660 self.fake_config.set(normal_suite, 'models', 'nami_akali, nami_bard')
661 self.fake_config.set(normal_suite, 'boards', 'nami')
662 self.fake_config.set(normal_suite, 'only_hwtest_sanity_required', 'True')
663 self._mock_config_reader.return_value = self.fake_config
664
665 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600666 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Linae7d6372019-09-12 14:42:10 -0700667 suite_trigger.cron()
668
669 self.assertEqual(len(suite_trigger.event_results), 1)
670 self.assertEqual(suite_trigger.event_results['new_build'],
671 [normal_suite])
672 self.assertIn('new_build', suite_trigger.event_results)
673 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
674 self.assertEqual(len(tasks), 2)
Jack Neus8f0edb42022-03-17 20:21:39 +0000675 tasks = sorted(tasks, key = lambda task: task.payload)
676 self.assertIn('model=bard', tasks[0].payload)
677 self.assertIn('9867.0.0', tasks[0].payload)
678 self.assertIn('model=akali', tasks[1].payload)
679 self.assertIn('9868.0.0', tasks[1].payload)
Xinan Linae7d6372019-09-12 14:42:10 -0700680
Xixuan Wua41efa22019-05-17 14:28:04 -0700681 def testNewBuildWithExcludeModels(self):
682 """Test the new_build suite with an existing exclude_models entry."""
683 normal_suite = 'FakeExludingModelsNewBuildTask'
684 self.fake_config.add_section(normal_suite)
685 self.fake_config.set(normal_suite, 'run_on', 'new_build')
686 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
687 self.fake_config.set(normal_suite, 'exclude_models',
688 'coral_lava, coral_santa')
689 self.fake_config.set(normal_suite, 'boards', 'coral')
690 self._mock_config_reader.return_value = self.fake_config
691
692 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600693 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700694 suite_trigger.cron()
695
696 self.assertEqual(len(suite_trigger.event_results), 1)
697 self.assertEqual(suite_trigger.event_results['new_build'],
698 [normal_suite])
699 self.assertIn('new_build', suite_trigger.event_results)
700 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
701 self.assertEqual(len(tasks), 1)
702 self.assertNotIn('model=santa', tasks[0].payload)
703 self.assertIn('model=astronaut', tasks[0].payload)
704
705 def testNewBuildWithModelsExcludeModels(self):
706 """Test the new_build suite with models and exclude_models entry."""
707 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
708 self.fake_config.add_section(normal_suite)
709 self.fake_config.set(normal_suite, 'run_on', 'new_build')
710 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
711 self.fake_config.set(normal_suite, 'models', 'coral_santa, coral_astronaut')
712 self.fake_config.set(normal_suite, 'exclude_models',
713 'coral_lava, coral_santa')
714 self.fake_config.set(normal_suite, 'boards', 'coral')
715 self._mock_config_reader.return_value = self.fake_config
716
717 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600718 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700719 suite_trigger.cron()
720
721 self.assertEqual(len(suite_trigger.event_results), 1)
722 self.assertEqual(suite_trigger.event_results['new_build'],
723 [normal_suite])
724 self.assertIn('new_build', suite_trigger.event_results)
725 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
726 self.assertEqual(len(tasks), 1)
727 self.assertNotIn('model=santa', tasks[0].payload)
728 self.assertIn('model=astronaut', tasks[0].payload)
729
730 def testNewBuildWithNoModelListAndModelBuild(self):
731 """Test the new_build suite with models and empty board_model mapping."""
732 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
733 self.fake_config.add_section(normal_suite)
734 self.fake_config.set(normal_suite, 'run_on', 'new_build')
735 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
736 self.fake_config.set(normal_suite, 'boards', 'coral')
737 self._mock_config_reader.return_value = self.fake_config
738
739 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600740 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700741 suite_trigger.cron()
742
743 self.assertIn('new_build', suite_trigger.event_results)
744 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
745 # Verify that coral-release is not kicked off on model lava as lava is not
746 # listed in cros_model_map.
747 self.assertEqual(len(tasks), 2)
748 self.assertNotIn('lava', tasks[0].payload)
749 self.assertNotIn('lava', tasks[1].payload)
750
751 def testNewBuildWithNoModelListAndNoModelBuild(self):
752 """Test the new_build suite with models and empty board_model mapping."""
753 normal_suite = 'FakeModelsExcludeModelsNewBuildTask'
754 self.fake_config.add_section(normal_suite)
755 self.fake_config.set(normal_suite, 'run_on', 'new_build')
756 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
757 self.fake_config.set(normal_suite, 'boards', 'reef')
758 self._mock_config_reader.return_value = self.fake_config
759
760 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600761 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wua41efa22019-05-17 14:28:04 -0700762 suite_trigger.cron()
763
764 self.assertIn('new_build', suite_trigger.event_results)
765 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
766 # Verify that reef-release is kicked off on reef models.
767 self.assertEqual(len(tasks), 1)
768 self.assertIn('model=electro', tasks[0].payload)
769
C Shapiro09108252019-08-01 14:52:52 -0500770 def testNewBuildWithAnyModel(self):
771 """Test the new_build suite with any_model option set."""
772 normal_suite = 'FakeAnyModelNewBuildTask'
773 self.fake_config.add_section(normal_suite)
774 self.fake_config.set(normal_suite, 'run_on', 'new_build')
775 self.fake_config.set(normal_suite, 'suite', 'fake_suite_base')
776 self.fake_config.set(normal_suite, 'any_model', 'True')
777 self.fake_config.set(normal_suite, 'boards', 'coral')
778 self._mock_config_reader.return_value = self.fake_config
779
780 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600781 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
C Shapiro09108252019-08-01 14:52:52 -0500782 suite_trigger.cron()
783
784 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
785 self.assertEqual(len(tasks), 1)
786 self.assertIn('model=None', tasks[0].payload)
787
Xinan Lin8b291982019-12-16 10:03:56 -0800788 def testNewBuildWithFirmwareTask(self):
789 """Test the new_build suite with firmware option set."""
790 # Construct a fake config with firmware build.
791 fsnbt_name = 'FakeStrictNewBuildTask'
792 self.fake_config.add_section(fsnbt_name)
793 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
794 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
795 self.fake_config.set(fsnbt_name, 'boards', 'zako')
796 self.fake_config.set(fsnbt_name, 'firmware_ro_build_spec', 'firmware')
797 self.fake_config.set(fsnbt_name, 'test_source', 'cros')
798 self._mock_config_reader.return_value = self.fake_config
799
800 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600801 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800802 some_event = suite_trigger.events['new_build']
803 suite_trigger.cron()
804
805 # The firmware query has run for once.
806 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 1)
807 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
808 self.assertEqual(len(tasks), 1)
809 self.assertIn('firmware-zako-12345.67', tasks[0].payload)
810
811
812 def testNewBuildWithoutFirmwareTask(self):
813 """Test the event skips fetch the firmware builds."""
814 # Construct a fake config without firmware build.
815 fsnbt_name = 'FakeStrictNewBuildTask'
816 self.fake_config.add_section(fsnbt_name)
817 self.fake_config.set(fsnbt_name, 'run_on', 'new_build')
818 self.fake_config.set(fsnbt_name, 'suite', 'fake_suite_base')
819 self.fake_config.set(fsnbt_name, 'boards', 'zako')
820 self._mock_config_reader.return_value = self.fake_config
821
822 queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600823 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lin8b291982019-12-16 10:03:56 -0800824 suite_trigger.cron()
825
826 # The firmware query was not called.
827 self.assertEqual(suite_trigger._build_client.firmware_builds_called, 0)
828 # Validate that the expected tests got kicked off.
829 tasks = queue.lease_tasks(3600, 10, deadline=0.5)
830 self.assertEqual(len(tasks), 1)
831
Craig Bergstrom58263d32018-04-26 14:11:35 -0600832
Xixuan Wu008ee832017-10-12 16:59:34 -0700833class TriggerReceiverRealConfigTestCase(TriggerReceiverBaseTestCase):
834
835 def setUp(self):
836 super(TriggerReceiverRealConfigTestCase, self).setUp()
837 mock_config_reader = mock.patch('config_reader.ConfigReader')
838 self._mock_config_reader = mock_config_reader.start()
839 self.addCleanup(mock_config_reader.stop)
840 self._mock_config_reader.return_value = _SUITE_CONFIG_READER
841
842 def _get_ground_truth_task_list_from_config(self):
843 """Get the ground truth of to-be-scheduled task list from config file."""
844 self._mock_utc_now.return_value = datetime.datetime.now(
845 time_converter.UTC_TZ)
Xixuan Wu51bb7102019-03-18 14:51:44 -0700846 task_config = task_config_reader.TaskConfig(_SUITE_CONFIG_READER)
Xixuan Wu008ee832017-10-12 16:59:34 -0700847 tasks = {}
Xixuan Wu51bb7102019-03-18 14:51:44 -0700848 for keyword, klass in task_config_reader.EVENT_CLASSES.iteritems():
Xixuan Wu008ee832017-10-12 16:59:34 -0700849 new_event = klass(
850 task_config.get_event_setting(klass.section_name()), None)
851 new_event.set_task_list(
852 task_config.get_tasks_by_keyword(klass.KEYWORD)['tasks'])
853 tasks[keyword] = new_event.task_list
854
855 return tasks
856
Xinan Lincfa41012020-04-08 13:22:03 -0700857 def testEventShouldScanNewBuildFromSinceDateToTargetDate(self):
858 """Test the event should scan new builds from last_exec to target_exec."""
859 _utc_now = datetime.datetime.now(time_converter.UTC_TZ)
860 # utc_now() should be called only 3 times for the creation of Weekly,
861 # Nightly or New_Build event.
862 self._mock_utc_now.side_effect = [_utc_now, _utc_now, _utc_now]
863 target_exec_utc = _get_current_min(_utc_now)
864 since_date = target_exec_utc - datetime.timedelta(hours=1)
865 last_exec_client = datastore_client.LastExecutionRecordStore()
866 last_exec_client.set_last_execute_time('new_build', since_date)
867 delay_minutes = datetime.timedelta(
868 minutes=constants.BaseEvent.DELAY_MINUTES)
869 with mock.patch(
870 'build_lib.get_cros_builds',
871 return_value=({}, {})) as mock_get_cros_builds:
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600872 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xinan Lincfa41012020-04-08 13:22:03 -0700873 suite_trigger.cron()
874 # The new CrOS builds we fetched should be created within
875 # the specified time span.
Garry Wangdce77572021-07-18 19:33:35 -0700876 mock_get_cros_builds.assert_any_call(
Xinan Lincfa41012020-04-08 13:22:03 -0700877 mock.ANY, mock.ANY, since_date - delay_minutes,
Jack Neus8f0edb42022-03-17 20:21:39 +0000878 target_exec_utc - delay_minutes, 'new_build',
879 rubik_build_targets=mock.ANY)
Xinan Lincfa41012020-04-08 13:22:03 -0700880
Xixuan Wu40998892017-08-29 14:32:26 -0700881 def testCronWithoutLastExec(self):
882 """Test the first round of cron can be successfully executed."""
883 self._mock_utc_now.return_value = datetime.datetime.now(
884 time_converter.UTC_TZ)
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600885 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700886 suite_trigger.cron()
887 self.assertFalse(suite_trigger.events['nightly'].should_handle)
888 self.assertFalse(suite_trigger.events['weekly'].should_handle)
889 self.assertFalse(suite_trigger.events['new_build'].should_handle)
890
891 self.assertEqual(suite_trigger.event_results, {})
892
893 def testCronTriggerNightly(self):
894 """Test nightly event is read with available nightly last_exec_time."""
895 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
896 last_exec_client = datastore_client.LastExecutionRecordStore()
897 last_exec_client.set_last_execute_time(
898 'nightly', utc_now - datetime.timedelta(hours=1))
899 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600900 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu40998892017-08-29 14:32:26 -0700901 self.assertTrue(suite_trigger.events['nightly'].should_handle)
902 self.assertFalse(suite_trigger.events['weekly'].should_handle)
903 self.assertFalse(suite_trigger.events['new_build'].should_handle)
904
Xixuan Wu33179672017-09-12 11:44:04 -0700905 def testCronTriggerNightlyOutdated(self):
906 """Test nightly event is read with available nightly last_exec_time."""
907 utc_now = datetime.datetime.now(time_converter.UTC_TZ)
908 last_exec_client = datastore_client.LastExecutionRecordStore()
909 last_exec_client.set_last_execute_time(
910 'nightly', utc_now - datetime.timedelta(days=3))
911 self._mock_utc_now.return_value = utc_now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600912 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu33179672017-09-12 11:44:04 -0700913 self.assertFalse(suite_trigger.events['nightly'].should_handle)
914
915 def testCronTriggerWeeklyOutdated(self):
916 """Test weekly event is read with available weekly 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 'weekly', utc_now - datetime.timedelta(days=8))
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['weekly'].should_handle)
924
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000925 def testCronForADay(self):
926 """Ensure cron job can be successfully scheduled for a day."""
Xixuan Wu008ee832017-10-12 16:59:34 -0700927 all_tasks = self._get_ground_truth_task_list_from_config()
Xixuan Wu40998892017-08-29 14:32:26 -0700928 last_now = None
929
Dhanya Ganeshb0e7c982020-07-30 17:45:19 +0000930 for now in now_generator(datetime.datetime.now(time_converter.UTC_TZ),
931 last_days=1):
Xixuan Wu40998892017-08-29 14:32:26 -0700932 self._mock_utc_now.return_value = now
Brigit Rossbach50d086f2020-09-17 13:29:49 -0600933 suite_trigger = trigger_receiver.TriggerReceiver(fake=True)
Xixuan Wu5451a662017-10-17 10:57:40 -0700934 with mock.patch('task.Task.schedule', return_value=True):
935 suite_trigger.cron()
Xixuan Wu40998892017-08-29 14:32:26 -0700936
Xixuan Wu40998892017-08-29 14:32:26 -0700937 should_scheduled_nightly_tasks = [
Xixuan Wu09962902018-12-11 10:49:27 -0800938 t.name for t in all_tasks['nightly'] if t.hour == now.hour]
Xixuan Wu008ee832017-10-12 16:59:34 -0700939
Xixuan Wu09962902018-12-11 10:49:27 -0800940 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700941 should_scheduled_nightly_tasks):
942 self.assertEqual(suite_trigger.event_results['nightly'],
943 should_scheduled_nightly_tasks)
944 else:
945 self.assertNotIn('nightly', suite_trigger.event_results.keys())
946
947 # Verify weekly tasks
948 should_scheduled_weekly_tasks = [
949 t.name for t in all_tasks['weekly']
Xixuan Wu09962902018-12-11 10:49:27 -0800950 if now.weekday() == t.day and now.hour == t.hour]
951 if (_should_schedule_timed_task(last_now, now) and
Xixuan Wu40998892017-08-29 14:32:26 -0700952 should_scheduled_weekly_tasks):
953 self.assertEqual(suite_trigger.event_results['weekly'],
954 should_scheduled_weekly_tasks)
955 else:
956 self.assertNotIn('weekly', suite_trigger.event_results.keys())
957
958 # Verify new_build tasks
959 should_scheduled_new_build_tasks = [
960 t.name for t in all_tasks['new_build']]
961 if (_should_schedule_new_build_task(last_now, now) and
962 should_scheduled_new_build_tasks):
963 self.assertEqual(suite_trigger.event_results['new_build'],
964 should_scheduled_new_build_tasks)
965 else:
966 self.assertNotIn('new_build', suite_trigger.event_results.keys())
967
968 last_now = now
969
970
971if __name__ == '__main__':
972 unittest.main()