blob: f4048741960e30cdde4ecbedd8c90ba95486229d [file] [log] [blame]
Aviv Keshetc679faf2019-11-27 17:52:50 -08001#!/usr/bin/env python2
Xinan Lin3ba18a02019-08-13 15:44:55 -07002# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Module for buildbucket unittests."""
7
8import mock
9import os
10import unittest
11
Xinan Lin9e4917d2019-11-04 10:58:47 -080012import constants
Xinan Lin3ba18a02019-08-13 15:44:55 -070013import build_lib
14import buildbucket
15import task_executor
16
17from chromite.api.gen.test_platform import request_pb2
Xinan Lin9e4917d2019-11-04 10:58:47 -080018from google.appengine.api import taskqueue
Xinan Lin3ba18a02019-08-13 15:44:55 -070019from google.appengine.ext import testbed
20from google.protobuf import json_format
21
22
23ADDR = u'http://localhost:1'
24
25
Xinan Lin9e4917d2019-11-04 10:58:47 -080026def _get_suite_params(board='fake_board',
27 model='fake_model',
28 suite='fake_suite',
29 pool='DUT_POOL_SUITES',
30 cros_build='fake_cros_build'):
Xinan Lin3ba18a02019-08-13 15:44:55 -070031 return {
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070032 'suite': suite,
33 'board': board,
34 'model': model,
35 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
Xinan Lin3ba18a02019-08-13 15:44:55 -070036 build_lib.BuildVersionKey.FW_RW_VERSION: 'fake_firmware_rw_build',
37 build_lib.BuildVersionKey.FW_RO_VERSION: 'fake_firmware_ro_build',
38 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: 'fake_android_build',
39 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: 'fake_testbed_build',
40 'num': 1,
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070041 'pool': pool,
Xinan Lin3ba18a02019-08-13 15:44:55 -070042 'priority': 10,
Xinan Lin6e097382019-08-27 18:43:35 -070043 'timeout': 12,
44 'timeout_mins': 4320,
45 'max_runtime_mins': 4320,
Xinan Lin3ba18a02019-08-13 15:44:55 -070046 'no_wait_for_results': True,
47 'test_source_build': 'fake_test_source_build',
48 'job_retry': False,
49 'no_delay': False,
50 'force': False,
51 'run_prod_code': True,
52 'is_skylab': False,
53 }
54
55
56class FakeTestPlatformClient(object):
57
58 def __init__(self, test):
59 self._test = test
60 self.called_with_requests = []
61
62 def ScheduleBuild(self, req, credentials=None):
63 self.called_with_requests.append(req)
64 # No test_platform_response proto. Simply return '200, ok'.
65 return '200 ok'
66
67
68class TestPlatformClientTestCase(unittest.TestCase):
69
70 def setUp(self):
71 super(TestPlatformClientTestCase, self).setUp()
72 self.fake_client = FakeTestPlatformClient(self)
73 patcher = mock.patch('buildbucket._get_client',
74 return_value=self._get_client(ADDR))
75 patcher.start()
76 self.client = buildbucket.TestPlatformClient(ADDR,
77 'foo-proj',
78 'foo-bucket',
79 'foo-builder')
80 self.addCleanup(patcher.stop)
81 self.testbed = testbed.Testbed()
82 self.testbed.activate()
83 self.addCleanup(self.testbed.deactivate)
84 self.testbed.init_taskqueue_stub(
85 root_path=os.path.join(os.path.dirname(__file__)))
86 self.taskqueue_stub = self.testbed.get_stub(
87 testbed.TASKQUEUE_SERVICE_NAME)
Xinan Lin9e4917d2019-11-04 10:58:47 -080088 self.queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Xinan Lin3ba18a02019-08-13 15:44:55 -070089
Xinan Lin9e4917d2019-11-04 10:58:47 -080090 def testFormTestPlatformMultiRequestSuccessfully(self):
91 suite_kwargs = [_get_suite_params(board=b)
92 for b in ['foo', 'goo']]
93 for suite in suite_kwargs:
94 task_executor.push(task_executor.SUITES_QUEUE,
95 tag='fake_suite', **suite)
Xinan Lin3ba18a02019-08-13 15:44:55 -070096
Xinan Lin9e4917d2019-11-04 10:58:47 -080097 tasks = self.queue.lease_tasks_by_tag(3600,
98 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
99
100 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700101 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800102
103 request_map = self._extract_request_map_from_bb_client()
104 request_list = [_struct_pb2_to_request_pb2(v)
105 for v in request_map.values()]
106 request_list.sort(
107 key=lambda req: req.params.software_attributes.build_target.name)
108 for i, req in enumerate(request_list):
109 self.assertEqual(req.params.scheduling.priority, 10)
110 self.assertEqual(req.params.scheduling.managed_pool,
111 request_pb2.Request.Params.Scheduling.MANAGED_POOL_SUITES)
112 self.assertEqual(req.params.time.maximum_duration.seconds, 165600)
Aviv Keshetc679faf2019-11-27 17:52:50 -0800113 gs_url = ('gs://chromeos-image-archive/%s' %
114 suite_kwargs[i]['test_source_build'])
115 self.assertEqual(req.params.metadata.test_metadata_url, gs_url)
116 self.assertEqual(req.params.metadata.debug_symbols_archive_url, gs_url)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800117 self.assertEqual(req.test_plan.suite[0].name, suite_kwargs[i]['suite'])
118 self.assertEqual(req.params.software_attributes.build_target.name,
119 suite_kwargs[i]['board'])
120
121 def testPoolName(self):
122 suite_kwargs = [_get_suite_params(board=b)
123 for b in ['foo', 'goo', 'hoo']]
124 suite_kwargs[0]['pool'] = 'cts'
125 suite_kwargs[1]['pool'] = 'wifi'
126 suite_kwargs[2]['override_qs_account'] = 'dummy@foo.com'
127 for suite in suite_kwargs:
128 task_executor.push(task_executor.SUITES_QUEUE,
129 tag='some_suite', **suite)
130
131 tasks = self.queue.lease_tasks_by_tag(3600,
132 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
133 self.client.multirequest_run(tasks, 'some_suite')
134 self._assert_bb_client_called()
135 request_map = self._extract_request_map_from_bb_client()
136 request_list = [_struct_pb2_to_request_pb2(v)
137 for v in request_map.values()]
138 self.assertEqual(len(request_list), 3)
139 request_list.sort(
140 key=lambda req: req.params.software_attributes.build_target.name)
141 self.assertEqual(request_list[0].params.scheduling.managed_pool,
Alex Zamorzaevc1935602019-08-28 14:37:35 -0700142 request_pb2.Request.Params.Scheduling.MANAGED_POOL_CTS)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800143 self.assertEqual(request_list[1].params.scheduling.unmanaged_pool,
144 suite_kwargs[1]['pool'])
145 self.assertEqual(request_list[2].params.scheduling.quota_account,
146 suite_kwargs[2]['override_qs_account'])
Prathmesh Prabhu88409f62019-08-30 14:32:28 -0700147
Xinan Lin3ba18a02019-08-13 15:44:55 -0700148 def testNoFinalBuild(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800149 suite_kwargs = _get_suite_params()
150 suite_kwargs[build_lib.BuildVersionKey.CROS_VERSION] = None
151 suite_kwargs[build_lib.BuildVersionKey.ANDROID_BUILD_VERSION] = None
152 suite_kwargs[build_lib.BuildVersionKey.TESTBED_BUILD_VERSION] = None
153
154 task_executor.push(task_executor.SUITES_QUEUE,
155 tag='fake_suite', **suite_kwargs)
156
157 tasks = self.queue.lease_tasks_by_tag(3600,
158 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
159 executed = self.client.multirequest_run(tasks, 'fake_suite')
160 self.assertEqual(len(executed), 0)
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700161 self._assert_bb_client_not_called()
Xinan Lin3ba18a02019-08-13 15:44:55 -0700162
Xinan Lin9e4917d2019-11-04 10:58:47 -0800163 def testShouldSetPriority(self):
164 suite_kwargs = _get_suite_params()
165 suite_kwargs['priority'] = '30'
Xinan Linfb63d572019-09-24 15:49:04 -0700166
Xinan Lin9e4917d2019-11-04 10:58:47 -0800167 task_executor.push(task_executor.SUITES_QUEUE,
168 tag='fake_suite', **suite_kwargs)
169
170 tasks = self.queue.lease_tasks_by_tag(3600,
171 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
172 self.client.multirequest_run(tasks, 'fake_suite')
173 request_map = self._extract_request_map_from_bb_client()
Xinan Linfb63d572019-09-24 15:49:04 -0700174 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800175 self.assertEqual(len(request_map), 1)
176 req = _struct_pb2_to_request_pb2(request_map['fake_board_fake_model'])
177 self.assertEqual(req.params.scheduling.priority, 30)
178
179 def testRequestWithInvalidTags(self):
180 suite_kwargs = [_get_suite_params(board=b)
181 for b in ['foo', 'foo']]
182
183 # test request having None String Tag
184 suite_kwargs[0]['model'] = 'None'
185
186 # test request having None Tag
187 suite_kwargs[1]['model'] = None
188
189 for suite in suite_kwargs:
190 task_executor.push(task_executor.SUITES_QUEUE,
191 tag='fake_suite', **suite)
192
193 tasks = self.queue.lease_tasks_by_tag(3600,
194 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
195 executed = self.client.multirequest_run(tasks, 'fake_suite')
196 self.assertEqual(len(executed), 2)
197
198 self._assert_bb_client_called()
199 request_map = self._extract_request_map_from_bb_client()
200 self.assertEqual(len(request_map), 2)
Xinan Linfb63d572019-09-24 15:49:04 -0700201 want = {
Xinan Lin9e4917d2019-11-04 10:58:47 -0800202 'suite:fake_suite',
203 'build:fake_cros_build',
Xinan Linfb63d572019-09-24 15:49:04 -0700204 'label-pool:DUT_POOL_SUITES',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800205 'label-board:foo',
Xinan Linfb63d572019-09-24 15:49:04 -0700206 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800207 want_bb = {
208 'suite:fake_suite',
209 }
210 for req_name in ['foo', 'foo_1']:
211 req = _struct_pb2_to_request_pb2(request_map[req_name])
212 req_tags = set([t for t in req.params.decorations.tags])
213 self.assertEqual(want, req_tags)
214 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
215 self.assertEqual(want_bb, bb_tags)
Xinan Linfb63d572019-09-24 15:49:04 -0700216
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700217 def testRequestTags(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800218 suite_kwargs = _get_suite_params(
219 board='fake_board',
220 model='fake_model',
221 pool='DUT_POOL_SUITES',
222 suite='fake_suite',
223 cros_build='fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700224 )
Xinan Lin9e4917d2019-11-04 10:58:47 -0800225 task_executor.push(task_executor.SUITES_QUEUE,
226 tag='fake_suite', **suite_kwargs)
227
228 tasks = self.queue.lease_tasks_by_tag(3600,
229 constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
230 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700231 self._assert_bb_client_called()
232 want = {
Xinan Lin9e4917d2019-11-04 10:58:47 -0800233 'label-board:fake_board',
234 'label-model:fake_model',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700235 'label-pool:DUT_POOL_SUITES',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800236 'suite:fake_suite',
237 'build:fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700238 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800239 want_bb = {
240 'suite:fake_suite',
241 }
242 request_map = self._extract_request_map_from_bb_client()
243 request_list = [_struct_pb2_to_request_pb2(v)
244 for v in request_map.values()]
245 self.assertEqual(len(request_list), 1)
246 req = request_list[0]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700247 req_tags = set([t for t in req.params.decorations.tags])
248 self.assertEqual(want, req_tags)
249 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800250 self.assertEqual(want_bb, bb_tags)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700251
Prathmesh Prabhu73801e12019-08-30 14:09:31 -0700252 def _get_client(self, addr):
253 self.assertEqual(ADDR, addr)
254 return self.fake_client
255
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700256 def _assert_bb_client_called(self):
257 self.assertEqual(len(self.fake_client.called_with_requests), 1)
258
259 def _assert_bb_client_not_called(self):
260 self.assertEqual(len(self.fake_client.called_with_requests), 0)
261
Xinan Lin9e4917d2019-11-04 10:58:47 -0800262 def _extract_request_map_from_bb_client(self):
263 return self.fake_client.called_with_requests[0].properties['requests']
Prathmesh Prabhu6348ea82019-08-30 14:15:21 -0700264
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700265 def _extract_tags_from_bb_client(self):
266 return ['%s:%s' % (t.key, t.value)
267 for t in self.fake_client.called_with_requests[0].tags]
268
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700269
Xinan Lin3ba18a02019-08-13 15:44:55 -0700270def _struct_pb2_to_request_pb2(struct_pb2):
271 """Transform google struct proto to test_platform_request.
272
273 Args:
274 struct_pb2: A struct_pb2 instance.
275
276 Returns:
277 A request_pb2 instance.
278 """
279 json = json_format.MessageToJson(struct_pb2)
280 return json_format.Parse(json, request_pb2.Request())