blob: 0de25c83ea517a8e33e921e21e108e3c1c7fb1a5 [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.
Xinan Lin3ba18a02019-08-13 15:44:55 -07005"""Module for buildbucket unittests."""
6
Xinan Lindf0698a2020-02-05 22:38:11 -08007import json
Xinan Lin3ba18a02019-08-13 15:44:55 -07008import 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
Jacob Kopczynskicefd50c2020-07-31 10:05:10 -070017from chromite.api.gen.test_platform import request_pb2 as ctp_request
Xinan Lindf0698a2020-02-05 22:38:11 -080018from chromite.api.gen.test_platform.suite_scheduler import analytics_pb2
Xinan Lin9e4917d2019-11-04 10:58:47 -080019from google.appengine.api import taskqueue
Xinan Lin3ba18a02019-08-13 15:44:55 -070020from google.appengine.ext import testbed
21from google.protobuf import json_format
Xinan Lindf0698a2020-02-05 22:38:11 -080022from infra_libs.buildbucket.proto import build_pb2
Xinan Lin3ba18a02019-08-13 15:44:55 -070023
Xinan Lin3ba18a02019-08-13 15:44:55 -070024ADDR = u'http://localhost:1'
Xinan Lindf0698a2020-02-05 22:38:11 -080025FAKE_UUID = 'c78e0bf3-4142-11ea-bc66-88e9fe4c5349'
26FAKE_BUILD_ID = 8890493019851395280
Xinan Lin3ba18a02019-08-13 15:44:55 -070027
28
Xinan Lin9e4917d2019-11-04 10:58:47 -080029def _get_suite_params(board='fake_board',
30 model='fake_model',
31 suite='fake_suite',
Xinan Lin1516edb2020-07-05 23:13:54 -070032 pool='MANAGED_POOL_QUOTA',
Xinan Lin9e4917d2019-11-04 10:58:47 -080033 cros_build='fake_cros_build'):
Xinan Lin3ba18a02019-08-13 15:44:55 -070034 return {
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070035 'suite': suite,
36 'board': board,
37 'model': model,
38 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
Xinan Lin3ba18a02019-08-13 15:44:55 -070039 build_lib.BuildVersionKey.FW_RW_VERSION: 'fake_firmware_rw_build',
40 build_lib.BuildVersionKey.FW_RO_VERSION: 'fake_firmware_ro_build',
41 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: 'fake_android_build',
42 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: 'fake_testbed_build',
43 'num': 1,
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070044 'pool': pool,
Xinan Lin3ba18a02019-08-13 15:44:55 -070045 'priority': 10,
Xinan Lin6e097382019-08-27 18:43:35 -070046 'timeout': 12,
47 'timeout_mins': 4320,
48 'max_runtime_mins': 4320,
Xinan Lin3ba18a02019-08-13 15:44:55 -070049 'no_wait_for_results': True,
50 'test_source_build': 'fake_test_source_build',
51 'job_retry': False,
52 'no_delay': False,
53 'force': False,
54 'run_prod_code': True,
55 'is_skylab': False,
56 }
57
58
59class FakeTestPlatformClient(object):
Xinan Lin3ba18a02019-08-13 15:44:55 -070060 def __init__(self, test):
61 self._test = test
62 self.called_with_requests = []
Xinan Lindf0698a2020-02-05 22:38:11 -080063 self.error = None
Xinan Lin3ba18a02019-08-13 15:44:55 -070064
Xinan Lin57e2d962020-03-30 17:24:53 -070065 def ScheduleBuild(self, req, credentials=None, timeout=10):
Xinan Lin3ba18a02019-08-13 15:44:55 -070066 self.called_with_requests.append(req)
Xinan Lindf0698a2020-02-05 22:38:11 -080067 if self.error:
68 return self.error
69 return build_pb2.Build(id=FAKE_BUILD_ID)
70
71
72class FakeBigqueryRestClient(object):
Xinan Lindf0698a2020-02-05 22:38:11 -080073 def __init__(self, rest_client, project=None, dataset=None, table=None):
74 """Initialize the mock class."""
75 self.table = table
76 self.rows = []
77
78 def insert(self, rows):
79 self.rows = rows
80 return True
Xinan Lin3ba18a02019-08-13 15:44:55 -070081
82
83class TestPlatformClientTestCase(unittest.TestCase):
Xinan Lin3ba18a02019-08-13 15:44:55 -070084 def setUp(self):
85 super(TestPlatformClientTestCase, self).setUp()
86 self.fake_client = FakeTestPlatformClient(self)
87 patcher = mock.patch('buildbucket._get_client',
88 return_value=self._get_client(ADDR))
89 patcher.start()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -070090 self.client = buildbucket.TestPlatformClient(ADDR, 'foo-proj',
91 'foo-bucket', 'foo-builder')
Xinan Lin3ba18a02019-08-13 15:44:55 -070092 self.addCleanup(patcher.stop)
93 self.testbed = testbed.Testbed()
94 self.testbed.activate()
95 self.addCleanup(self.testbed.deactivate)
96 self.testbed.init_taskqueue_stub(
97 root_path=os.path.join(os.path.dirname(__file__)))
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -070098 self.taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
Xinan Lin9e4917d2019-11-04 10:58:47 -080099 self.queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Xinan Linc54a7462020-04-17 15:39:01 -0700100 _mock_application_id = mock.patch('constants.application_id')
101 self.mock_application_id = _mock_application_id.start()
102 self.addCleanup(_mock_application_id.stop)
103 self.mock_application_id.return_value = constants.AppID.PROD_APP
Xinan Lin3ba18a02019-08-13 15:44:55 -0700104
Xinan Lin9e4917d2019-11-04 10:58:47 -0800105 def testFormTestPlatformMultiRequestSuccessfully(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700106 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'goo']]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800107 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700108 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700109
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700110 tasks = self.queue.lease_tasks_by_tag(
111 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800112
113 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700114 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800115
116 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700117 request_list = [
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700118 _struct_pb2_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700119 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800120 request_list.sort(
121 key=lambda req: req.params.software_attributes.build_target.name)
122 for i, req in enumerate(request_list):
123 self.assertEqual(req.params.scheduling.priority, 10)
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700124 self.assertEqual(
125 req.params.scheduling.managed_pool,
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700126 ctp_request.Request.Params.Scheduling.MANAGED_POOL_QUOTA)
Prathmesh Prabhu9adfa632020-02-21 10:39:24 -0800127 # Don't check for exact max timeout to stay DRY.
128 # But do check that the maximum is sane.
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700129 self.assertLess(req.params.time.maximum_duration.seconds,
130 2 * 24 * 60 * 60)
Aviv Keshetc679faf2019-11-27 17:52:50 -0800131 gs_url = ('gs://chromeos-image-archive/%s' %
132 suite_kwargs[i]['test_source_build'])
133 self.assertEqual(req.params.metadata.test_metadata_url, gs_url)
134 self.assertEqual(req.params.metadata.debug_symbols_archive_url, gs_url)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800135 self.assertEqual(req.test_plan.suite[0].name, suite_kwargs[i]['suite'])
136 self.assertEqual(req.params.software_attributes.build_target.name,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700137 suite_kwargs[i]['board'])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800138
139 def testPoolName(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700140 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'goo', 'hoo']]
Xinan Lin1516edb2020-07-05 23:13:54 -0700141 suite_kwargs[0]['pool'] = 'MANAGED_POOL_CTS'
Xinan Lin9e4917d2019-11-04 10:58:47 -0800142 suite_kwargs[1]['pool'] = 'wifi'
Xinan Lin9e4917d2019-11-04 10:58:47 -0800143 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700144 task_executor.push(task_executor.SUITES_QUEUE, tag='some_suite', **suite)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800145
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700146 tasks = self.queue.lease_tasks_by_tag(
147 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800148 self.client.multirequest_run(tasks, 'some_suite')
149 self._assert_bb_client_called()
150 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700151 request_list = [
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700152 _struct_pb2_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700153 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800154 self.assertEqual(len(request_list), 3)
155 request_list.sort(
156 key=lambda req: req.params.software_attributes.build_target.name)
157 self.assertEqual(request_list[0].params.scheduling.managed_pool,
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700158 ctp_request.Request.Params.Scheduling.MANAGED_POOL_CTS)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800159 self.assertEqual(request_list[1].params.scheduling.unmanaged_pool,
160 suite_kwargs[1]['pool'])
Prathmesh Prabhu88409f62019-08-30 14:32:28 -0700161
Xinan Lin3ba18a02019-08-13 15:44:55 -0700162 def testNoFinalBuild(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800163 suite_kwargs = _get_suite_params()
164 suite_kwargs[build_lib.BuildVersionKey.CROS_VERSION] = None
165 suite_kwargs[build_lib.BuildVersionKey.ANDROID_BUILD_VERSION] = None
166 suite_kwargs[build_lib.BuildVersionKey.TESTBED_BUILD_VERSION] = None
167
168 task_executor.push(task_executor.SUITES_QUEUE,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700169 tag='fake_suite',
170 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800171
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700172 tasks = self.queue.lease_tasks_by_tag(
173 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800174 executed = self.client.multirequest_run(tasks, 'fake_suite')
175 self.assertEqual(len(executed), 0)
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700176 self._assert_bb_client_not_called()
Xinan Lin3ba18a02019-08-13 15:44:55 -0700177
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700178 def testShouldSetQsAccountForUnmanagedPool(self):
Xinan Lin4757d6f2020-03-24 22:20:31 -0700179 suite_kwargs = _get_suite_params(pool='foo')
180 suite_kwargs['priority'] = '30'
181 suite_kwargs['qs_account'] = 'qs-foo'
182
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700183 task_executor.push(task_executor.SUITES_QUEUE,
184 tag='fake_suite',
185 **suite_kwargs)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700186
187 tasks = self.queue.lease_tasks_by_tag(
188 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
189 self.client.multirequest_run(tasks, 'fake_suite')
190 request_map = self._extract_request_map_from_bb_client()
191 self._assert_bb_client_called()
192 self.assertEqual(len(request_map), 1)
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700193 req = _struct_pb2_to_ctp_request(request_map['fake_board_fake_model'])
Xinan Lin4757d6f2020-03-24 22:20:31 -0700194 self.assertEqual(req.params.scheduling.qs_account, 'qs-foo')
195 # If qs_account is set, priority should be 0, the default value
196 # defined by proto3.
197 self.assertEqual(req.params.scheduling.priority, 0)
198
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700199 def testShouldSetQsAccountForManagedPool(self):
Xinan Lin1516edb2020-07-05 23:13:54 -0700200 suite_kwargs = _get_suite_params(pool='MANAGED_POOL_QUOTA')
Xinan Lin4757d6f2020-03-24 22:20:31 -0700201 suite_kwargs['qs_account'] = 'qs-foo'
202
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700203 task_executor.push(task_executor.SUITES_QUEUE,
204 tag='fake_suite',
205 **suite_kwargs)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700206
207 tasks = self.queue.lease_tasks_by_tag(
208 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
209 self.client.multirequest_run(tasks, 'fake_suite')
210 request_map = self._extract_request_map_from_bb_client()
211 self._assert_bb_client_called()
212 self.assertEqual(len(request_map), 1)
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700213 req = _struct_pb2_to_ctp_request(request_map['fake_board_fake_model'])
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700214 self.assertEqual(req.params.scheduling.qs_account, 'qs-foo')
215 # If qs_account is set, priority should be 0, the default value
216 # defined by proto3.
217 self.assertEqual(req.params.scheduling.priority, 0)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700218
Xinan Lin9e4917d2019-11-04 10:58:47 -0800219 def testShouldSetPriority(self):
220 suite_kwargs = _get_suite_params()
221 suite_kwargs['priority'] = '30'
Xinan Linfb63d572019-09-24 15:49:04 -0700222
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700223 task_executor.push(task_executor.SUITES_QUEUE,
224 tag='fake_suite',
225 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800226
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700227 tasks = self.queue.lease_tasks_by_tag(
228 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800229 self.client.multirequest_run(tasks, 'fake_suite')
230 request_map = self._extract_request_map_from_bb_client()
Xinan Linfb63d572019-09-24 15:49:04 -0700231 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800232 self.assertEqual(len(request_map), 1)
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700233 req = _struct_pb2_to_ctp_request(request_map['fake_board_fake_model'])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800234 self.assertEqual(req.params.scheduling.priority, 30)
235
236 def testRequestWithInvalidTags(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700237 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'foo']]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800238
239 # test request having None String Tag
240 suite_kwargs[0]['model'] = 'None'
241
242 # test request having None Tag
243 suite_kwargs[1]['model'] = None
244
245 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700246 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800247
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700248 tasks = self.queue.lease_tasks_by_tag(
249 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800250 executed = self.client.multirequest_run(tasks, 'fake_suite')
251 self.assertEqual(len(executed), 2)
252
253 self._assert_bb_client_called()
254 request_map = self._extract_request_map_from_bb_client()
255 self.assertEqual(len(request_map), 2)
Xinan Linfb63d572019-09-24 15:49:04 -0700256 want = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700257 'suite:fake_suite',
258 'build:fake_cros_build',
Xinan Lin1516edb2020-07-05 23:13:54 -0700259 'label-pool:MANAGED_POOL_QUOTA',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700260 'label-board:foo',
Xinan Linfb63d572019-09-24 15:49:04 -0700261 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800262 want_bb = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700263 'suite:fake_suite',
Dhanya Ganeshedb78cb2020-07-20 19:40:50 +0000264 'user_agent:suite_scheduler',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800265 }
266 for req_name in ['foo', 'foo_1']:
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700267 req = _struct_pb2_to_ctp_request(request_map[req_name])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800268 req_tags = set([t for t in req.params.decorations.tags])
269 self.assertEqual(want, req_tags)
270 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
271 self.assertEqual(want_bb, bb_tags)
Xinan Linfb63d572019-09-24 15:49:04 -0700272
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700273 def testRequestTags(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800274 suite_kwargs = _get_suite_params(
275 board='fake_board',
276 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700277 pool='DUT_POOL_QUOTA',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800278 suite='fake_suite',
279 cros_build='fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700280 )
Xinan Lin9e4917d2019-11-04 10:58:47 -0800281 task_executor.push(task_executor.SUITES_QUEUE,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700282 tag='fake_suite',
283 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800284
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700285 tasks = self.queue.lease_tasks_by_tag(
286 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800287 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700288 self._assert_bb_client_called()
289 want = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700290 'label-board:fake_board',
291 'label-model:fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700292 'label-pool:DUT_POOL_QUOTA',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700293 'suite:fake_suite',
294 'build:fake_build',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700295 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800296 want_bb = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700297 'suite:fake_suite',
Dhanya Ganeshedb78cb2020-07-20 19:40:50 +0000298 'user_agent:suite_scheduler',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800299 }
300 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700301 request_list = [
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700302 _struct_pb2_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700303 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800304 self.assertEqual(len(request_list), 1)
305 req = request_list[0]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700306 req_tags = set([t for t in req.params.decorations.tags])
307 self.assertEqual(want, req_tags)
308 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800309 self.assertEqual(want_bb, bb_tags)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700310
Xinan Linba3b9322020-04-24 15:08:12 -0700311 def testRequestUserDefinedDimensions(self):
312 suite_kwargs = _get_suite_params(
313 board='fake_board',
314 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700315 pool='MANAGED_POOL_QUOTA',
Xinan Linba3b9322020-04-24 15:08:12 -0700316 suite='fake_suite',
317 cros_build='fake_build',
318 )
319 suite_kwargs['dimensions'] = 'label-wifi:foo,label-bt:hoo'
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700320 task_executor.push(task_executor.SUITES_QUEUE,
321 tag='fake_suite',
322 **suite_kwargs)
Xinan Linba3b9322020-04-24 15:08:12 -0700323
324 tasks = self.queue.lease_tasks_by_tag(
325 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
326 self.client.multirequest_run(tasks, 'fake_suite')
327 self._assert_bb_client_called()
328 request_map = self._extract_request_map_from_bb_client()
329 request_list = [
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700330 _struct_pb2_to_ctp_request(v) for v in request_map.values()
Xinan Linba3b9322020-04-24 15:08:12 -0700331 ]
332 self.assertEqual(len(request_list), 1)
333 req = request_list[0]
334 free_dimensions = req.params.freeform_attributes.swarming_dimensions
335 self.assertTrue(len(free_dimensions), 2)
336 self.assertTrue('label-wifi:foo' in free_dimensions)
337 self.assertTrue('label-bt:hoo' in free_dimensions)
338
339 def testRequestInvalidUserDefinedDimensions(self):
340 suite_kwargs = _get_suite_params(
341 board='fake_board',
342 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700343 pool='MANAGED_POOL_QUOTA',
Xinan Linba3b9322020-04-24 15:08:12 -0700344 suite='fake_suite',
345 cros_build='fake_build',
346 )
347 suite_kwargs['dimensions'] = 'invalid-dimension'
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700348 task_executor.push(task_executor.SUITES_QUEUE,
349 tag='fake_suite',
350 **suite_kwargs)
Xinan Linba3b9322020-04-24 15:08:12 -0700351
352 tasks = self.queue.lease_tasks_by_tag(
353 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
354 self.client.multirequest_run(tasks, 'fake_suite')
355 self._assert_bb_client_not_called()
356
Prathmesh Prabhu73801e12019-08-30 14:09:31 -0700357 def _get_client(self, addr):
358 self.assertEqual(ADDR, addr)
359 return self.fake_client
360
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700361 def _assert_bb_client_called(self):
362 self.assertEqual(len(self.fake_client.called_with_requests), 1)
363
364 def _assert_bb_client_not_called(self):
365 self.assertEqual(len(self.fake_client.called_with_requests), 0)
366
Xinan Lin9e4917d2019-11-04 10:58:47 -0800367 def _extract_request_map_from_bb_client(self):
368 return self.fake_client.called_with_requests[0].properties['requests']
Prathmesh Prabhu6348ea82019-08-30 14:15:21 -0700369
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700370 def _extract_tags_from_bb_client(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700371 return [
372 '%s:%s' % (t.key, t.value)
373 for t in self.fake_client.called_with_requests[0].tags
374 ]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700375
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700376
Xinan Lindf0698a2020-02-05 22:38:11 -0800377class TestTaskExecutions(TestPlatformClientTestCase):
Xinan Lindf0698a2020-02-05 22:38:11 -0800378 def setUp(self):
379 super(TestTaskExecutions, self).setUp()
380 _mock_bq_client = mock.patch('rest_client.BigqueryRestClient')
381 mock_bq_client = _mock_bq_client.start()
382 self.addCleanup(_mock_bq_client.stop)
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700383 self.mock_bq_client = FakeBigqueryRestClient(None,
384 project='proj',
385 dataset='dataset',
386 table='foo')
Xinan Lindf0698a2020-02-05 22:38:11 -0800387 mock_bq_client.return_value = self.mock_bq_client
388
389 def testRecordSuccessfulTaskExecution(self):
Xinan Lin083ba8f2020-02-06 13:55:18 -0800390 suite = _get_suite_params(board='foo')
391 suite['task_id'] = FAKE_UUID
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700392 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
393 tasks = self.queue.lease_tasks_by_tag(
394 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lindf0698a2020-02-05 22:38:11 -0800395 self.client.multirequest_run(tasks, 'fake_suite')
396 self._assert_bb_client_called()
397 task_execution = json_format.Parse(
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700398 json.dumps(self.mock_bq_client.rows[0]['json']),
399 analytics_pb2.ExecutionTask())
Xinan Lindf0698a2020-02-05 22:38:11 -0800400 self.assertEqual(task_execution.queued_task_id, FAKE_UUID)
401 self.assertEqual(task_execution.response.ctp_build_id, str(FAKE_BUILD_ID))
402 self.assertEqual(task_execution.error.error_message, '')
403
404 def testRecordFailedTaskExecution(self):
Xinan Lin083ba8f2020-02-06 13:55:18 -0800405 suite = _get_suite_params(board='foo')
406 suite['task_id'] = FAKE_UUID
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700407 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lindf0698a2020-02-05 22:38:11 -0800408 self.fake_client.error = "cros_test_platform error"
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700409 tasks = self.queue.lease_tasks_by_tag(
410 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lindf0698a2020-02-05 22:38:11 -0800411 self.client.multirequest_run(tasks, 'fake_suite')
412 self._assert_bb_client_called()
413 task_execution = json_format.Parse(
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700414 json.dumps(self.mock_bq_client.rows[0]['json']),
415 analytics_pb2.ExecutionTask())
Xinan Lindf0698a2020-02-05 22:38:11 -0800416 self.assertEqual(task_execution.queued_task_id, FAKE_UUID)
417 self.assertEqual(task_execution.response.ctp_build_id, '')
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700418 self.assertEqual(task_execution.error.error_message,
419 self.fake_client.error)
Xinan Lindf0698a2020-02-05 22:38:11 -0800420
Xinan Lin083ba8f2020-02-06 13:55:18 -0800421 def testIgnoreTaskWithoutTaskID(self):
422 suite = _get_suite_params(board='foo')
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700423 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin083ba8f2020-02-06 13:55:18 -0800424 self.fake_client.error = "cros_test_platform error"
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700425 tasks = self.queue.lease_tasks_by_tag(
426 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin083ba8f2020-02-06 13:55:18 -0800427 self.client.multirequest_run(tasks, 'fake_suite')
428 self._assert_bb_client_called()
429 self.assertEqual(len(self.mock_bq_client.rows), 0)
430
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700431 def testIgnoreSuiteForUnmanagedPoolInStaging(self):
Xinan Linc54a7462020-04-17 15:39:01 -0700432 self.mock_application_id.return_value = 'suite-scheduler-staging'
433 suite = _get_suite_params(pool='foo')
434 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
435 self.fake_client.error = "cros_test_platform error"
436 tasks = self.queue.lease_tasks_by_tag(
437 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
438 self.client.multirequest_run(tasks, 'fake_suite')
439 self._assert_bb_client_not_called()
440
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700441 def testSetSyncOffloads(self):
442 self.mock_application_id.return_value = 'suite-scheduler-staging'
443 suite = _get_suite_params(pool='foo')
444 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
445 tasks = self.queue.lease_tasks_by_tag(
446 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
447 executed_tasks = self.client.multirequest_run(tasks, 'fake_suite')
448 switch_settings = [
449 t.params.migrations.enable_synchronous_offload for t in executed_tasks
450 ]
451 self.assertTrue(all(switch_settings))
Xinan Lindf0698a2020-02-05 22:38:11 -0800452
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700453def _struct_pb2_to_ctp_request(struct_pb2):
Xinan Lin3ba18a02019-08-13 15:44:55 -0700454 """Transform google struct proto to test_platform_request.
455
456 Args:
457 struct_pb2: A struct_pb2 instance.
458
459 Returns:
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700460 A ctp_request instance.
Xinan Lin3ba18a02019-08-13 15:44:55 -0700461 """
462 json = json_format.MessageToJson(struct_pb2)
Jacob Kopczynski4889b612020-07-30 14:50:58 -0700463 return json_format.Parse(json, ctp_request.Request())