blob: 4534ec303cdbfc40bce8f3b0c28f01b7bff2f90b [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
Xinan Lin9e4917d2019-11-04 10:58:47 -08009import collections
Xixuan Wu835dee22017-09-07 10:47:29 -070010import mock
11import os
12import sys
13import unittest
14
Xinan Lin9e4917d2019-11-04 10:58:47 -080015import constants
Xixuan Wu835dee22017-09-07 10:47:29 -070016import task_executor
17
18from google.appengine.api import taskqueue
19from google.appengine.ext import testbed
20
21
Xinan Lin3ba18a02019-08-13 15:44:55 -070022class FakeFrontdoorClient(object):
23
24 # pylint: disable=g-deprecated-member-used
25 def __init__(self, success_num=sys.maxint, error_num=0):
26 self.success_num = success_num
27 self.error_num = error_num
Xinan Lin9e4917d2019-11-04 10:58:47 -080028 self.frontdoor_run_count = collections.defaultdict(list)
Xinan Lin3ba18a02019-08-13 15:44:55 -070029
Xinan Lin9e4917d2019-11-04 10:58:47 -080030 def multirequest_run(self, tasks, suite):
31 executed_tasks = []
32 for task in tasks:
33 params = task.extract_params()
34 num = int(params.get('num', 0))
35 if num > self.success_num and num <= self.success_num + self.error_num:
36 raise ValueError('test')
37 executed_tasks.append(task)
38 self.frontdoor_run_count[suite].append(executed_tasks)
39 return executed_tasks
Xinan Lin3ba18a02019-08-13 15:44:55 -070040
41
Xixuan Wu835dee22017-09-07 10:47:29 -070042class TaskExecutorTestCase(unittest.TestCase):
43
44 def setUp(self):
45 self.testbed = testbed.Testbed()
46 self.testbed.activate()
47 self.addCleanup(self.testbed.deactivate)
48
49 # root_path must be set the location of queue.yaml.
50 # Otherwise, only the 'default' queue will be available.
51 self.testbed.init_taskqueue_stub(
52 root_path=os.path.join(os.path.dirname(__file__)))
53 self.taskqueue_stub = self.testbed.get_stub(
54 testbed.TASKQUEUE_SERVICE_NAME)
55
56 def testPushTask(self):
57 suite_kwargs = {'suite': 'fake_suite'}
58 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
59 tasks = self.taskqueue_stub.get_filtered_tasks()
60 self.assertEqual(len(tasks), 1)
61 self.assertEqual(suite_kwargs, tasks[0].extract_params())
62
Xinan Lin3ba18a02019-08-13 15:44:55 -070063 def testBatchExecuteTask(self):
Xixuan Wua5a29442017-10-11 11:03:02 -070064 """Test task_executor execute tasks in batch in testing on GAE."""
Xinan Lin9e4917d2019-11-04 10:58:47 -080065 extra_num = 10
66 for i in range(constants.Buildbucket.MULTIREQUEST_SIZE):
67 suite_kwargs = {'suite': 'foo_suite',
Xinan Lin3ba18a02019-08-13 15:44:55 -070068 'num': i + 1}
Xinan Lin9e4917d2019-11-04 10:58:47 -080069 task_executor.push(task_executor.SUITES_QUEUE,
70 tag='foo_suite', **suite_kwargs)
71 for i in range(constants.Buildbucket.MULTIREQUEST_SIZE + extra_num):
72 suite_kwargs = {'suite': 'hoo_suite',
73 'num': i + 1}
74 task_executor.push(task_executor.SUITES_QUEUE,
75 tag='hoo_suite', **suite_kwargs)
Xinan Lin3ba18a02019-08-13 15:44:55 -070076 with mock.patch('buildbucket.TestPlatformClient',
77 return_value=FakeFrontdoorClient()):
Xinan Lin9e4917d2019-11-04 10:58:47 -080078 with mock.patch('global_config.GAE_TESTING', return_value=True):
79 task_processor = task_executor.TaskProcessor(
80 task_executor.SUITES_QUEUE)
81 task_processor.batch_execute()
82 client = task_processor.test_platform_client
83 self.assertEqual(1, len(client.frontdoor_run_count['foo_suite']))
84 self.assertEqual(constants.Buildbucket.MULTIREQUEST_SIZE,
85 len(client.frontdoor_run_count['foo_suite'][0]))
86 self.assertEqual(1, len(client.frontdoor_run_count['hoo_suite']))
87 self.assertEqual(constants.Buildbucket.MULTIREQUEST_SIZE,
88 len(client.frontdoor_run_count['hoo_suite'][0]))
89 # Now BATCH_SIZE = 2 * MULTIREQUEST_SIZE. After batch_execute run,
90 # the extra tasks should remain in the queue.
91 tasks = self.taskqueue_stub.get_filtered_tasks()
92 self.assertEqual(extra_num, len(tasks))
Xixuan Wua5a29442017-10-11 11:03:02 -070093
Xinan Lin9e4917d2019-11-04 10:58:47 -080094 def testBatchExecuteTaskFailedFrontdoorTotally(self):
Xixuan Wu835dee22017-09-07 10:47:29 -070095 """Test task_executor fails at the beginning, and no tasks are deleted."""
96 suite_kwargs = {'suite': 'fake_suite'}
97 extra_num = 10
Xinan Lin9e4917d2019-11-04 10:58:47 -080098 for i in range(constants.Buildbucket.MULTIREQUEST_SIZE + extra_num):
Xixuan Wu835dee22017-09-07 10:47:29 -070099 suite_kwargs['num'] = i + 1
100 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
101
102 # Before batch_execute
103 tasks = self.taskqueue_stub.get_filtered_tasks()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800104 self.assertEqual(len(tasks),
105 constants.Buildbucket.MULTIREQUEST_SIZE + extra_num)
106 with mock.patch('buildbucket.TestPlatformClient',
107 return_value=FakeFrontdoorClient(0, error_num=len(tasks))):
108 task_processor = task_executor.TaskProcessor(task_executor.SUITES_QUEUE)
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700109 task_processor.batch_execute()
110 # After batch_execute, no tasks are deleted from task queue, due
111 # to they're all failed to kick off.
Xixuan Wu835dee22017-09-07 10:47:29 -0700112 tasks = self.taskqueue_stub.get_filtered_tasks()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800113 self.assertEqual(len(tasks),
114 constants.Buildbucket.MULTIREQUEST_SIZE + extra_num)
Xixuan Wu835dee22017-09-07 10:47:29 -0700115
Xinan Lin9e4917d2019-11-04 10:58:47 -0800116 def testBatchExecuteTaskFailedFrontdoorPartially(self):
Xixuan Wu835dee22017-09-07 10:47:29 -0700117 """Test task_executor fails halfway, and only executed tasks are deleted."""
118 suite_kwargs = {'suite': 'fake_suite'}
119 extra_num = 10
Xinan Lin9e4917d2019-11-04 10:58:47 -0800120 success_num = (extra_num + constants.Buildbucket.MULTIREQUEST_SIZE) / 2
121 error_num = extra_num + constants.Buildbucket.MULTIREQUEST_SIZE
122 for i in range(constants.Buildbucket.MULTIREQUEST_SIZE + extra_num):
Xixuan Wu835dee22017-09-07 10:47:29 -0700123 suite_kwargs['num'] = i + 1
124 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
125
126 # Before batch_execute
127 tasks = self.taskqueue_stub.get_filtered_tasks()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800128 self.assertEqual(len(tasks),
129 constants.Buildbucket.MULTIREQUEST_SIZE + extra_num)
130 with mock.patch('buildbucket.TestPlatformClient',
131 return_value=FakeFrontdoorClient(success_num, error_num)):
132 task_processor = task_executor.TaskProcessor(task_executor.SUITES_QUEUE)
Xixuan Wu0a8d3ee2017-10-19 11:33:26 -0700133 task_processor.batch_execute()
134 # After batch_execute, only failed suites and extra suites are
135 # kept in task queue.
Xixuan Wu835dee22017-09-07 10:47:29 -0700136 tasks = self.taskqueue_stub.get_filtered_tasks()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800137 self.assertEqual(len(tasks), error_num)
Xixuan Wu835dee22017-09-07 10:47:29 -0700138
139 def testBatchExecuteTaskFailedLeasing(self):
140 """Test task_executor fails to lease task."""
141 suite_kwargs = {'suite': 'fake_suite'}
142 task_executor.push(task_executor.SUITES_QUEUE, **suite_kwargs)
143
Xinan Lin9e4917d2019-11-04 10:58:47 -0800144 with mock.patch('buildbucket.TestPlatformClient',
145 return_value=FakeFrontdoorClient(False)):
146 task_processor = task_executor.TaskProcessor('nonExistentQueue')
Xixuan Wu835dee22017-09-07 10:47:29 -0700147 self.assertRaises(taskqueue.UnknownQueueError,
148 task_processor.batch_execute)
149 # After batch_execute fails, no tasks are deleted from task queue.
150 tasks = self.taskqueue_stub.get_filtered_tasks()
151 self.assertEqual(len(tasks), 1)
152
153
154if __name__ == '__main__':
155 unittest.main()