blob: 6a48c0a7882f9a7665d75f2dc8423124c1b23136 [file] [log] [blame]
Xixuan Wu835dee22017-09-07 10:47:29 -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 task_executor unittests."""
6# pylint: disable=g-bad-import-order
Xinan Lin3ba18a02019-08-13 15:44:55 -07007# pylint: disable=unused-argument
Xixuan Wu835dee22017-09-07 10:47:29 -07008
9import mock
10import os
11import sys
12import unittest
13
14import task_executor
15
16from google.appengine.api import taskqueue
17from google.appengine.ext import testbed
18
19
20class FakeSwarmingLib(object):
21
Craig Bergstrom58263d32018-04-26 14:11:35 -060022 # pylint: disable=g-deprecated-member-used
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -070023 def __init__(self, success_num=sys.maxint, error_num=0):
Xixuan Wu835dee22017-09-07 10:47:29 -070024 self.success_num = success_num
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -070025 self.error_num = error_num
Xixuan Wua17e3282018-08-21 16:11:11 -070026 self.skylab_dummy_run_count = 0
27 self.afe_dummy_run_count = 0
Xixuan Wu835dee22017-09-07 10:47:29 -070028
29 def run(self, **suite_kwargs):
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -070030 num = int(suite_kwargs.get('num', 0))
31 if num > self.success_num and num <= self.success_num + self.error_num:
Xixuan Wu835dee22017-09-07 10:47:29 -070032 raise ValueError('test')
33
Xinan Lin3ba18a02019-08-13 15:44:55 -070034 def dummy_run(self, **params):
35 if params.get('is_skylab', 'False') == 'True':
Xixuan Wua17e3282018-08-21 16:11:11 -070036 self.skylab_dummy_run_count += 1
37 else:
38 self.afe_dummy_run_count += 1
Xixuan Wua5a29442017-10-11 11:03:02 -070039
Xixuan Wu835dee22017-09-07 10:47:29 -070040
Xinan Lin3ba18a02019-08-13 15:44:55 -070041class FakeFrontdoorClient(object):
42
43 # pylint: disable=g-deprecated-member-used
44 def __init__(self, success_num=sys.maxint, error_num=0):
45 self.success_num = success_num
46 self.error_num = error_num
47 self.frontdoor_dummy_run_count = 0
48
49 def run(self, **suite_kwargs):
50 num = int(suite_kwargs.get('num', 0))
51 if num > self.success_num and num <= self.success_num + self.error_num:
52 raise ValueError('test')
Xinan Lin3ba18a02019-08-13 15:44:55 -070053 self.frontdoor_dummy_run_count += 1
54
55
Xixuan Wu835dee22017-09-07 10:47:29 -070056class TaskExecutorTestCase(unittest.TestCase):
57
58 def setUp(self):
59 self.testbed = testbed.Testbed()
60 self.testbed.activate()
61 self.addCleanup(self.testbed.deactivate)
62
63 # root_path must be set the location of queue.yaml.
64 # Otherwise, only the 'default' queue will be available.
65 self.testbed.init_taskqueue_stub(
66 root_path=os.path.join(os.path.dirname(__file__)))
67 self.taskqueue_stub = self.testbed.get_stub(
68 testbed.TASKQUEUE_SERVICE_NAME)
69
70 def testPushTask(self):
71 suite_kwargs = {'suite': 'fake_suite'}
72 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
73 tasks = self.taskqueue_stub.get_filtered_tasks()
74 self.assertEqual(len(tasks), 1)
75 self.assertEqual(suite_kwargs, tasks[0].extract_params())
76
Xinan Lin3ba18a02019-08-13 15:44:55 -070077 def testBatchExecuteTask(self):
Xixuan Wua5a29442017-10-11 11:03:02 -070078 """Test task_executor execute tasks in batch in testing on GAE."""
Xixuan Wua5a29442017-10-11 11:03:02 -070079 for i in range(task_executor.BATCH_SIZE):
Xinan Lin3ba18a02019-08-13 15:44:55 -070080 suite_kwargs = {'suite': 'fake_suite',
81 'is_frontdoor': i % 2 == 0,
82 'is_skylab': (i + 1) % 4 == 0,
83 'num': i + 1}
Xixuan Wua5a29442017-10-11 11:03:02 -070084 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
85
Xinan Lin3ba18a02019-08-13 15:44:55 -070086 with mock.patch('buildbucket.TestPlatformClient',
87 return_value=FakeFrontdoorClient()):
88 with mock.patch('swarming_lib.SwarmingRunner',
89 return_value=FakeSwarmingLib()):
90 with mock.patch('global_config.GAE_TESTING', return_value=True):
91 task_processor = task_executor.TaskProcessor(
92 task_executor.SUITES_QUEUE,
93 'invalidhostname',
94 'skylab_swarming_server')
95 task_processor.batch_execute()
96 self.assertEqual(task_executor.BATCH_SIZE/2,
97 task_processor.test_platform_client.frontdoor_dummy_run_count)
98 self.assertEqual(task_executor.BATCH_SIZE/4,
99 task_processor.swarming.afe_dummy_run_count)
100 self.assertEqual(task_executor.BATCH_SIZE/4,
101 task_processor.swarming.skylab_dummy_run_count)
Xixuan Wua5a29442017-10-11 11:03:02 -0700102
Xixuan Wu835dee22017-09-07 10:47:29 -0700103 def testBatchExecuteTaskSuccessfully(self):
104 """Test task_executor successfully execute tasks in batch."""
105 suite_kwargs = {'suite': 'fake_suite'}
106 extra_num = 10
107 for i in range(task_executor.BATCH_SIZE + extra_num):
108 suite_kwargs['num'] = i + 1
109 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
110
111 # Before batch_execute
112 tasks = self.taskqueue_stub.get_filtered_tasks()
113 self.assertEqual(len(tasks), task_executor.BATCH_SIZE + extra_num)
114 with mock.patch('swarming_lib.SwarmingRunner',
115 return_value=FakeSwarmingLib()):
Craig Bergstrom3212fb42018-04-17 19:24:15 -0600116 task_processor = task_executor.TaskProcessor(task_executor.SUITES_QUEUE,
Xixuan Wu5d700dc2018-08-21 15:13:10 -0700117 'invalidhostname',
118 'skylab_swarming_server')
Xixuan Wu835dee22017-09-07 10:47:29 -0700119 task_processor.batch_execute()
120 # After batch_execute succeeds, only extra_num tasks left.
121 tasks = self.taskqueue_stub.get_filtered_tasks()
122 self.assertEqual(len(tasks), extra_num)
123
124 def testBatchExecuteTaskFailedSwarmingTotally(self):
125 """Test task_executor fails at the beginning, and no tasks are deleted."""
126 suite_kwargs = {'suite': 'fake_suite'}
127 extra_num = 10
128 for i in range(task_executor.BATCH_SIZE + extra_num):
129 suite_kwargs['num'] = i + 1
130 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
131
132 # Before batch_execute
133 tasks = self.taskqueue_stub.get_filtered_tasks()
134 self.assertEqual(len(tasks), task_executor.BATCH_SIZE + extra_num)
135 with mock.patch('swarming_lib.SwarmingRunner',
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700136 return_value=FakeSwarmingLib(0, error_num=len(tasks))):
Craig Bergstrom3212fb42018-04-17 19:24:15 -0600137 task_processor = task_executor.TaskProcessor(task_executor.SUITES_QUEUE,
Xixuan Wu5d700dc2018-08-21 15:13:10 -0700138 'invalidhostname',
139 'skylab_swarming_server')
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700140 task_processor.batch_execute()
141 # After batch_execute, no tasks are deleted from task queue, due
142 # to they're all failed to kick off.
Xixuan Wu835dee22017-09-07 10:47:29 -0700143 tasks = self.taskqueue_stub.get_filtered_tasks()
144 self.assertEqual(len(tasks), task_executor.BATCH_SIZE + extra_num)
145
146 def testBatchExecuteTaskFailedSwarmingPartially(self):
147 """Test task_executor fails halfway, and only executed tasks are deleted."""
148 suite_kwargs = {'suite': 'fake_suite'}
149 extra_num = 10
150 success_num = 50
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700151 error_num = 5
Xixuan Wu835dee22017-09-07 10:47:29 -0700152 for i in range(task_executor.BATCH_SIZE + extra_num):
153 suite_kwargs['num'] = i + 1
154 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
155
156 # Before batch_execute
157 tasks = self.taskqueue_stub.get_filtered_tasks()
158 self.assertEqual(len(tasks), task_executor.BATCH_SIZE + extra_num)
159 with mock.patch('swarming_lib.SwarmingRunner',
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700160 return_value=FakeSwarmingLib(success_num, error_num)):
Craig Bergstrom3212fb42018-04-17 19:24:15 -0600161 task_processor = task_executor.TaskProcessor(task_executor.SUITES_QUEUE,
Xixuan Wu5d700dc2018-08-21 15:13:10 -0700162 'invalidhostname',
163 'skylab_swarming_server')
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700164 task_processor.batch_execute()
165 # After batch_execute, only failed suites and extra suites are
166 # kept in task queue.
Xixuan Wu835dee22017-09-07 10:47:29 -0700167 tasks = self.taskqueue_stub.get_filtered_tasks()
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700168 self.assertEqual(len(tasks), error_num + extra_num)
Xixuan Wu835dee22017-09-07 10:47:29 -0700169
170 def testBatchExecuteTaskFailedLeasing(self):
171 """Test task_executor fails to lease task."""
172 suite_kwargs = {'suite': 'fake_suite'}
173 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
174
175 with mock.patch('swarming_lib.SwarmingRunner',
176 return_value=FakeSwarmingLib(False)):
Craig Bergstrom3212fb42018-04-17 19:24:15 -0600177 task_processor = task_executor.TaskProcessor('nonExistentQueue',
Xixuan Wu5d700dc2018-08-21 15:13:10 -0700178 'invalidhostname',
179 'skylab_swarming_server')
Xixuan Wu835dee22017-09-07 10:47:29 -0700180 self.assertRaises(taskqueue.UnknownQueueError,
181 task_processor.batch_execute)
182 # After batch_execute fails, no tasks are deleted from task queue.
183 tasks = self.taskqueue_stub.get_filtered_tasks()
184 self.assertEqual(len(tasks), 1)
185
186
187if __name__ == '__main__':
188 unittest.main()