Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 1 | # 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 timed_event unittests.""" |
| 6 | |
| 7 | import datetime |
| 8 | import unittest |
| 9 | |
| 10 | import base_event |
| 11 | import config_reader |
| 12 | import datastore_client |
| 13 | import mock |
| 14 | import task |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 15 | import task_config_reader |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 16 | import time_converter |
| 17 | |
| 18 | from google.appengine.ext import ndb |
| 19 | from google.appengine.ext import testbed |
| 20 | |
| 21 | |
| 22 | # pylint: disable=unused-argument |
| 23 | class FakeTask(object): |
| 24 | |
| 25 | def __init__(self, name, success, lc_branches='', lc_targets=''): |
| 26 | self.name = name |
| 27 | self.success = success |
| 28 | self.launch_control_branches = lc_branches.split(',') |
| 29 | self.launch_control_targets = lc_targets.split(',') |
| 30 | |
Xinan Lin | 028f958 | 2019-12-11 10:55:33 -0800 | [diff] [blame^] | 31 | def schedule(self, lc_builds, cros_builds, firmware_builds, |
| 32 | lab_config): |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 33 | if not self.success: |
| 34 | raise task.SchedulingError('Failed to run task.') |
Xixuan Wu | 5451a66 | 2017-10-17 10:57:40 -0700 | [diff] [blame] | 35 | |
| 36 | return self.success |
Xinan Lin | 028f958 | 2019-12-11 10:55:33 -0800 | [diff] [blame^] | 37 | |
| 38 | |
| 39 | class FakeBuildClient(object): |
| 40 | """Mock rest_client.BuildBucketBigqueryClient.""" |
| 41 | |
| 42 | def get_latest_passed_firmware_builds(self): |
| 43 | """Mock get_passed_firmware_builds.""" |
| 44 | return [ |
| 45 | ['cros', 'fake_board', ('gs://chromeos-image-archive/' |
| 46 | 'fake_board-release/R30-6182.0.0-rc2/' |
| 47 | 'fake_board')], |
| 48 | ['firmware', 'fake_board', ('gs://chromeos-image-archive/' |
| 49 | 'firmware-fake_board-12345.67.' |
| 50 | 'A-firmwarebranch/RFoo-1.0.0-b1e234567')], |
| 51 | ['firmware', 'foo_board', ('gs://chromeos-image-archive-foo/' |
| 52 | 'firmware-foo_board-12345.67.' |
| 53 | 'A-firmwarebranch/RFoo-1.0.0-b1e234567')], |
| 54 | ] |
| 55 | # pylint: enable=unused-argument |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 56 | |
| 57 | |
| 58 | class BaseEventTestCase(unittest.TestCase): |
| 59 | |
| 60 | _KLASS = base_event.BaseEvent |
| 61 | |
| 62 | def setUp(self): |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 63 | super(BaseEventTestCase, self).setUp() |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 64 | mock_utc_now = mock.patch('time_converter.utc_now') |
| 65 | self._mock_utc_now = mock_utc_now.start() |
| 66 | self.addCleanup(mock_utc_now.stop) |
| 67 | |
| 68 | self.testbed = testbed.Testbed() |
| 69 | self.testbed.activate() |
| 70 | self.addCleanup(self.testbed.deactivate) |
| 71 | self.testbed.init_datastore_v3_stub() |
| 72 | self.testbed.init_memcache_stub() |
| 73 | ndb.get_context().clear_cache() |
| 74 | |
| 75 | self.config = config_reader.ConfigReader(None) |
| 76 | |
| 77 | def testCreateEventWithAlwaysHandle(self): |
| 78 | """Create a base event with always_handle=True.""" |
| 79 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 80 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 81 | task_config_reader.EventSettings(True, None), utc_now, utc_now) |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 82 | |
| 83 | self.assertEqual(event.target_exec_utc, utc_now) |
| 84 | self.assertEqual(event.last_exec_utc, utc_now) |
| 85 | self.assertTrue(event.always_handle) |
| 86 | self.assertTrue(event.should_handle) |
| 87 | |
| 88 | def testCreateEventWithoutAlwaysHandle(self): |
| 89 | """Create a base event with always_handle=False.""" |
| 90 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 91 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 92 | task_config_reader.EventSettings(False, None), utc_now, utc_now) |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 93 | |
| 94 | self.assertEqual(event.target_exec_utc, utc_now) |
| 95 | self.assertEqual(event.last_exec_utc, utc_now) |
| 96 | self.assertFalse(event.always_handle) |
| 97 | self.assertFalse(event.should_handle) |
| 98 | |
| 99 | def testProcessTasks(self): |
| 100 | """Test process_tasks() for event.""" |
| 101 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 102 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 103 | task_config_reader.EventSettings(True, None), utc_now, utc_now) |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 104 | task_list = [FakeTask('test1', True), FakeTask('test2', False)] |
| 105 | event.set_task_list(task_list) |
| 106 | finished_tasks = event.process_tasks(None, None, None, None) |
| 107 | self.assertEqual(len(finished_tasks), 1) |
| 108 | self.assertEqual(finished_tasks[0], 'test1') |
| 109 | |
| 110 | def testEventFinish(self): |
| 111 | """Test finish() for event.""" |
| 112 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 113 | last_exec_utc = utc_now - datetime.timedelta(hours=1) |
| 114 | last_exec_client = datastore_client.LastExecutionRecordStore() |
| 115 | last_exec_client.set_last_execute_time(self._KLASS.KEYWORD, last_exec_utc) |
| 116 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 117 | task_config_reader.EventSettings(True, None), last_exec_utc, utc_now) |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 118 | |
| 119 | self.assertEqual( |
| 120 | last_exec_client.get_last_execute_time(self._KLASS.KEYWORD), |
| 121 | last_exec_utc) |
| 122 | |
| 123 | event.finish() |
| 124 | self.assertEqual( |
| 125 | last_exec_client.get_last_execute_time(self._KLASS.KEYWORD), |
| 126 | utc_now) |
| 127 | |
| 128 | def testPropertyLaunchControlBranchTargets(self): |
| 129 | """Test getter of property launch_control_branch_targets.""" |
| 130 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 131 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 132 | task_config_reader.EventSettings(True, None), utc_now, utc_now) |
Xixuan Wu | 303a519 | 2017-08-29 11:10:42 -0700 | [diff] [blame] | 133 | task_list = [FakeTask('test1', True, 'b1', 't1,t2'), |
| 134 | FakeTask('test2', True, 'b2', 't3,t4'), |
| 135 | FakeTask('test3', True, 'b1', 't5,t6')] |
| 136 | event.set_task_list(task_list) |
| 137 | self.assertEqual(event.launch_control_branch_targets, |
| 138 | {'b1': ['t1', 't2', 't5', 't6'], |
| 139 | 'b2': ['t3', 't4']}) |
Xixuan Wu | a5a2944 | 2017-10-11 11:03:02 -0700 | [diff] [blame] | 140 | |
| 141 | def testGAETestingForShouldHandle(self): |
| 142 | """Verify that testing on GAE staging will cause event to handle.""" |
| 143 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 144 | with mock.patch('global_config.GAE_TESTING', return_value=True): |
| 145 | event = self._KLASS( |
Xixuan Wu | 51bb710 | 2019-03-18 14:51:44 -0700 | [diff] [blame] | 146 | task_config_reader.EventSettings(True, None), utc_now, utc_now) |
Xixuan Wu | a5a2944 | 2017-10-11 11:03:02 -0700 | [diff] [blame] | 147 | self.assertTrue(event.should_handle) |
Xinan Lin | 028f958 | 2019-12-11 10:55:33 -0800 | [diff] [blame^] | 148 | |
| 149 | def testGetFirmwareBuilds(self): |
| 150 | """Test filter out invalid firmware build from BuildBucket.""" |
| 151 | utc_now = datetime.datetime(2017, 8, 1, 4, tzinfo=time_converter.UTC_TZ) |
| 152 | event = self._KLASS( |
| 153 | task_config_reader.EventSettings(True, None), utc_now, utc_now) |
| 154 | self.assertEqual(2, len(event.get_firmware_builds(FakeBuildClient()))) |