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

Side by Side Diff: third_party/google-endpoints/test/test_report_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 time
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, messages, metric_value
25 from google.api.control import metric_descriptor, report_request, timestamp
26
27
28 class TestReportingRules(unittest2.TestCase):
29 subject_cls = report_request.ReportingRules
30 WANTED_LABELS = (label_descriptor.KnownLabels.REFERER,)
31 WANTED_METRICS = (metric_descriptor.KnownMetrics.CONSUMER_REQUEST_COUNT,)
32
33 def test_should_construct_with_no_args(self):
34 rules = self.subject_cls()
35 expect(rules).not_to(be_none)
36 expect(rules.logs).to(equal(set()))
37 expect(rules.metrics).to(equal(tuple()))
38 expect(rules.labels).to(equal(tuple()))
39
40 def test_should_construct_with_ok_expected_args(self):
41 rules = self.subject_cls(logs=['wanted_log'],
42 metrics=self.WANTED_METRICS,
43 labels=self.WANTED_LABELS)
44 expect(rules).not_to(be_none)
45 expect(rules.logs).to(equal(set(['wanted_log'])))
46 expect(rules.metrics).to(equal(self.WANTED_METRICS))
47 expect(rules.labels).to(equal(self.WANTED_LABELS))
48
49 def test_should_construct_with_alt_constructor(self):
50 rules = self.subject_cls.from_known_inputs()
51 expect(rules).not_to(be_none)
52 expect(rules.logs).to(equal(set()))
53 expect(rules.metrics).to(equal(tuple()))
54 expect(rules.labels).to(equal(tuple()))
55
56 def test_should_construct_with_alt_constructor_with_ok_args(self):
57 logs = ['wanted_log', 'wanted_log']
58 label_names = [x.label_name for x in self.WANTED_LABELS]
59 metric_names = [x.metric_name for x in self.WANTED_METRICS]
60 rules = self.subject_cls.from_known_inputs(
61 logs=logs,
62 label_names=label_names,
63 metric_names=metric_names
64 )
65 expect(rules).not_to(be_none)
66 expect(rules.logs).to(equal(set(['wanted_log'])))
67 expect(rules.metrics).to(equal(self.WANTED_METRICS))
68 expect(rules.labels).to(equal(self.WANTED_LABELS))
69
70
71 _TEST_CONSUMER_ID = 'testConsumerID'
72 _TEST_OP1_NAME = 'testOp1'
73 _TEST_OP2_NAME = 'testOp2'
74 _WANTED_USER_AGENT = label_descriptor.USER_AGENT
75 _START_OF_EPOCH = datetime.datetime.utcfromtimestamp(0)
76 _START_OF_EPOCH_TIMESTAMP = timestamp.to_rfc3339(_START_OF_EPOCH)
77 _TEST_SERVICE_NAME = 'a_service_name'
78 _TEST_SIZE=1
79 _TEST_LATENCY=datetime.timedelta(seconds=7)
80 _EXPECTED_OK_LOG_ENTRY = messages.LogEntry(
81 name = 'endpoints-log',
82 severity = messages.LogEntry.SeverityValueValuesEnum.INFO,
83 structPayload=encoding.PyValueToMessage(
84 messages.LogEntry.StructPayloadValue, {
85 'http_response_code': 200,
86 'http_method': 'GET',
87 'request_latency_in_ms': 7000.0,
88 'timestamp': time.mktime(_START_OF_EPOCH.timetuple()),
89 'response_size': 1,
90 'request_size': 1,
91 'referer': 'a_referer',
92 }),
93 timestamp=_START_OF_EPOCH_TIMESTAMP
94 )
95 _EXPECTED_NOK_LOG_ENTRY = messages.LogEntry(
96 name = 'endpoints-log',
97 severity = messages.LogEntry.SeverityValueValuesEnum.ERROR,
98 structPayload=encoding.PyValueToMessage(
99 messages.LogEntry.StructPayloadValue, {
100 'http_response_code': 404,
101 'http_method': 'GET',
102 'request_latency_in_ms': 7000.0,
103 'timestamp': time.mktime(_START_OF_EPOCH.timetuple()),
104 'response_size': 1,
105 'request_size': 1,
106 'referer': 'a_referer',
107 'error_cause': 'internal',
108 }),
109 timestamp=_START_OF_EPOCH_TIMESTAMP
110 )
111
112 _EXPECTED_OK_METRIC = metric_descriptor.KnownMetrics.CONSUMER_REQUEST_COUNT
113 _EXPECTED_NOK_METRIC = metric_descriptor.KnownMetrics.CONSUMER_ERROR_COUNT
114 _ADD_LOG_TESTS = [
115 (report_request.Info(
116 operation_id='an_op_id',
117 operation_name='an_op_name',
118 method='GET',
119 referer='a_referer',
120 backend_time=_TEST_LATENCY,
121 overhead_time=_TEST_LATENCY,
122 request_time=_TEST_LATENCY,
123 request_size=_TEST_SIZE,
124 response_size=_TEST_SIZE,
125 service_name=_TEST_SERVICE_NAME),
126 messages.Operation(
127 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
128 logEntries=[_EXPECTED_OK_LOG_ENTRY],
129 operationId='an_op_id',
130 operationName='an_op_name',
131 startTime=_START_OF_EPOCH_TIMESTAMP,
132 endTime=_START_OF_EPOCH_TIMESTAMP)
133 ),
134 (report_request.Info(
135 response_code=404,
136 operation_id='an_op_id',
137 operation_name='an_op_name',
138 method='GET',
139 referer='a_referer',
140 backend_time=_TEST_LATENCY,
141 overhead_time=_TEST_LATENCY,
142 request_time=_TEST_LATENCY,
143 request_size=_TEST_SIZE,
144 response_size=_TEST_SIZE,
145 service_name=_TEST_SERVICE_NAME),
146 messages.Operation(
147 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
148 logEntries=[_EXPECTED_NOK_LOG_ENTRY],
149 operationId='an_op_id',
150 operationName='an_op_name',
151 startTime=_START_OF_EPOCH_TIMESTAMP,
152 endTime=_START_OF_EPOCH_TIMESTAMP)
153 )
154 ]
155
156 _TEST_API_KEY = 'test_key'
157 _ADD_METRICS_TESTS = [
158 (report_request.Info(
159 operation_id='an_op_id',
160 operation_name='an_op_name',
161 method='GET',
162 referer='a_referer',
163 backend_time=_TEST_LATENCY,
164 overhead_time=_TEST_LATENCY,
165 request_time=_TEST_LATENCY,
166 request_size=_TEST_SIZE,
167 response_size=_TEST_SIZE,
168 service_name=_TEST_SERVICE_NAME,
169 api_key=_TEST_API_KEY,
170 api_key_valid=True),
171 messages.Operation(
172 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
173 logEntries=[],
174 metricValueSets = [
175 messages.MetricValueSet(
176 metricName=_EXPECTED_OK_METRIC.metric_name,
177 metricValues=[
178 metric_value.create(int64Value=1),
179 ]
180 ),
181 ],
182 consumerId='api_key:' + _TEST_API_KEY,
183 operationId='an_op_id',
184 operationName='an_op_name',
185 startTime=_START_OF_EPOCH_TIMESTAMP,
186 endTime=_START_OF_EPOCH_TIMESTAMP)
187 ),
188 (report_request.Info(
189 response_code=404,
190 operation_id='an_op_id',
191 operation_name='an_op_name',
192 method='GET',
193 referer='a_referer',
194 backend_time=_TEST_LATENCY,
195 overhead_time=_TEST_LATENCY,
196 request_time=_TEST_LATENCY,
197 request_size=_TEST_SIZE,
198 response_size=_TEST_SIZE,
199 service_name=_TEST_SERVICE_NAME,
200 api_key=_TEST_API_KEY,
201 api_key_valid=True),
202 messages.Operation(
203 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
204 logEntries=[],
205 metricValueSets = [
206 messages.MetricValueSet(
207 metricName=_EXPECTED_OK_METRIC.metric_name,
208 metricValues=[
209 metric_value.create(int64Value=1),
210 ]
211 ),
212 messages.MetricValueSet(
213 metricName=_EXPECTED_NOK_METRIC.metric_name,
214 metricValues=[
215 metric_value.create(int64Value=1),
216 ]
217 ),
218 ],
219 consumerId='api_key:' + _TEST_API_KEY,
220 operationId='an_op_id',
221 operationName='an_op_name',
222 startTime=_START_OF_EPOCH_TIMESTAMP,
223 endTime=_START_OF_EPOCH_TIMESTAMP)
224 ),
225 ]
226
227 _EXPECTED_OK_LABEL = label_descriptor.KnownLabels.REFERER
228 _ADD_LABELS_TESTS = [
229 (report_request.Info(
230 operation_id='an_op_id',
231 operation_name='an_op_name',
232 method='GET',
233 referer='a_referer',
234 service_name=_TEST_SERVICE_NAME),
235 messages.Operation(
236 importance=messages.Operation.ImportanceValueValuesEnum.LOW,
237 labels=encoding.PyValueToMessage(
238 messages.Operation.LabelsValue, {
239 _EXPECTED_OK_LABEL.label_name: 'a_referer'
240 }),
241 logEntries=[],
242 operationId='an_op_id',
243 operationName='an_op_name',
244 startTime=_START_OF_EPOCH_TIMESTAMP,
245 endTime=_START_OF_EPOCH_TIMESTAMP)
246 ),
247 ]
248
249
250 class TestInfo(unittest2.TestCase):
251
252 def test_should_construct_with_no_args(self):
253 expect(report_request.Info()).not_to(be_none)
254
255 def test_should_raise_if_constructed_with_a_bad_protocol(self):
256 testf = lambda: report_request.Info(protocol=object())
257 # not a report_request.ReportedProtocols
258 expect(testf).to(raise_error(ValueError))
259
260 def test_should_raise_if_constructed_with_a_bad_platform(self):
261 testf = lambda: report_request.Info(platform=object())
262 expect(testf).to(raise_error(ValueError))
263
264 def test_should_raise_if_constructed_with_a_bad_request_size(self):
265 testf = lambda: report_request.Info(request_size=object())
266 expect(testf).to(raise_error(ValueError))
267 testf = lambda: report_request.Info(request_size=-2)
268 expect(testf).to(raise_error(ValueError))
269
270 def test_should_raise_if_constructed_with_a_bad_response_size(self):
271 testf = lambda: report_request.Info(response_size=object())
272 expect(testf).to(raise_error(ValueError))
273 testf = lambda: report_request.Info(response_size=-2)
274 expect(testf).to(raise_error(ValueError))
275
276 def test_should_raise_if_constructed_with_a_bad_backend_time(self):
277 testf = lambda: report_request.Info(backend_time=object())
278 expect(testf).to(raise_error(ValueError))
279
280 def test_should_raise_if_constructed_with_a_bad_overhead_time(self):
281 testf = lambda: report_request.Info(overhead_time=object())
282 expect(testf).to(raise_error(ValueError))
283
284 def test_should_raise_if_constructed_with_a_bad_request_time(self):
285 testf = lambda: report_request.Info(request_time=object())
286 expect(testf).to(raise_error(ValueError))
287
288 def test_should_raise_if_constructed_with_a_bad_error_cause(self):
289 testf = lambda: report_request.Info(error_cause=object())
290 expect(testf).to(raise_error(ValueError))
291
292 def test_should_fail_as_report_request_on_incomplete_info(self):
293 timer = _DateTimeTimer()
294 incomplete = report_request.Info() # has no service_name
295 rules = report_request.ReportingRules()
296 testf = lambda: incomplete.as_report_request(rules, timer=timer)
297 expect(testf).to(raise_error(ValueError))
298
299 def test_should_add_expected_logs_as_report_request(self):
300 timer = _DateTimeTimer()
301 rules = report_request.ReportingRules(logs=['endpoints-log'])
302 for info, want in _ADD_LOG_TESTS:
303 got = info.as_report_request(rules, timer=timer)
304 expect(got.serviceName).to(equal(_TEST_SERVICE_NAME))
305 # compare the log entry in detail to avoid instability when
306 # comparing the operations directly
307 wantLogEntry = want.logEntries[0]
308 gotLogEntry = got.reportRequest.operations[0].logEntries[0]
309 expect(gotLogEntry.name).to(equal(wantLogEntry.name))
310 expect(gotLogEntry.timestamp).to(equal(wantLogEntry.timestamp))
311 print 'got timestamp', gotLogEntry.timestamp
312 print 'want timestamp', wantLogEntry.timestamp
313 expect(gotLogEntry.severity).to(equal(wantLogEntry.severity))
314 gotStruct = encoding.MessageToPyValue(gotLogEntry.structPayload)
315 print 'got struct', gotStruct
316 wantStruct = encoding.MessageToPyValue(wantLogEntry.structPayload)
317 print 'want struct', wantStruct
318 expect(gotStruct).to(equal(wantStruct))
319
320 def test_should_add_expected_metric_as_report_request(self):
321 timer = _DateTimeTimer()
322 rules = report_request.ReportingRules(metrics=[
323 _EXPECTED_OK_METRIC, _EXPECTED_NOK_METRIC
324 ])
325 for info, want in _ADD_METRICS_TESTS:
326 got = info.as_report_request(rules, timer=timer)
327 expect(got.serviceName).to(equal(_TEST_SERVICE_NAME))
328 expect(got.reportRequest.operations[0]).to(equal(want))
329
330 def test_should_add_expected_label_as_report_request(self):
331 timer = _DateTimeTimer()
332 rules = report_request.ReportingRules(labels=[
333 _EXPECTED_OK_LABEL
334 ])
335 for info, want in _ADD_LABELS_TESTS:
336 got = info.as_report_request(rules, timer=timer)
337 expect(got.serviceName).to(equal(_TEST_SERVICE_NAME))
338 expect(got.reportRequest.operations[0]).to(equal(want))
339
340
341 class TestAggregatorReport(unittest2.TestCase):
342 SERVICE_NAME = 'service.report'
343
344 def setUp(self):
345 self.timer = _DateTimeTimer()
346 self.agg = report_request.Aggregator(
347 self.SERVICE_NAME, caches.ReportOptions())
348
349 def test_should_fail_if_req_is_bad(self):
350 testf = lambda: self.agg.report(object())
351 expect(testf).to(raise_error(ValueError))
352 testf = lambda: self.agg.report(None)
353 expect(testf).to(raise_error(ValueError))
354
355 def test_should_fail_if_service_name_does_not_match(self):
356 req = _make_test_request(self.SERVICE_NAME + '-will-not-match')
357 testf = lambda: self.agg.report(req)
358 expect(testf).to(raise_error(ValueError))
359
360 def test_should_fail_if_check_request_is_missing(self):
361 req = messages.ServicecontrolServicesReportRequest(
362 serviceName=self.SERVICE_NAME)
363 testf = lambda: self.agg.report(req)
364 expect(testf).to(raise_error(ValueError))
365
366
367 class TestAggregatorTheCannotCache(unittest2.TestCase):
368 SERVICE_NAME = 'service.no_cache'
369
370 def setUp(self):
371 # -ve num_entries means no cache is present
372 self.agg = report_request.Aggregator(
373 self.SERVICE_NAME,
374 caches.ReportOptions(num_entries=-1))
375
376 def test_should_not_cache_responses(self):
377 req = _make_test_request(self.SERVICE_NAME)
378 expect(self.agg.report(req)).to(be_none)
379
380 def test_should_have_empty_flush_response(self):
381 expect(len(self.agg.flush())).to(equal(0))
382
383 def test_should_have_none_as_flush_interval(self):
384 expect(self.agg.flush_interval).to(be_none)
385
386
387 class TestCachingAggregator(unittest2.TestCase):
388 SERVICE_NAME = 'service.with_cache'
389
390 def setUp(self):
391 self.timer = _DateTimeTimer()
392 self.flush_interval = datetime.timedelta(seconds=1)
393 options = caches.ReportOptions(flush_interval=self.flush_interval)
394 self.agg = report_request.Aggregator(
395 self.SERVICE_NAME, options, timer=self.timer)
396
397 def test_should_have_option_flush_interval_as_the_flush_interval(self):
398 expect(self.agg.flush_interval).to(equal(self.flush_interval))
399
400 def test_should_not_cache_requests_with_important_operations(self):
401 req = _make_test_request(
402 self.SERVICE_NAME,
403 importance=messages.Operation.ImportanceValueValuesEnum.HIGH)
404 agg = self.agg
405 expect(agg.report(req)).to(be_none)
406
407 def test_should_cache_requests_and_return_cached_ok(self):
408 req = _make_test_request(self.SERVICE_NAME, n=2, start=0)
409 agg = self.agg
410 expect(agg.report(req)).to(equal(report_request.Aggregator.CACHED_OK))
411
412 def test_should_cache_requests_and_batch_them_on_flush(self):
413 req1 = _make_test_request(self.SERVICE_NAME, n=2, start=0)
414 req2 = _make_test_request(self.SERVICE_NAME, n=2, start=2)
415
416 agg = self.agg
417 expect(agg.report(req1)).to(equal(report_request.Aggregator.CACHED_OK))
418 expect(agg.report(req2)).to(equal(report_request.Aggregator.CACHED_OK))
419 # no immediate requests for flush
420 flushed_reqs = agg.flush()
421 expect(len(flushed_reqs)).to(equal(0))
422
423 self.timer.tick() # time passes ...
424 self.timer.tick() # ... and is now past the flush_interval
425 flushed_reqs = agg.flush()
426 expect(len(flushed_reqs)).to(equal(1))
427 flushed_ops = flushed_reqs[0].reportRequest.operations
428 expect(len(flushed_ops)).to(equal(4)) # number of ops in the req{1,2}
429
430 def test_should_aggregate_operations_in_requests(self):
431 n = 261 # arbitrary
432 agg = self.agg
433 for _ in range(n):
434 # many requests, but only two ops
435 req = _make_test_request(self.SERVICE_NAME, n=2, start=0)
436 expect(agg.report(req)).to(
437 equal(report_request.Aggregator.CACHED_OK))
438
439 # time passes ...
440 self.timer.tick()
441 self.timer.tick() # ... and is now past the flush_interval
442 flushed_reqs = agg.flush()
443 expect(len(flushed_reqs)).to(equal(1))
444 flushed_ops = flushed_reqs[0].reportRequest.operations
445 expect(len(flushed_ops)).to(equal(2)) # many requests, but only two ops
446
447 def test_may_clear_aggregated_operations(self):
448 n = 261 # arbitrary
449 agg = self.agg
450 for i in range(n):
451 # many requests, but only two ops
452 req = _make_test_request(self.SERVICE_NAME, n=2, start=0)
453 expect(agg.report(req)).to(
454 equal(report_request.Aggregator.CACHED_OK))
455
456 # time passes ...
457 agg.clear() # the aggregator is cleared
458 self.timer.tick()
459 self.timer.tick() # ... and is now past the flush_interval
460 flushed_reqs = agg.flush()
461 expect(len(flushed_reqs)).to(equal(0)) # but there is nothing
462
463
464 class _DateTimeTimer(object):
465 def __init__(self, auto=False):
466 self.auto = auto
467 self.time = datetime.datetime.utcfromtimestamp(0)
468
469 def __call__(self):
470 if self.auto:
471 self.tick()
472 return self.time
473
474 def tick(self):
475 self.time += datetime.timedelta(seconds=1)
476
477
478 def _make_op_names(n, start=0):
479 return ('testOp%d' % (x,) for x in range(start, start + n))
480
481
482 def _make_test_request(service_name, importance=None, n=3, start=0):
483 if importance is None:
484 importance = messages.Operation.ImportanceValueValuesEnum.LOW
485 op_names = _make_op_names(n, start=start)
486 ops = [messages.Operation(consumerId=_TEST_CONSUMER_ID,
487 operationName=op_name,
488 importance=importance) for op_name in op_names]
489 if ops:
490 ops[0].labels = encoding.PyValueToMessage(
491 messages.Operation.LabelsValue, {
492 'key1': 'always add a label to the first op'
493 })
494 report_request = messages.ReportRequest(operations=ops)
495 return messages.ServicecontrolServicesReportRequest(
496 serviceName=service_name,
497 reportRequest=report_request)
OLDNEW
« no previous file with comments | « third_party/google-endpoints/test/test_path_template.py ('k') | third_party/google-endpoints/test/test_service.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698