Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: third_party/google-endpoints/test/test_check_request.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from __future__ import absolute_import
16
17 import datetime
18 import httplib
19 import unittest2
20 from expects import be_none, equal, expect, raise_error
21
22 from apitools.base.py import encoding
23
24 from google.api.control import caches, label_descriptor, timestamp
25 from google.api.control import check_request, messages, metric_value
26
27
28 class TestSign(unittest2.TestCase):
29
30 def setUp(self):
31 op = messages.Operation(
32 consumerId=_TEST_CONSUMER_ID,
33 operationName=_TEST_OP_NAME
34 )
35 self.test_check_request = messages.CheckRequest(operation=op)
36 self.test_op = op
37
38 def test_should_fail_if_operation_is_not_set(self):
39 testf = lambda: check_request.sign(messages.CheckRequest())
40 expect(testf).to(raise_error(ValueError))
41
42 def test_should_fail_on_invalid_input(self):
43 testf = lambda: check_request.sign(None)
44 expect(testf).to(raise_error(ValueError))
45 testf = lambda: check_request.sign(object())
46 expect(testf).to(raise_error(ValueError))
47
48 def test_should_fail_if_operation_has_no_operation_name(self):
49 op = messages.Operation(consumerId=_TEST_CONSUMER_ID)
50 testf = lambda: check_request.sign(messages.CheckRequest(operation=op))
51 expect(testf).to(raise_error(ValueError))
52
53 def test_should_fail_if_operation_has_no_consumer_id(self):
54 op = messages.Operation(operationName=_TEST_OP_NAME)
55 testf = lambda: check_request.sign(messages.CheckRequest(operation=op))
56 expect(testf).to(raise_error(ValueError))
57
58 def test_should_sign_a_valid_check_request(self):
59 check_request.sign(self.test_check_request)
60
61 def test_should_change_signature_when_labels_are_added(self):
62 without_labels = check_request.sign(self.test_check_request)
63 self.test_op.labels = encoding.PyValueToMessage(
64 messages.Operation.LabelsValue, {
65 'key1': 'value1',
66 'key2': 'value2'
67 })
68 with_labels = check_request.sign(self.test_check_request)
69 expect(with_labels).not_to(equal(without_labels))
70
71 def test_should_change_signature_when_metric_values_are_added(self):
72 without_mvs = check_request.sign(self.test_check_request)
73 self.test_op.metricValueSets = [
74 messages.MetricValueSet(
75 metricName='a_float',
76 metricValues=[
77 metric_value.create(
78 labels={
79 'key1': 'value1',
80 'key2': 'value2'
81 },
82 doubleValue=1.1,
83 ),
84 ]
85 )
86 ]
87 with_mvs = check_request.sign(self.test_check_request)
88 expect(with_mvs).not_to(equal(without_mvs))
89
90 def test_should_change_signature_quota_properties_are_specified(self):
91 without_qprops = check_request.sign(self.test_check_request)
92 self.test_op.quotaProperties = messages.QuotaProperties()
93 with_qprops = check_request.sign(self.test_check_request)
94 expect(with_qprops).not_to(equal(without_qprops))
95
96
97 class TestAggregatorCheck(unittest2.TestCase):
98 SERVICE_NAME = 'service.check'
99 FAKE_OPERATION_ID = 'service.general.check'
100
101 def setUp(self):
102 self.timer = _DateTimeTimer()
103 self.agg = check_request.Aggregator(
104 self.SERVICE_NAME, caches.CheckOptions())
105
106 def test_should_fail_if_req_is_bad(self):
107 testf = lambda: self.agg.check(object())
108 expect(testf).to(raise_error(ValueError))
109 testf = lambda: self.agg.check(None)
110 expect(testf).to(raise_error(ValueError))
111
112 def test_should_fail_if_service_name_does_not_match(self):
113 req = _make_test_request(self.SERVICE_NAME + '-will-not-match')
114 testf = lambda: self.agg.check(req)
115 expect(testf).to(raise_error(ValueError))
116
117 def test_should_fail_if_check_request_is_missing(self):
118 req = messages.ServicecontrolServicesCheckRequest(
119 serviceName=self.SERVICE_NAME)
120 testf = lambda: self.agg.check(req)
121 expect(testf).to(raise_error(ValueError))
122
123 def test_should_fail_if_operation_is_missing(self):
124 req = messages.ServicecontrolServicesCheckRequest(
125 serviceName=self.SERVICE_NAME,
126 checkRequest=messages.CheckRequest())
127 testf = lambda: self.agg.check(req)
128 expect(testf).to(raise_error(ValueError))
129
130 def test_should_return_none_initially_as_req_is_not_cached(self):
131 req = _make_test_request(self.SERVICE_NAME)
132 fake_response = messages.CheckResponse(
133 operationId=self.FAKE_OPERATION_ID)
134 agg = self.agg
135 expect(agg.check(req)).to(be_none)
136
137
138 class TestAggregatorThatCannotCache(unittest2.TestCase):
139 SERVICE_NAME = 'service.no_cache'
140 FAKE_OPERATION_ID = 'service.no_cache.op_id'
141
142 def setUp(self):
143 # -ve num_entries means no cache is present
144 self.agg = check_request.Aggregator(
145 self.SERVICE_NAME,
146 caches.CheckOptions(num_entries=-1))
147
148 def test_should_not_cache_responses(self):
149 req = _make_test_request(self.SERVICE_NAME)
150 fake_response = messages.CheckResponse(
151 operationId=self.FAKE_OPERATION_ID)
152 agg = self.agg
153 expect(agg.check(req)).to(be_none)
154 agg.add_response(req, fake_response)
155 expect(agg.check(req)).to(be_none)
156 agg.clear()
157 expect(agg.check(req)).to(be_none)
158
159 def test_should_have_empty_flush_response(self):
160 expect(len(self.agg.flush())).to(equal(0))
161
162 def test_should_have_none_as_flush_interval(self):
163 expect(self.agg.flush_interval).to(be_none)
164
165
166
167 class _DateTimeTimer(object):
168 def __init__(self, auto=False):
169 self.auto = auto
170 self.time = datetime.datetime.utcfromtimestamp(0)
171
172 def __call__(self):
173 if self.auto:
174 self.tick()
175 return self.time
176
177 def tick(self):
178 self.time += datetime.timedelta(seconds=1)
179
180
181 class TestCachingAggregator(unittest2.TestCase):
182 SERVICE_NAME = 'service.with_cache'
183 FAKE_OPERATION_ID = 'service.with_cache.op_id'
184
185 def setUp(self):
186 self.timer = _DateTimeTimer()
187 self.expiration = datetime.timedelta(seconds=2)
188 options = caches.CheckOptions(
189 flush_interval=datetime.timedelta(seconds=1),
190 expiration=self.expiration)
191 self.agg = check_request.Aggregator(
192 self.SERVICE_NAME, options, timer=self.timer)
193
194 def test_should_have_expiration_as_flush_interval(self):
195 expect(self.agg.flush_interval).to(equal(self.expiration))
196
197 def test_should_cache_responses(self):
198 req = _make_test_request(self.SERVICE_NAME)
199 fake_response = messages.CheckResponse(
200 operationId=self.FAKE_OPERATION_ID)
201 agg = self.agg
202 expect(agg.check(req)).to(be_none)
203 agg.add_response(req, fake_response)
204 expect(agg.check(req)).to(equal(fake_response))
205
206 def test_should_not_cache_requests_with_important_operations(self):
207 req = _make_test_request(
208 self.SERVICE_NAME,
209 importance=messages.Operation.ImportanceValueValuesEnum.HIGH)
210 fake_response = messages.CheckResponse(
211 operationId=self.FAKE_OPERATION_ID)
212 agg = self.agg
213 expect(agg.check(req)).to(be_none)
214 agg.add_response(req, fake_response)
215 expect(agg.check(req)).to(be_none)
216
217 def test_signals_a_resend_on_1st_call_after_flush_interval(self):
218 req = _make_test_request(self.SERVICE_NAME)
219 fake_response = messages.CheckResponse(
220 operationId=self.FAKE_OPERATION_ID)
221 agg = self.agg
222 expect(agg.check(req)).to(be_none)
223 agg.add_response(req, fake_response)
224 expect(agg.check(req)).to(equal(fake_response))
225
226 # Now flush interval is reached, but not the response expiry
227 self.timer.tick() # now past the flush_interval
228 expect(agg.check(req)).to(be_none) # none signals the resend
229
230 # Until expiry, the response will continue to be returned
231 expect(agg.check(req)).to(equal(fake_response))
232 expect(agg.check(req)).to(equal(fake_response))
233
234 # Once expired the cached response is no longer returned
235 # expire
236 self.timer.tick()
237 self.timer.tick() # now expired
238 expect(agg.check(req)).to(be_none)
239 expect(agg.check(req)).to(be_none) # 2nd check is None as well
240
241 def test_signals_resend_on_1st_call_after_flush_interval_with_errors(self):
242 req = _make_test_request(self.SERVICE_NAME)
243 failure_code = messages.CheckError.CodeValueValuesEnum.NOT_FOUND
244 fake_response = messages.CheckResponse(
245 operationId=self.FAKE_OPERATION_ID, checkErrors=[
246 messages.CheckError(code=failure_code)
247 ])
248 agg = self.agg
249 expect(agg.check(req)).to(be_none)
250 agg.add_response(req, fake_response)
251 expect(agg.check(req)).to(equal(fake_response))
252
253 # Now flush interval is reached, but not the response expiry
254 self.timer.tick() # now past the flush_interval
255 expect(agg.check(req)).to(be_none) # first response is null
256
257 # until expiry, the response will continue to be returned
258 expect(agg.check(req)).to(equal(fake_response))
259 expect(agg.check(req)).to(equal(fake_response))
260
261 # expire
262 self.timer.tick()
263 self.timer.tick() # now expired
264 expect(agg.check(req)).to(be_none)
265 expect(agg.check(req)).to(be_none) # 2nd check is None as well
266
267 def test_should_extend_expiration_on_receipt_of_a_response(self):
268 req = _make_test_request(self.SERVICE_NAME)
269 fake_response = messages.CheckResponse(
270 operationId=self.FAKE_OPERATION_ID
271 )
272 agg = self.agg
273 expect(agg.check(req)).to(be_none)
274 agg.add_response(req, fake_response)
275 expect(agg.check(req)).to(equal(fake_response))
276
277 # Now flush interval is reached, but not the response expiry
278 self.timer.tick() # now past the flush_interval
279 expect(agg.check(req)).to(be_none) # first response is null
280
281 # until expiry, the response will continue to be returned
282 expect(agg.check(req)).to(equal(fake_response))
283 expect(agg.check(req)).to(equal(fake_response))
284
285 # add a response as the request expires
286 self.timer.tick()
287 agg.add_response(req, fake_response)
288 # it would have expired, but because the response was added it does not
289 expect(agg.check(req)).to(equal(fake_response))
290 expect(agg.check(req)).to(equal(fake_response))
291 self.timer.tick() # now past the flush interval again
292 expect(agg.check(req)).to(be_none)
293 expect(agg.check(req)).to(equal(fake_response))
294
295 def test_does_not_flush_request_that_has_not_been_updated(self):
296 req = _make_test_request(self.SERVICE_NAME)
297 fake_response = messages.CheckResponse(
298 operationId=self.FAKE_OPERATION_ID
299 )
300 agg = self.agg
301 expect(agg.check(req)).to(be_none)
302 agg.add_response(req, fake_response)
303 self.timer.tick() # now past the flush_interval
304 expect(len(agg.flush())).to(equal(0)) # nothing expired
305 self.timer.tick() # now past expiry
306 self.timer.tick() # now past expiry
307 expect(agg.check(req)).to(be_none) # confirm nothing in cache
308 expect(agg.check(req)).to(be_none) # confirm nothing in cache
309 expect(len(agg.flush())).to(equal(0)) # no cached check request
310
311 def test_does_flush_requests_that_have_been_updated(self):
312 req = _make_test_request(self.SERVICE_NAME)
313 fake_response = messages.CheckResponse(
314 operationId=self.FAKE_OPERATION_ID
315 )
316 agg = self.agg
317 expect(agg.check(req)).to(be_none)
318 agg.add_response(req, fake_response)
319 expect(agg.check(req)).to(equal(fake_response))
320 self.timer.tick() # now past the flush_interval
321 expect(len(agg.flush())).to(equal(0)) # nothing expired
322 self.timer.tick() # now past expiry
323 self.timer.tick() # now past expiry
324 expect(len(agg.flush())).to(equal(1)) # got the cached check request
325
326 def test_should_clear_requests(self):
327 req = _make_test_request(self.SERVICE_NAME)
328 fake_response = messages.CheckResponse(
329 operationId=self.FAKE_OPERATION_ID
330 )
331 agg = self.agg
332 expect(agg.check(req)).to(be_none)
333 agg.add_response(req, fake_response)
334 expect(agg.check(req)).to(equal(fake_response))
335 agg.clear()
336 expect(agg.check(req)).to(be_none)
337 expect(len(agg.flush())).to(equal(0))
338
339
340 _TEST_CONSUMER_ID = 'testConsumerID'
341 _TEST_OP_NAME = 'testOperationName'
342
343
344 def _make_test_request(service_name, importance=None):
345 if importance is None:
346 importance = messages.Operation.ImportanceValueValuesEnum.LOW
347 op = messages.Operation(
348 consumerId=_TEST_CONSUMER_ID,
349 operationName=_TEST_OP_NAME,
350 importance=importance
351 )
352 check_request = messages.CheckRequest(operation=op)
353 return messages.ServicecontrolServicesCheckRequest(
354 serviceName=service_name,
355 checkRequest=check_request)
356
357
358 _WANTED_USER_AGENT = label_descriptor.USER_AGENT
359 _START_OF_EPOCH = timestamp.to_rfc3339(datetime.datetime(1970, 1, 1, 0, 0, 0))
360 _TEST_SERVICE_NAME = 'a_service_name'
361 _INFO_TESTS = [
362 (check_request.Info(
363 operation_id='an_op_id',
364 operation_name='an_op_name',
365 referer='a_referer',
366 service_name=_TEST_SERVICE_NAME),
367 messages.Operation(
368 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
369 labels = encoding.PyValueToMessage(
370 messages.Operation.LabelsValue, {
371 'servicecontrol.googleapis.com/user_agent': _WANTED_USER_AGENT,
372 'servicecontrol.googleapis.com/referer': 'a_referer'
373 }),
374 operationId='an_op_id',
375 operationName='an_op_name',
376 startTime=_START_OF_EPOCH,
377 endTime=_START_OF_EPOCH)),
378 (check_request.Info(
379 api_key='an_api_key',
380 api_key_valid=True,
381 operation_id='an_op_id',
382 operation_name='an_op_name',
383 referer='a_referer',
384 service_name=_TEST_SERVICE_NAME),
385 messages.Operation(
386 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
387 consumerId='api_key:an_api_key',
388 labels = encoding.PyValueToMessage(
389 messages.Operation.LabelsValue, {
390 'servicecontrol.googleapis.com/user_agent': _WANTED_USER_AGENT,
391 'servicecontrol.googleapis.com/referer': 'a_referer'
392 }),
393 operationId='an_op_id',
394 operationName='an_op_name',
395 startTime=_START_OF_EPOCH,
396 endTime=_START_OF_EPOCH)),
397 (check_request.Info(
398 api_key='an_api_key',
399 api_key_valid=False,
400 client_ip='127.0.0.1',
401 consumer_project_id='project_id',
402 operation_id='an_op_id',
403 operation_name='an_op_name',
404 referer='a_referer',
405 service_name=_TEST_SERVICE_NAME),
406 messages.Operation(
407 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
408 consumerId='project:project_id',
409 labels = encoding.PyValueToMessage(
410 messages.Operation.LabelsValue, {
411 'servicecontrol.googleapis.com/caller_ip': '127.0.0.1',
412 'servicecontrol.googleapis.com/user_agent': _WANTED_USER_AGENT,
413 'servicecontrol.googleapis.com/referer': 'a_referer'
414 }),
415 operationId='an_op_id',
416 operationName='an_op_name',
417 startTime=_START_OF_EPOCH,
418 endTime=_START_OF_EPOCH)),
419 ]
420 _INCOMPLETE_INFO_TESTS = [
421 check_request.Info(
422 operation_name='an_op_name',
423 service_name=_TEST_SERVICE_NAME),
424 check_request.Info(
425 operation_id='an_op_id',
426 service_name=_TEST_SERVICE_NAME),
427 check_request.Info(
428 operation_id='an_op_id',
429 operation_name='an_op_name')
430 ]
431
432
433 class TestInfo(unittest2.TestCase):
434
435 def test_should_construct_with_no_args(self):
436 expect(check_request.Info()).not_to(be_none)
437
438 def test_should_convert_using_as_check_request(self):
439 timer = _DateTimeTimer()
440 for info, want in _INFO_TESTS:
441 got = info.as_check_request(timer=timer)
442 expect(got.checkRequest.operation).to(equal(want))
443 expect(got.serviceName).to(equal(_TEST_SERVICE_NAME))
444
445 def test_should_fail_as_check_request_on_incomplete_info(self):
446 timer = _DateTimeTimer()
447 for info in _INCOMPLETE_INFO_TESTS:
448 testf = lambda: info.as_check_request(timer=timer)
449 expect(testf).to(raise_error(ValueError))
450
451
452 class TestConvertResponse(unittest2.TestCase):
453 PROJECT_ID = 'test_convert_response'
454
455 def test_should_be_ok_with_no_errors(self):
456 code, message, _ = check_request.convert_response(
457 messages.CheckResponse(), self.PROJECT_ID)
458 expect(code).to(equal(httplib.OK))
459 expect(message).to(equal(''))
460
461 def test_should_include_project_id_in_error_text_when_needed(self):
462 resp = messages.CheckResponse(
463 checkErrors = [
464 messages.CheckError(
465 code=messages.CheckError.CodeValueValuesEnum.PROJECT_DELETED )
466 ]
467 )
468 code, got, _ = check_request.convert_response(resp, self.PROJECT_ID)
469 want = 'Project %s has been deleted' % (self.PROJECT_ID,)
470 expect(code).to(equal(httplib.FORBIDDEN))
471 expect(got).to(equal(want))
472
473 def test_should_include_detail_in_error_text_when_needed(self):
474 detail = 'details, details, details'
475 resp = messages.CheckResponse(
476 checkErrors = [
477 messages.CheckError(
478 code=messages.CheckError.CodeValueValuesEnum.IP_ADDRESS_BLOC KED,
479 detail=detail)
480 ]
481 )
482 code, got, _ = check_request.convert_response(resp, self.PROJECT_ID)
483 expect(code).to(equal(httplib.FORBIDDEN))
484 expect(got).to(equal(detail))
485
486
487 class _DateTimeTimer(object):
488 def __init__(self, auto=False):
489 self.auto = auto
490 self.time = datetime.datetime(1970, 1, 1)
491
492 def __call__(self):
493 if self.auto:
494 self.tick()
495 return self.time
496
497 def tick(self):
498 self.time += datetime.timedelta(seconds=1)
OLDNEW
« no previous file with comments | « third_party/google-endpoints/test/test_caches.py ('k') | third_party/google-endpoints/test/test_client.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698