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 |