blob: 8ccd6e01238710e198d84d42cfa82a894ed22aaa [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
Sean McAllisteraf32bfb2021-07-19 09:20:17 -060019from chromite.third_party.infra_libs.buildbucket.proto import build_pb2
Xinan Lin9e4917d2019-11-04 10:58:47 -080020from google.appengine.api import taskqueue
Xinan Lin3ba18a02019-08-13 15:44:55 -070021from google.appengine.ext import testbed
Sean McAllister66bf7e92021-07-16 18:46:04 +000022from google.protobuf import json_format
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',
Taylor Clarke12ec9a2021-02-18 22:22:19 +000033 cros_build='fake_cros_build',
34 analytics_name=None):
Xinan Lin3ba18a02019-08-13 15:44:55 -070035 return {
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070036 'suite': suite,
37 'board': board,
38 'model': model,
39 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
Xinan Lin3ba18a02019-08-13 15:44:55 -070040 build_lib.BuildVersionKey.FW_RW_VERSION: 'fake_firmware_rw_build',
41 build_lib.BuildVersionKey.FW_RO_VERSION: 'fake_firmware_ro_build',
42 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: 'fake_android_build',
43 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: 'fake_testbed_build',
Brigit Rossbachbb080912020-11-18 13:52:17 -070044 'firmware_ro_version': 'fake_firmware_ro_build',
Xinan Lin3ba18a02019-08-13 15:44:55 -070045 'num': 1,
Prathmesh Prabhu2382a182019-09-07 21:18:10 -070046 'pool': pool,
Xinan Lin3ba18a02019-08-13 15:44:55 -070047 'priority': 10,
Xinan Lin6e097382019-08-27 18:43:35 -070048 'timeout': 12,
49 'timeout_mins': 4320,
50 'max_runtime_mins': 4320,
Xinan Lin3ba18a02019-08-13 15:44:55 -070051 'no_wait_for_results': True,
52 'test_source_build': 'fake_test_source_build',
53 'job_retry': False,
54 'no_delay': False,
55 'force': False,
56 'run_prod_code': True,
57 'is_skylab': False,
Taylor Clarke12ec9a2021-02-18 22:22:19 +000058 'analytics_name': analytics_name,
Azizur Rahmanb720e512022-05-13 18:30:40 +000059 'secondary_targets': '',
Azizur Rahmana9a189f2022-07-29 20:28:28 +000060 'run_via_cft': True,
61 'include_tags': 'a, b, c',
62 'exclude_tags': 'e, f, g',
Xinan Lin3ba18a02019-08-13 15:44:55 -070063 }
64
65
66class FakeTestPlatformClient(object):
Xinan Lin3ba18a02019-08-13 15:44:55 -070067 def __init__(self, test):
68 self._test = test
69 self.called_with_requests = []
Xinan Lindf0698a2020-02-05 22:38:11 -080070 self.error = None
Xinan Lin3ba18a02019-08-13 15:44:55 -070071
Xinan Lin57e2d962020-03-30 17:24:53 -070072 def ScheduleBuild(self, req, credentials=None, timeout=10):
Xinan Lin3ba18a02019-08-13 15:44:55 -070073 self.called_with_requests.append(req)
Xinan Lindf0698a2020-02-05 22:38:11 -080074 if self.error:
75 return self.error
76 return build_pb2.Build(id=FAKE_BUILD_ID)
77
78
79class FakeBigqueryRestClient(object):
Xinan Lindf0698a2020-02-05 22:38:11 -080080 def __init__(self, rest_client, project=None, dataset=None, table=None):
81 """Initialize the mock class."""
82 self.table = table
83 self.rows = []
84
85 def insert(self, rows):
86 self.rows = rows
87 return True
Xinan Lin3ba18a02019-08-13 15:44:55 -070088
89
90class TestPlatformClientTestCase(unittest.TestCase):
Xinan Lin3ba18a02019-08-13 15:44:55 -070091 def setUp(self):
92 super(TestPlatformClientTestCase, self).setUp()
93 self.fake_client = FakeTestPlatformClient(self)
94 patcher = mock.patch('buildbucket._get_client',
95 return_value=self._get_client(ADDR))
96 patcher.start()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -070097 self.client = buildbucket.TestPlatformClient(ADDR, 'foo-proj',
98 'foo-bucket', 'foo-builder')
Xinan Lin3ba18a02019-08-13 15:44:55 -070099 self.addCleanup(patcher.stop)
100 self.testbed = testbed.Testbed()
101 self.testbed.activate()
102 self.addCleanup(self.testbed.deactivate)
103 self.testbed.init_taskqueue_stub(
104 root_path=os.path.join(os.path.dirname(__file__)))
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700105 self.taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800106 self.queue = taskqueue.Queue(task_executor.SUITES_QUEUE)
Xinan Linc54a7462020-04-17 15:39:01 -0700107 _mock_application_id = mock.patch('constants.application_id')
108 self.mock_application_id = _mock_application_id.start()
109 self.addCleanup(_mock_application_id.stop)
110 self.mock_application_id.return_value = constants.AppID.PROD_APP
Xinan Lin3ba18a02019-08-13 15:44:55 -0700111
Xinan Lin9e4917d2019-11-04 10:58:47 -0800112 def testFormTestPlatformMultiRequestSuccessfully(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700113 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'goo']]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800114 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700115 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700116
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700117 tasks = self.queue.lease_tasks_by_tag(
118 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800119
120 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700121 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800122
123 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700124 request_list = [
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700125 _struct_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700126 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800127 request_list.sort(
128 key=lambda req: req.params.software_attributes.build_target.name)
129 for i, req in enumerate(request_list):
130 self.assertEqual(req.params.scheduling.priority, 10)
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700131 self.assertEqual(
132 req.params.scheduling.managed_pool,
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700133 ctp_request.Request.Params.Scheduling.MANAGED_POOL_QUOTA)
Prathmesh Prabhu9adfa632020-02-21 10:39:24 -0800134 # Don't check for exact max timeout to stay DRY.
135 # But do check that the maximum is sane.
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700136 self.assertLess(req.params.time.maximum_duration.seconds,
137 2 * 24 * 60 * 60)
Aviv Keshetc679faf2019-11-27 17:52:50 -0800138 gs_url = ('gs://chromeos-image-archive/%s' %
139 suite_kwargs[i]['test_source_build'])
140 self.assertEqual(req.params.metadata.test_metadata_url, gs_url)
141 self.assertEqual(req.params.metadata.debug_symbols_archive_url, gs_url)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800142 self.assertEqual(req.test_plan.suite[0].name, suite_kwargs[i]['suite'])
143 self.assertEqual(req.params.software_attributes.build_target.name,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700144 suite_kwargs[i]['board'])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800145
146 def testPoolName(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700147 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'goo', 'hoo']]
Xinan Lin1516edb2020-07-05 23:13:54 -0700148 suite_kwargs[0]['pool'] = 'MANAGED_POOL_CTS'
Xinan Lin9e4917d2019-11-04 10:58:47 -0800149 suite_kwargs[1]['pool'] = 'wifi'
Xinan Lin9e4917d2019-11-04 10:58:47 -0800150 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700151 task_executor.push(task_executor.SUITES_QUEUE, tag='some_suite', **suite)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800152
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700153 tasks = self.queue.lease_tasks_by_tag(
154 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800155 self.client.multirequest_run(tasks, 'some_suite')
156 self._assert_bb_client_called()
157 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700158 request_list = [
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700159 _struct_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700160 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800161 self.assertEqual(len(request_list), 3)
162 request_list.sort(
163 key=lambda req: req.params.software_attributes.build_target.name)
164 self.assertEqual(request_list[0].params.scheduling.managed_pool,
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700165 ctp_request.Request.Params.Scheduling.MANAGED_POOL_CTS)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800166 self.assertEqual(request_list[1].params.scheduling.unmanaged_pool,
167 suite_kwargs[1]['pool'])
Prathmesh Prabhu88409f62019-08-30 14:32:28 -0700168
Xinan Lin3ba18a02019-08-13 15:44:55 -0700169 def testNoFinalBuild(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800170 suite_kwargs = _get_suite_params()
171 suite_kwargs[build_lib.BuildVersionKey.CROS_VERSION] = None
172 suite_kwargs[build_lib.BuildVersionKey.ANDROID_BUILD_VERSION] = None
173 suite_kwargs[build_lib.BuildVersionKey.TESTBED_BUILD_VERSION] = None
174
175 task_executor.push(task_executor.SUITES_QUEUE,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700176 tag='fake_suite',
177 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800178
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700179 tasks = self.queue.lease_tasks_by_tag(
180 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800181 executed = self.client.multirequest_run(tasks, 'fake_suite')
182 self.assertEqual(len(executed), 0)
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700183 self._assert_bb_client_not_called()
Xinan Lin3ba18a02019-08-13 15:44:55 -0700184
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700185 def testShouldSetQsAccountForUnmanagedPool(self):
Xinan Lin4757d6f2020-03-24 22:20:31 -0700186 suite_kwargs = _get_suite_params(pool='foo')
187 suite_kwargs['priority'] = '30'
188 suite_kwargs['qs_account'] = 'qs-foo'
189
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700190 task_executor.push(task_executor.SUITES_QUEUE,
191 tag='fake_suite',
192 **suite_kwargs)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700193
194 tasks = self.queue.lease_tasks_by_tag(
195 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
196 self.client.multirequest_run(tasks, 'fake_suite')
Xinan Lin4757d6f2020-03-24 22:20:31 -0700197 self._assert_bb_client_called()
Jacob Kopczynskif464c8f2020-08-20 17:54:35 +0000198 request_map = self._extract_request_map_from_bb_client()
Xinan Lin4757d6f2020-03-24 22:20:31 -0700199 self.assertEqual(len(request_map), 1)
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700200 req = _struct_to_ctp_request(request_map['fake_board_fake_model'])
Xinan Lin4757d6f2020-03-24 22:20:31 -0700201 self.assertEqual(req.params.scheduling.qs_account, 'qs-foo')
202 # If qs_account is set, priority should be 0, the default value
203 # defined by proto3.
204 self.assertEqual(req.params.scheduling.priority, 0)
205
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700206 def testShouldSetQsAccountForManagedPool(self):
Xinan Lin1516edb2020-07-05 23:13:54 -0700207 suite_kwargs = _get_suite_params(pool='MANAGED_POOL_QUOTA')
Xinan Lin4757d6f2020-03-24 22:20:31 -0700208 suite_kwargs['qs_account'] = 'qs-foo'
209
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700210 task_executor.push(task_executor.SUITES_QUEUE,
211 tag='fake_suite',
212 **suite_kwargs)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700213
214 tasks = self.queue.lease_tasks_by_tag(
215 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
216 self.client.multirequest_run(tasks, 'fake_suite')
Xinan Lin4757d6f2020-03-24 22:20:31 -0700217 self._assert_bb_client_called()
Jacob Kopczynskif464c8f2020-08-20 17:54:35 +0000218 request_map = self._extract_request_map_from_bb_client()
Xinan Lin4757d6f2020-03-24 22:20:31 -0700219 self.assertEqual(len(request_map), 1)
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700220 req = _struct_to_ctp_request(request_map['fake_board_fake_model'])
Prathmesh Prabhu46156ff2020-06-20 00:18:52 -0700221 self.assertEqual(req.params.scheduling.qs_account, 'qs-foo')
222 # If qs_account is set, priority should be 0, the default value
223 # defined by proto3.
224 self.assertEqual(req.params.scheduling.priority, 0)
Xinan Lin4757d6f2020-03-24 22:20:31 -0700225
Xinan Lin9e4917d2019-11-04 10:58:47 -0800226 def testShouldSetPriority(self):
227 suite_kwargs = _get_suite_params()
228 suite_kwargs['priority'] = '30'
Xinan Linfb63d572019-09-24 15:49:04 -0700229
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700230 task_executor.push(task_executor.SUITES_QUEUE,
231 tag='fake_suite',
232 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800233
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700234 tasks = self.queue.lease_tasks_by_tag(
235 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800236 self.client.multirequest_run(tasks, 'fake_suite')
237 request_map = self._extract_request_map_from_bb_client()
Xinan Linfb63d572019-09-24 15:49:04 -0700238 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800239 self.assertEqual(len(request_map), 1)
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700240 req = _struct_to_ctp_request(request_map['fake_board_fake_model'])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800241 self.assertEqual(req.params.scheduling.priority, 30)
242
243 def testRequestWithInvalidTags(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700244 suite_kwargs = [_get_suite_params(board=b) for b in ['foo', 'foo']]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800245
246 # test request having None String Tag
247 suite_kwargs[0]['model'] = 'None'
248
249 # test request having None Tag
250 suite_kwargs[1]['model'] = None
251
252 for suite in suite_kwargs:
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700253 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800254
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700255 tasks = self.queue.lease_tasks_by_tag(
256 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800257 executed = self.client.multirequest_run(tasks, 'fake_suite')
Jacob Kopczynskif464c8f2020-08-20 17:54:35 +0000258 self._assert_bb_client_called()
Xinan Lin9e4917d2019-11-04 10:58:47 -0800259 self.assertEqual(len(executed), 2)
260
Xinan Lin9e4917d2019-11-04 10:58:47 -0800261 request_map = self._extract_request_map_from_bb_client()
262 self.assertEqual(len(request_map), 2)
Xinan Linfb63d572019-09-24 15:49:04 -0700263 want = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700264 'suite:fake_suite',
265 'build:fake_cros_build',
Xinan Lin1516edb2020-07-05 23:13:54 -0700266 'label-pool:MANAGED_POOL_QUOTA',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700267 'label-board:foo',
Taylor Clarke12ec9a2021-02-18 22:22:19 +0000268 'ctp-fwd-task-name:None',
Xinan Linfb63d572019-09-24 15:49:04 -0700269 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800270 want_bb = {
Jared Loucks438bf3a2022-04-06 13:43:15 -0600271 'label-image:fake_cros_build',
272 'label-suite:fake_suite',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700273 'suite:fake_suite',
Dhanya Ganeshedb78cb2020-07-20 19:40:50 +0000274 'user_agent:suite_scheduler',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800275 }
276 for req_name in ['foo', 'foo_1']:
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700277 req = _struct_to_ctp_request(request_map[req_name])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800278 req_tags = set([t for t in req.params.decorations.tags])
279 self.assertEqual(want, req_tags)
280 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
281 self.assertEqual(want_bb, bb_tags)
Xinan Linfb63d572019-09-24 15:49:04 -0700282
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700283 def testRequestTags(self):
Xinan Lin9e4917d2019-11-04 10:58:47 -0800284 suite_kwargs = _get_suite_params(
285 board='fake_board',
286 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700287 pool='DUT_POOL_QUOTA',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800288 suite='fake_suite',
289 cros_build='fake_build',
Taylor Clarke12ec9a2021-02-18 22:22:19 +0000290 analytics_name='fake_analytics_name',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700291 )
Xinan Lin9e4917d2019-11-04 10:58:47 -0800292 task_executor.push(task_executor.SUITES_QUEUE,
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700293 tag='fake_suite',
294 **suite_kwargs)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800295
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700296 tasks = self.queue.lease_tasks_by_tag(
297 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin9e4917d2019-11-04 10:58:47 -0800298 self.client.multirequest_run(tasks, 'fake_suite')
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700299 self._assert_bb_client_called()
300 want = {
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700301 'label-board:fake_board',
302 'label-model:fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700303 'label-pool:DUT_POOL_QUOTA',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700304 'suite:fake_suite',
305 'build:fake_build',
Taylor Clarke12ec9a2021-02-18 22:22:19 +0000306 'analytics_name:fake_analytics_name',
307 'ctp-fwd-task-name:None',
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700308 }
Xinan Lin9e4917d2019-11-04 10:58:47 -0800309 want_bb = {
Jared Loucks438bf3a2022-04-06 13:43:15 -0600310 'label-suite:fake_suite',
311 'label-image:fake_build',
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700312 'suite:fake_suite',
Dhanya Ganeshedb78cb2020-07-20 19:40:50 +0000313 'user_agent:suite_scheduler',
Xinan Lin9e4917d2019-11-04 10:58:47 -0800314 }
315 request_map = self._extract_request_map_from_bb_client()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700316 request_list = [
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700317 _struct_to_ctp_request(v) for v in request_map.values()
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700318 ]
Xinan Lin9e4917d2019-11-04 10:58:47 -0800319 self.assertEqual(len(request_list), 1)
320 req = request_list[0]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700321 req_tags = set([t for t in req.params.decorations.tags])
322 self.assertEqual(want, req_tags)
323 bb_tags = set([t for t in self._extract_tags_from_bb_client()])
Xinan Lin9e4917d2019-11-04 10:58:47 -0800324 self.assertEqual(want_bb, bb_tags)
Xinan Lin3ba18a02019-08-13 15:44:55 -0700325
Xinan Linba3b9322020-04-24 15:08:12 -0700326 def testRequestUserDefinedDimensions(self):
327 suite_kwargs = _get_suite_params(
328 board='fake_board',
329 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700330 pool='MANAGED_POOL_QUOTA',
Xinan Linba3b9322020-04-24 15:08:12 -0700331 suite='fake_suite',
332 cros_build='fake_build',
333 )
Patrick Meiringd4f60772021-03-04 12:09:28 +1100334 suite_kwargs['dimensions'] = 'label-wifi:foo, label-bt:hoo'
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700335 task_executor.push(task_executor.SUITES_QUEUE,
336 tag='fake_suite',
337 **suite_kwargs)
Xinan Linba3b9322020-04-24 15:08:12 -0700338
339 tasks = self.queue.lease_tasks_by_tag(
340 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
341 self.client.multirequest_run(tasks, 'fake_suite')
342 self._assert_bb_client_called()
343 request_map = self._extract_request_map_from_bb_client()
344 request_list = [
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700345 _struct_to_ctp_request(v) for v in request_map.values()
Xinan Linba3b9322020-04-24 15:08:12 -0700346 ]
347 self.assertEqual(len(request_list), 1)
348 req = request_list[0]
349 free_dimensions = req.params.freeform_attributes.swarming_dimensions
350 self.assertTrue(len(free_dimensions), 2)
351 self.assertTrue('label-wifi:foo' in free_dimensions)
352 self.assertTrue('label-bt:hoo' in free_dimensions)
353
354 def testRequestInvalidUserDefinedDimensions(self):
355 suite_kwargs = _get_suite_params(
356 board='fake_board',
357 model='fake_model',
Xinan Lin1516edb2020-07-05 23:13:54 -0700358 pool='MANAGED_POOL_QUOTA',
Xinan Linba3b9322020-04-24 15:08:12 -0700359 suite='fake_suite',
360 cros_build='fake_build',
361 )
362 suite_kwargs['dimensions'] = 'invalid-dimension'
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700363 task_executor.push(task_executor.SUITES_QUEUE,
364 tag='fake_suite',
365 **suite_kwargs)
Xinan Linba3b9322020-04-24 15:08:12 -0700366
367 tasks = self.queue.lease_tasks_by_tag(
368 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
369 self.client.multirequest_run(tasks, 'fake_suite')
370 self._assert_bb_client_not_called()
371
Prathmesh Prabhu73801e12019-08-30 14:09:31 -0700372 def _get_client(self, addr):
373 self.assertEqual(ADDR, addr)
374 return self.fake_client
375
Jacob Kopczynskif464c8f2020-08-20 17:54:35 +0000376 def _assert_bb_client_called(self, times=1):
377 actual = len(self.fake_client.called_with_requests)
378 self.assertEqual(actual, times,
379 "BB client called %s times, expected %s" % (actual, times))
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700380
381 def _assert_bb_client_not_called(self):
Jacob Kopczynskif464c8f2020-08-20 17:54:35 +0000382 actual = len(self.fake_client.called_with_requests)
383 self.assertEqual(actual, 0,
384 "BB client called %s times, expected 0"% actual)
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700385
Xinan Lin9e4917d2019-11-04 10:58:47 -0800386 def _extract_request_map_from_bb_client(self):
387 return self.fake_client.called_with_requests[0].properties['requests']
Prathmesh Prabhu6348ea82019-08-30 14:15:21 -0700388
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700389 def _extract_tags_from_bb_client(self):
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700390 return [
391 '%s:%s' % (t.key, t.value)
392 for t in self.fake_client.called_with_requests[0].tags
393 ]
Prathmesh Prabhu2382a182019-09-07 21:18:10 -0700394
Prathmesh Prabhu9a8060a2019-08-30 14:13:23 -0700395
Xinan Lindf0698a2020-02-05 22:38:11 -0800396class TestTaskExecutions(TestPlatformClientTestCase):
Xinan Lindf0698a2020-02-05 22:38:11 -0800397 def setUp(self):
398 super(TestTaskExecutions, self).setUp()
399 _mock_bq_client = mock.patch('rest_client.BigqueryRestClient')
400 mock_bq_client = _mock_bq_client.start()
401 self.addCleanup(_mock_bq_client.stop)
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700402 self.mock_bq_client = FakeBigqueryRestClient(None,
403 project='proj',
404 dataset='dataset',
405 table='foo')
Xinan Lindf0698a2020-02-05 22:38:11 -0800406 mock_bq_client.return_value = self.mock_bq_client
407
408 def testRecordSuccessfulTaskExecution(self):
Xinan Lin9b17c5b2020-08-06 10:43:30 -0700409 suite = _get_suite_params(board='fake_build', model='fake_model')
Xinan Lin083ba8f2020-02-06 13:55:18 -0800410 suite['task_id'] = FAKE_UUID
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700411 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
412 tasks = self.queue.lease_tasks_by_tag(
413 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lindf0698a2020-02-05 22:38:11 -0800414 self.client.multirequest_run(tasks, 'fake_suite')
415 self._assert_bb_client_called()
416 task_execution = json_format.Parse(
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700417 json.dumps(self.mock_bq_client.rows[0]['json']),
418 analytics_pb2.ExecutionTask())
Xinan Lindf0698a2020-02-05 22:38:11 -0800419 self.assertEqual(task_execution.queued_task_id, FAKE_UUID)
Xinan Lin9b17c5b2020-08-06 10:43:30 -0700420 self.assertEqual(task_execution.request_tag, 'fake_build_fake_model')
Xinan Lindf0698a2020-02-05 22:38:11 -0800421 self.assertEqual(task_execution.response.ctp_build_id, str(FAKE_BUILD_ID))
422 self.assertEqual(task_execution.error.error_message, '')
423
424 def testRecordFailedTaskExecution(self):
Xinan Lin9b17c5b2020-08-06 10:43:30 -0700425 suite = _get_suite_params(board='fake_build', model='fake_model')
Xinan Lin083ba8f2020-02-06 13:55:18 -0800426 suite['task_id'] = FAKE_UUID
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700427 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lindf0698a2020-02-05 22:38:11 -0800428 self.fake_client.error = "cros_test_platform error"
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700429 tasks = self.queue.lease_tasks_by_tag(
430 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lindf0698a2020-02-05 22:38:11 -0800431 self.client.multirequest_run(tasks, 'fake_suite')
432 self._assert_bb_client_called()
433 task_execution = json_format.Parse(
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700434 json.dumps(self.mock_bq_client.rows[0]['json']),
435 analytics_pb2.ExecutionTask())
Xinan Lindf0698a2020-02-05 22:38:11 -0800436 self.assertEqual(task_execution.queued_task_id, FAKE_UUID)
Xinan Lin9b17c5b2020-08-06 10:43:30 -0700437 self.assertEqual(task_execution.request_tag, 'fake_build_fake_model')
Xinan Lindf0698a2020-02-05 22:38:11 -0800438 self.assertEqual(task_execution.response.ctp_build_id, '')
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700439 self.assertEqual(task_execution.error.error_message,
440 self.fake_client.error)
Xinan Lindf0698a2020-02-05 22:38:11 -0800441
Xinan Lin083ba8f2020-02-06 13:55:18 -0800442 def testIgnoreTaskWithoutTaskID(self):
443 suite = _get_suite_params(board='foo')
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700444 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
Xinan Lin083ba8f2020-02-06 13:55:18 -0800445 self.fake_client.error = "cros_test_platform error"
Prathmesh Prabhuaf0857f2020-06-20 00:16:32 -0700446 tasks = self.queue.lease_tasks_by_tag(
447 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
Xinan Lin083ba8f2020-02-06 13:55:18 -0800448 self.client.multirequest_run(tasks, 'fake_suite')
449 self._assert_bb_client_called()
450 self.assertEqual(len(self.mock_bq_client.rows), 0)
451
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700452 def testIgnoreSuiteForUnmanagedPoolInStaging(self):
Xinan Linc54a7462020-04-17 15:39:01 -0700453 self.mock_application_id.return_value = 'suite-scheduler-staging'
454 suite = _get_suite_params(pool='foo')
455 task_executor.push(task_executor.SUITES_QUEUE, tag='fake_suite', **suite)
456 self.fake_client.error = "cros_test_platform error"
457 tasks = self.queue.lease_tasks_by_tag(
458 3600, constants.Buildbucket.MULTIREQUEST_SIZE, deadline=60)
459 self.client.multirequest_run(tasks, 'fake_suite')
460 self._assert_bb_client_not_called()
461
Xinan Lindf0698a2020-02-05 22:38:11 -0800462
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700463def _struct_to_ctp_request(struct_pb2):
Xinan Lin3ba18a02019-08-13 15:44:55 -0700464 """Transform google struct proto to test_platform_request.
465
466 Args:
467 struct_pb2: A struct_pb2 instance.
468
469 Returns:
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700470 A ctp_request instance.
Xinan Lin3ba18a02019-08-13 15:44:55 -0700471 """
472 json = json_format.MessageToJson(struct_pb2)
Jacob Kopczynski408f3fd2020-08-07 13:31:59 -0700473 return json_format.Parse(json, ctp_request.Request())