| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import datetime | 5 import datetime |
| 6 import httplib | 6 import httplib |
| 7 import json | 7 import json |
| 8 import mock | 8 import mock |
| 9 | 9 |
| 10 from components import auth | 10 from components import auth |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 self.assertEqual( | 71 self.assertEqual( |
| 72 resp['build']['parameters_json'], '{"buildername": "linux_rel"}') | 72 resp['build']['parameters_json'], '{"buildername": "linux_rel"}') |
| 73 | 73 |
| 74 def test_get_nonexistent_build(self): | 74 def test_get_nonexistent_build(self): |
| 75 self.service.get.return_value = None | 75 self.service.get.return_value = None |
| 76 self.expect_error('get', {'id': 1}, 'BUILD_NOT_FOUND') | 76 self.expect_error('get', {'id': 1}, 'BUILD_NOT_FOUND') |
| 77 | 77 |
| 78 ##################################### PUT #################################### | 78 ##################################### PUT #################################### |
| 79 | 79 |
| 80 def test_put(self): | 80 def test_put(self): |
| 81 self.test_build.tags = ['owner=ivan'] | 81 self.test_build.tags = ['owner:ivan'] |
| 82 self.service.add.return_value = self.test_build | 82 self.service.add.return_value = self.test_build |
| 83 req = { | 83 req = { |
| 84 'bucket': self.test_build.bucket, | 84 'bucket': self.test_build.bucket, |
| 85 'tags': self.test_build.tags, | 85 'tags': self.test_build.tags, |
| 86 } | 86 } |
| 87 resp = self.call_api('put', req).json_body | 87 resp = self.call_api('put', req).json_body |
| 88 self.service.add.assert_called_once_with( | 88 self.service.add.assert_called_once_with( |
| 89 bucket=self.test_build.bucket, | 89 bucket=self.test_build.bucket, |
| 90 tags=req['tags'], | 90 tags=req['tags'], |
| 91 parameters=None, | 91 parameters=None, |
| 92 lease_expiration_date=None, | 92 lease_expiration_date=None, |
| 93 client_operation_id=None, |
| 93 ) | 94 ) |
| 94 self.assertEqual(resp['build']['id'], str(self.test_build.key.id())) | 95 self.assertEqual(resp['build']['id'], str(self.test_build.key.id())) |
| 95 self.assertEqual(resp['build']['bucket'], req['bucket']) | 96 self.assertEqual(resp['build']['bucket'], req['bucket']) |
| 96 self.assertEqual(resp['build']['tags'], req['tags']) | 97 self.assertEqual(resp['build']['tags'], req['tags']) |
| 97 | 98 |
| 98 def test_put_with_parameters(self): | 99 def test_put_with_parameters(self): |
| 99 self.service.add.return_value = self.test_build | 100 self.service.add.return_value = self.test_build |
| 100 req = { | 101 req = { |
| 101 'bucket': self.test_build.bucket, | 102 'bucket': self.test_build.bucket, |
| 102 'parameters_json': json.dumps(self.test_build.parameters), | 103 'parameters_json': json.dumps(self.test_build.parameters), |
| 103 } | 104 } |
| 104 resp = self.call_api('put', req).json_body | 105 resp = self.call_api('put', req).json_body |
| 105 self.assertEqual(resp['build']['parameters_json'], req['parameters_json']) | 106 self.assertEqual(resp['build']['parameters_json'], req['parameters_json']) |
| 106 | 107 |
| 107 def test_put_with_leasing(self): | 108 def test_put_with_leasing(self): |
| 108 self.test_build.lease_expiration_date = self.future_date | 109 self.test_build.lease_expiration_date = self.future_date |
| 109 self.service.add.return_value = self.test_build | 110 self.service.add.return_value = self.test_build |
| 110 req = { | 111 req = { |
| 111 'bucket': self.test_build.bucket, | 112 'bucket': self.test_build.bucket, |
| 112 'lease_expiration_ts': self.future_ts, | 113 'lease_expiration_ts': self.future_ts, |
| 113 } | 114 } |
| 114 resp = self.call_api('put', req).json_body | 115 resp = self.call_api('put', req).json_body |
| 115 self.service.add.assert_called_once_with( | 116 self.service.add.assert_called_once_with( |
| 116 bucket=self.test_build.bucket, | 117 bucket=self.test_build.bucket, |
| 117 tags=[], | 118 tags=[], |
| 118 parameters=None, | 119 parameters=None, |
| 119 lease_expiration_date=self.future_date, | 120 lease_expiration_date=self.future_date, |
| 121 client_operation_id=None, |
| 120 ) | 122 ) |
| 121 self.assertEqual( | 123 self.assertEqual( |
| 122 resp['build']['lease_expiration_ts'], req['lease_expiration_ts']) | 124 resp['build']['lease_expiration_ts'], req['lease_expiration_ts']) |
| 123 | 125 |
| 124 def test_put_with_empty_bucket(self): | |
| 125 self.expect_error('put', {'bucket': ''}, 'INVALID_INPUT') | |
| 126 | |
| 127 def test_put_with_malformed_parameters_json(self): | 126 def test_put_with_malformed_parameters_json(self): |
| 128 req = { | 127 req = { |
| 129 'bucket':'chromium', | 128 'bucket':'chromium', |
| 130 'parameters_json': '}non-json', | 129 'parameters_json': '}non-json', |
| 131 } | 130 } |
| 132 self.expect_error('put', req, 'INVALID_INPUT') | 131 self.expect_error('put', req, 'INVALID_INPUT') |
| 133 | 132 |
| 133 ################################## PUT_BATCH ################################# |
| 134 |
| 135 def test_put_batch(self): |
| 136 self.test_build.tags = ['owner:ivan'] |
| 137 build1_future = ndb.Future() |
| 138 build1_future.set_result(self.test_build) |
| 139 |
| 140 build2 = model.Build(id=2, bucket='v8') |
| 141 build2_future = ndb.Future() |
| 142 build2_future.set_result(build2) |
| 143 |
| 144 bad_build_future = ndb.Future() |
| 145 bad_build_future.set_exception(errors.InvalidInputError('Just bad')) |
| 146 |
| 147 self.service.add_async.side_effect = [ |
| 148 build1_future, build2_future, bad_build_future] |
| 149 req = { |
| 150 'builds': [ |
| 151 { |
| 152 'bucket': self.test_build.bucket, |
| 153 'tags': self.test_build.tags, |
| 154 'client_operation_id': '0', |
| 155 }, |
| 156 { |
| 157 'bucket': build2.bucket, |
| 158 'client_operation_id': '1', |
| 159 }, |
| 160 { |
| 161 'bucket': 'bad name', |
| 162 'client_operation_id': '2', |
| 163 }, |
| 164 ], |
| 165 } |
| 166 resp = self.call_api('put_batch', req).json_body |
| 167 self.service.add_async.assert_any_call( |
| 168 bucket=self.test_build.bucket, |
| 169 tags=self.test_build.tags, |
| 170 parameters=None, |
| 171 lease_expiration_date=None, |
| 172 client_operation_id='0', |
| 173 ) |
| 174 self.service.add_async.assert_any_call( |
| 175 bucket=build2.bucket, |
| 176 tags=[], |
| 177 parameters=None, |
| 178 lease_expiration_date=None, |
| 179 client_operation_id='1', |
| 180 ) |
| 181 |
| 182 res0 = resp['results'][0] |
| 183 self.assertEqual(res0['client_operation_id'], '0') |
| 184 self.assertEqual(res0['build']['id'], str(self.test_build.key.id())) |
| 185 self.assertEqual(res0['build']['bucket'], self.test_build.bucket) |
| 186 self.assertEqual(res0['build']['tags'], self.test_build.tags) |
| 187 |
| 188 res1 = resp['results'][1] |
| 189 self.assertEqual(res1['client_operation_id'], '1') |
| 190 self.assertEqual(res1['build']['id'], str(build2.key.id())) |
| 191 self.assertEqual(res1['build']['bucket'], build2.bucket) |
| 192 |
| 193 res2 = resp['results'][2] |
| 194 self.assertEqual(res2, { |
| 195 'client_operation_id': '2', |
| 196 'error': {'reason': 'INVALID_INPUT', 'message': 'Just bad'}, |
| 197 }) |
| 198 |
| 134 #################################### SEARCH ################################## | 199 #################################### SEARCH ################################## |
| 135 | 200 |
| 136 def test_search(self): | 201 def test_search(self): |
| 137 self.test_build.put() | 202 self.test_build.put() |
| 138 self.service.search.return_value = ([self.test_build], 'the cursor') | 203 self.service.search.return_value = ([self.test_build], 'the cursor') |
| 139 req = { | 204 req = { |
| 140 'bucket': ['chromium'], | 205 'bucket': ['chromium'], |
| 141 'cancelation_reason': 'CANCELED_EXPLICITLY', | 206 'cancelation_reason': 'CANCELED_EXPLICITLY', |
| 142 'created_by': 'user:x@chromium.org', | 207 'created_by': 'user:x@chromium.org', |
| 143 'result': 'CANCELED', | 208 'result': 'CANCELED', |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 'lease_key': 42, | 305 'lease_key': 42, |
| 241 'url': self.test_build.url, | 306 'url': self.test_build.url, |
| 242 } | 307 } |
| 243 res = self.call_api('start', req).json_body | 308 res = self.call_api('start', req).json_body |
| 244 self.service.start.assert_called_once_with( | 309 self.service.start.assert_called_once_with( |
| 245 req['id'], req['lease_key'], url=req['url']) | 310 req['id'], req['lease_key'], url=req['url']) |
| 246 self.assertEqual(int(res['build']['id']), req['id']) | 311 self.assertEqual(int(res['build']['id']), req['id']) |
| 247 self.assertEqual(res['build']['url'], req['url']) | 312 self.assertEqual(res['build']['url'], req['url']) |
| 248 | 313 |
| 249 def test_start_completed_build(self): | 314 def test_start_completed_build(self): |
| 250 def raise_completed(*_, **__): | 315 self.service.start.side_effect = errors.BuildIsCompletedError |
| 251 raise errors.BuildIsCompletedError() | |
| 252 self.service.start.side_effect = raise_completed | |
| 253 req = { | 316 req = { |
| 254 'id': self.test_build.key.id(), | 317 'id': self.test_build.key.id(), |
| 255 'lease_key': 42, | 318 'lease_key': 42, |
| 256 } | 319 } |
| 257 res = self.call_api('start', req).json_body | 320 res = self.call_api('start', req).json_body |
| 258 self.assertEqual(res['error']['reason'], 'BUILD_IS_COMPLETED') | 321 self.assertEqual(res['error']['reason'], 'BUILD_IS_COMPLETED') |
| 259 | 322 |
| 260 #################################### HEATBEAT ################################ | 323 #################################### HEATBEAT ################################ |
| 261 | 324 |
| 262 def test_heartbeat(self): | 325 def test_heartbeat(self): |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 self.assertTrue('error' in res) | 534 self.assertTrue('error' in res) |
| 472 self.assertEqual(res['error']['reason'], 'INVALID_INPUT') | 535 self.assertEqual(res['error']['reason'], 'INVALID_INPUT') |
| 473 | 536 |
| 474 expect_invalid_input_error( | 537 expect_invalid_input_error( |
| 475 {'role': 'READER', 'group': 'good group'}, bucket='bad bucket') | 538 {'role': 'READER', 'group': 'good group'}, bucket='bad bucket') |
| 476 expect_invalid_input_error({'role': 'READER', 'group': 'bad/ group'}) | 539 expect_invalid_input_error({'role': 'READER', 'group': 'bad/ group'}) |
| 477 | 540 |
| 478 #################################### ERRORS ################################## | 541 #################################### ERRORS ################################## |
| 479 | 542 |
| 480 def error_test(self, error_class, reason): | 543 def error_test(self, error_class, reason): |
| 481 def raise_service_error(*_, **__): | 544 self.service.get.side_effect = error_class |
| 482 raise error_class() | |
| 483 self.service.get.side_effect = raise_service_error | |
| 484 self.expect_error('get', {'id': 123}, reason) | 545 self.expect_error('get', {'id': 123}, reason) |
| 485 | 546 |
| 486 def test_build_not_found_error(self): | 547 def test_build_not_found_error(self): |
| 487 self.error_test(errors.BuildNotFoundError, 'BUILD_NOT_FOUND') | 548 self.error_test(errors.BuildNotFoundError, 'BUILD_NOT_FOUND') |
| 488 | 549 |
| 489 def test_invalid_input_error(self): | 550 def test_invalid_input_error(self): |
| 490 self.error_test(errors.InvalidInputError, 'INVALID_INPUT') | 551 self.error_test(errors.InvalidInputError, 'INVALID_INPUT') |
| 491 | 552 |
| 492 def test_invalid_build_state_error(self): | 553 def test_invalid_build_state_error(self): |
| 493 self.error_test(errors.InvalidBuildStateError, 'INVALID_BUILD_STATE') | 554 self.error_test(errors.InvalidBuildStateError, 'INVALID_BUILD_STATE') |
| 494 | 555 |
| 495 def test_lease_expired_error(self): | 556 def test_lease_expired_error(self): |
| 496 self.error_test(errors.LeaseExpiredError, 'LEASE_EXPIRED') | 557 self.error_test(errors.LeaseExpiredError, 'LEASE_EXPIRED') |
| OLD | NEW |