blob: 04591a08fbb834736ae30345b8d0e59592047f8c [file] [log] [blame]
Xinan Lin3ba18a02019-08-13 15:44:55 -07001# Copyright 2019 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 buildbucket unittests."""
6
7import mock
8import os
9import unittest
10
Xinan Lin9e4917d2019-11-04 10:58:47 -080011import constants
Xinan Lin3ba18a02019-08-13 15:44:55 -070012import build_lib
13import buildbucket
14import task_executor
15
16from chromite.api.gen.test_platform import request_pb2
Xinan Lin9e4917d2019-11-04 10:58:47 -080017from google.appengine.api import taskqueue
Xinan Lin3ba18a02019-08-13 15:44:55 -070018from google.appengine.ext import testbed
19from google.protobuf import json_format
20
21
22ADDR = u'http://localhost:1'
23
24
Xinan Lin9e4917d2019-11-04 10:58:47 -080025def _get_suite_params(board='fake_board',
26 model='fake_model',
27 suite='fake_suite',
28 pool='DUT_POOL_SUITES',
29 cros_build='fake_cros_build'):
Xinan Lin3ba18a02019-08-13 15:44:55 -070030 return {
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070031 'suite': suite,
32 'board': board,
33 'model': model,
34 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
Xinan Lin3ba18a02019-08-13 15:44:55 -070035 build_lib.BuildVersionKey.FW_RW_VERSION: 'fake_firmware_rw_build',
36 build_lib.BuildVersionKey.FW_RO_VERSION: 'fake_firmware_ro_build',
37 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: 'fake_android_build',
38 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: 'fake_testbed_build',
39 'num': 1,
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070040 'pool': pool,
Xinan Lin3ba18a02019-08-13 15:44:55 -070041 'priority': 10,
Xinan Lin6e097382019-08-27 18:43:35 -070042 'timeout': 12,
43 'timeout_mins': 4320,
44 'max_runtime_mins': 4320,
Xinan Lin3ba18a02019-08-13 15:44:55 -070045 'no_wait_for_results': True,
46 'test_source_build': 'fake_test_source_build',
47 'job_retry': False,
48 'no_delay': False,
49 'force': False,
50 'run_prod_code': True,
51 'is_skylab': False,
52 }
53
54
55class FakeTestPlatformClient(object):
56
57 def __init__(self, test):
58 self._test = test
59 self.called_with_requests = []
60
61 def ScheduleBuild(self, req, credentials=None):
62 self.called_with_requests.append(req)
63 # No test_platform_response proto. Simply return '200, ok'.
64 return '200 ok'
65
66
67class TestPlatformClientTestCase(unittest.TestCase):
68
69 def setUp(self):
70 super(TestPlatformClientTestCase, self).setUp()
71 self.fake_client = FakeTestPlatformClient(self)
72 patcher = mock.patch('buildbucket._get_client',
73 return_value=self._get_client(ADDR))
74 patcher.start()
75 self.client = buildbucket.TestPlatformClient(ADDR,
76 'foo-proj',
77 'foo-bucket',
78 'foo-builder')
79 self.addCleanup(patcher.stop)
80 self.testbed = testbed.Testbed()
81 self.testbed.activate()
82 self.addCleanup(self.testbed.deactivate)
83 self.testbed.init_taskqueue_stub(
84 root_path=os.path.join(os.path.dirname(__file__)))
85 self.taskqueue_stub = self.testbed.get_stub(
86 testbed.TASKQUEUE_SERVICE_NAME)
Xinan Lin9e4917d2019-11-04 10:58:47 -080087 self.queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Xinan Lin3ba18a02019-08-13 15:44:55 -070088
Xinan Lin9e4917d2019-11-04 10:58:47 -080089 def testFormTestPlatformMultiRequestSuccessfully(self):
90 suite_kwargs = [_get_suite_params(board=b)
91 for b in ['foo', 'goo']]
92 for suite in suite_kwargs:
93 task_executor.push(task_executor.SUITES_QUEUE,
94 tag='fake_suite', **suite)
Xinan Lin3ba18a02019-08-13 15:44:55 -070095
Xinan Lin9e4917d2019-11-04 10:58:47 -080096 tasks = self.queue.lease_tasks_by_tag(3600,
97 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
98
99 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700100 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800101
102 request_map = self._extract_request_map_from_bb_client()
103 request_list = [_struct_pb2_to_request_pb2(v)
104 for v in request_map.values()]
105 request_list.sort(
106 key=lambda req: req.params.software_attributes.build_target.name)
107 for i, req in enumerate(request_list):
108 self.assertEqual(req.params.scheduling.priority, 10)
109 self.assertEqual(req.params.scheduling.managed_pool,
110 request_pb2.Request.Params.Scheduling.MANAGED_POOL_SUITES)
111 self.assertEqual(req.params.time.maximum_duration.seconds, 165600)
112 self.assertEqual(req.params.metadata.test_metadata_url,
113 ('gs://chromeos-image-archive/%s' %
114 suite_kwargs[i]['test_source_build']))
115 self.assertEqual(req.test_plan.suite[0].name, suite_kwargs[i]['suite'])
116 self.assertEqual(req.params.software_attributes.build_target.name,
117 suite_kwargs[i]['board'])
118
119 def testPoolName(self):
120 suite_kwargs = [_get_suite_params(board=b)
121 for b in ['foo', 'goo', 'hoo']]
122 suite_kwargs[0]['pool'] = 'cts'
123 suite_kwargs[1]['pool'] = 'wifi'
124 suite_kwargs[2]['override_qs_account'] = 'dummy@foo.com'
125 for suite in suite_kwargs:
126 task_executor.push(task_executor.SUITES_QUEUE,
127 tag='some_suite', **suite)
128
129 tasks = self.queue.lease_tasks_by_tag(3600,
130 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
131 self.client.multirequest_run(tasks, 'some_suite')
132 self._assert_bb_client_called()
133 request_map = self._extract_request_map_from_bb_client()
134 request_list = [_struct_pb2_to_request_pb2(v)
135 for v in request_map.values()]
136 self.assertEqual(len(request_list), 3)
137 request_list.sort(
138 key=lambda req: req.params.software_attributes.build_target.name)
139 self.assertEqual(request_list[0].params.scheduling.managed_pool,
Alex Zamorzaevc1935602019-08-28 14:37:35 -0700140 request_pb2.Request.Params.Scheduling.MANAGED_POOL_CTS)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800141 self.assertEqual(request_list[1].params.scheduling.unmanaged_pool,
142 suite_kwargs[1]['pool'])
143 self.assertEqual(request_list[2].params.scheduling.quota_account,
144 suite_kwargs[2]['override_qs_account'])
Prathmesh Prabhu88409f62019-08-30 14:32:28 -0700145
Xinan Lin3ba18a02019-08-13 15:44:55 -0700146 def testNoFinalBuild(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800147 suite_kwargs = _get_suite_params()
148 suite_kwargs[build_lib.BuildVersionKey.CROS_VERSION] = None
149 suite_kwargs[build_lib.BuildVersionKey.ANDROID_BUILD_VERSION] = None
150 suite_kwargs[build_lib.BuildVersionKey.TESTBED_BUILD_VERSION] = None
151
152 task_executor.push(task_executor.SUITES_QUEUE,
153 tag='fake_suite', **suite_kwargs)
154
155 tasks = self.queue.lease_tasks_by_tag(3600,
156 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
157 executed = self.client.multirequest_run(tasks, 'fake_suite')
158 self.assertEqual(len(executed), 0)
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700159 self._assert_bb_client_not_called()
Xinan Lin3ba18a02019-08-13 15:44:55 -0700160
Xinan Lin9e4917d2019-11-04 10:58:47 -0800161 def testShouldSetPriority(self):
162 suite_kwargs = _get_suite_params()
163 suite_kwargs['priority'] = '30'
Xinan Linfb63d572019-09-24 15:49:04 -0700164
Xinan Lin9e4917d2019-11-04 10:58:47 -0800165 task_executor.push(task_executor.SUITES_QUEUE,
166 tag='fake_suite', **suite_kwargs)
167
168 tasks = self.queue.lease_tasks_by_tag(3600,
169 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
170 self.client.multirequest_run(tasks, 'fake_suite')
171 request_map = self._extract_request_map_from_bb_client()
Xinan Linfb63d572019-09-24 15:49:04 -0700172 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800173 self.assertEqual(len(request_map), 1)
174 req = _struct_pb2_to_request_pb2(request_map['fake_board_fake_model'])
175 self.assertEqual(req.params.scheduling.priority, 30)
176
177 def testRequestWithInvalidTags(self):
178 suite_kwargs = [_get_suite_params(board=b)
179 for b in ['foo', 'foo']]
180
181 # test request having None String Tag
182 suite_kwargs[0]['model'] = 'None'
183
184 # test request having None Tag
185 suite_kwargs[1]['model'] = None
186
187 for suite in suite_kwargs:
188 task_executor.push(task_executor.SUITES_QUEUE,
189 tag='fake_suite', **suite)
190
191 tasks = self.queue.lease_tasks_by_tag(3600,
192 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
193 executed = self.client.multirequest_run(tasks, 'fake_suite')
194 self.assertEqual(len(executed), 2)
195
196 self._assert_bb_client_called()
197 request_map = self._extract_request_map_from_bb_client()
198 self.assertEqual(len(request_map), 2)
Xinan Linfb63d572019-09-24 15:49:04 -0700199 want = {
Xinan Lin9e4917d2019-11-04 10:58:47 -0800200 'suite:fake_suite',
201 'build:fake_cros_build',
Xinan Linfb63d572019-09-24 15:49:04 -0700202 'label-pool:DUT_POOL_SUITES',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800203 'label-board:foo',
Xinan Linfb63d572019-09-24 15:49:04 -0700204 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800205 want_bb = {
206 'suite:fake_suite',
207 }
208 for req_name in ['foo', 'foo_1']:
209 req = _struct_pb2_to_request_pb2(request_map[req_name])
210 req_tags = set([t for t in req.params.decorations.tags])
211 self.assertEqual(want, req_tags)
212 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
213 self.assertEqual(want_bb, bb_tags)
Xinan Linfb63d572019-09-24 15:49:04 -0700214
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700215 def testRequestTags(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800216 suite_kwargs = _get_suite_params(
217 board='fake_board',
218 model='fake_model',
219 pool='DUT_POOL_SUITES',
220 suite='fake_suite',
221 cros_build='fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700222 )
Xinan Lin9e4917d2019-11-04 10:58:47 -0800223 task_executor.push(task_executor.SUITES_QUEUE,
224 tag='fake_suite', **suite_kwargs)
225
226 tasks = self.queue.lease_tasks_by_tag(3600,
227 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
228 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700229 self._assert_bb_client_called()
230 want = {
Xinan Lin9e4917d2019-11-04 10:58:47 -0800231 'label-board:fake_board',
232 'label-model:fake_model',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700233 'label-pool:DUT_POOL_SUITES',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800234 'suite:fake_suite',
235 'build:fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700236 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800237 want_bb = {
238 'suite:fake_suite',
239 }
240 request_map = self._extract_request_map_from_bb_client()
241 request_list = [_struct_pb2_to_request_pb2(v)
242 for v in request_map.values()]
243 self.assertEqual(len(request_list), 1)
244 req = request_list[0]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700245 req_tags = set([t for t in req.params.decorations.tags])
246 self.assertEqual(want, req_tags)
247 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800248 self.assertEqual(want_bb, bb_tags)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700249
Prathmesh Prabhu73801e12019-08-30 14:09:31 -0700250 def _get_client(self, addr):
251 self.assertEqual(ADDR, addr)
252 return self.fake_client
253
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700254 def _assert_bb_client_called(self):
255 self.assertEqual(len(self.fake_client.called_with_requests), 1)
256
257 def _assert_bb_client_not_called(self):
258 self.assertEqual(len(self.fake_client.called_with_requests), 0)
259
Xinan Lin9e4917d2019-11-04 10:58:47 -0800260 def _extract_request_map_from_bb_client(self):
261 return self.fake_client.called_with_requests[0].properties['requests']
Prathmesh Prabhu6348ea82019-08-30 14:15:21 -0700262
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700263 def _extract_tags_from_bb_client(self):
264 return ['%s:%s' % (t.key, t.value)
265 for t in self.fake_client.called_with_requests[0].tags]
266
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700267
Xinan Lin3ba18a02019-08-13 15:44:55 -0700268def _struct_pb2_to_request_pb2(struct_pb2):
269 """Transform google struct proto to test_platform_request.
270
271 Args:
272 struct_pb2: A struct_pb2 instance.
273
274 Returns:
275 A request_pb2 instance.
276 """
277 json = json_format.MessageToJson(struct_pb2)
278 return json_format.Parse(json, request_pb2.Request())