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

Side by Side Diff: telemetry/third_party/webpagereplay/httparchive_test.py

Issue 2210063003: Rename third_party/webpagereplay to third_party/web-page-replay (Closed) Base URL: https://github.com/catapult-project/catapult@master
Patch Set: Created 4 years, 4 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 #!/usr/bin/env python
2 # Copyright 2011 Google Inc. All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import calendar
17 import email.utils
18 import httparchive
19 import unittest
20
21
22 def create_request(headers):
23 return httparchive.ArchivedHttpRequest(
24 'GET', 'www.test.com', '/', None, headers)
25
26 def create_response(headers):
27 return httparchive.ArchivedHttpResponse(
28 11, 200, 'OK', headers, '')
29
30
31 class HttpArchiveTest(unittest.TestCase):
32
33 REQUEST_HEADERS = {}
34 REQUEST = create_request(REQUEST_HEADERS)
35
36 # Used for if-(un)modified-since checks
37 DATE_PAST = 'Wed, 13 Jul 2011 03:58:08 GMT'
38 DATE_PRESENT = 'Wed, 20 Jul 2011 04:58:08 GMT'
39 DATE_FUTURE = 'Wed, 27 Jul 2011 05:58:08 GMT'
40 DATE_INVALID = 'This is an invalid date!!'
41
42 # etag values
43 ETAG_VALID = 'etag'
44 ETAG_INVALID = 'This is an invalid etag value!!'
45
46 RESPONSE_HEADERS = [('last-modified', DATE_PRESENT), ('etag', ETAG_VALID)]
47 RESPONSE = create_response(RESPONSE_HEADERS)
48
49 def setUp(self):
50 self.archive = httparchive.HttpArchive()
51 self.archive[self.REQUEST] = self.RESPONSE
52
53 # Also add an identical POST request for testing
54 request = httparchive.ArchivedHttpRequest(
55 'POST', 'www.test.com', '/', None, self.REQUEST_HEADERS)
56 self.archive[request] = self.RESPONSE
57
58 def tearDown(self):
59 pass
60
61 def test_init(self):
62 archive = httparchive.HttpArchive()
63 self.assertEqual(len(archive), 0)
64
65 def test_request__TrimHeaders(self):
66 request = httparchive.ArchivedHttpRequest
67 header1 = {'accept-encoding': 'gzip,deflate'}
68 self.assertEqual(request._TrimHeaders(header1),
69 [(k, v) for k, v in header1.items()])
70
71 header2 = {'referer': 'www.google.com'}
72 self.assertEqual(request._TrimHeaders(header2), [])
73
74 header3 = {'referer': 'www.google.com', 'cookie': 'cookie_monster!',
75 'hello': 'world'}
76 self.assertEqual(request._TrimHeaders(header3), [('hello', 'world')])
77
78 # Tests that spaces and trailing comma get stripped.
79 header4 = {'accept-encoding': 'gzip, deflate,, '}
80 self.assertEqual(request._TrimHeaders(header4),
81 [('accept-encoding', 'gzip,deflate')])
82
83 # Tests that 'lzma' gets stripped.
84 header5 = {'accept-encoding': 'gzip, deflate, lzma'}
85 self.assertEqual(request._TrimHeaders(header5),
86 [('accept-encoding', 'gzip,deflate')])
87
88 # Tests that x-client-data gets stripped.
89 header6 = {'x-client-data': 'testdata'}
90 self.assertEqual(request._TrimHeaders(header6), [])
91
92 def test_matches(self):
93 headers = {}
94 request1 = httparchive.ArchivedHttpRequest(
95 'GET', 'www.test.com', '/index.html?hello=world', None, headers)
96 request2 = httparchive.ArchivedHttpRequest(
97 'GET', 'www.test.com', '/index.html?foo=bar', None, headers)
98
99 self.assert_(not request1.matches(
100 request2.command, request2.host, request2.full_path, use_query=True))
101 self.assert_(request1.matches(
102 request2.command, request2.host, request2.full_path, use_query=False))
103
104 self.assert_(request1.matches(
105 request2.command, request2.host, None, use_query=True))
106 self.assert_(request1.matches(
107 request2.command, None, request2.full_path, use_query=False))
108
109 empty_request = httparchive.ArchivedHttpRequest(
110 None, None, None, None, headers)
111 self.assert_(not empty_request.matches(
112 request2.command, request2.host, None, use_query=True))
113 self.assert_(not empty_request.matches(
114 request2.command, None, request2.full_path, use_query=False))
115
116 def setup_find_closest_request(self):
117 headers = {}
118 request1 = httparchive.ArchivedHttpRequest(
119 'GET', 'www.test.com', '/a?hello=world', None, headers)
120 request2 = httparchive.ArchivedHttpRequest(
121 'GET', 'www.test.com', '/a?foo=bar', None, headers)
122 request3 = httparchive.ArchivedHttpRequest(
123 'GET', 'www.test.com', '/b?hello=world', None, headers)
124 request4 = httparchive.ArchivedHttpRequest(
125 'GET', 'www.test.com', '/c?hello=world', None, headers)
126
127 archive = httparchive.HttpArchive()
128 # Add requests 2 and 3 and find closest match with request1
129 archive[request2] = self.RESPONSE
130 archive[request3] = self.RESPONSE
131
132 return archive, request1, request2, request3, request4
133
134 def test_find_closest_request(self):
135 archive, request1, request2, request3, request4 = (
136 self.setup_find_closest_request())
137
138 # Always favor requests with same paths, even if use_path=False.
139 self.assertEqual(
140 request2, archive.find_closest_request(request1, use_path=False))
141 # If we match strictly on path, request2 is the only match
142 self.assertEqual(
143 request2, archive.find_closest_request(request1, use_path=True))
144 # request4 can be matched with request3, if use_path=False
145 self.assertEqual(
146 request3, archive.find_closest_request(request4, use_path=False))
147 # ...but None, if use_path=True
148 self.assertEqual(
149 None, archive.find_closest_request(request4, use_path=True))
150
151 def test_find_closest_request_delete_simple(self):
152 archive, request1, request2, request3, request4 = (
153 self.setup_find_closest_request())
154
155 del archive[request3]
156 self.assertEqual(
157 request2, archive.find_closest_request(request1, use_path=False))
158 self.assertEqual(
159 request2, archive.find_closest_request(request1, use_path=True))
160
161 def test_find_closest_request_delete_complex(self):
162 archive, request1, request2, request3, request4 = (
163 self.setup_find_closest_request())
164
165 del archive[request2]
166 self.assertEqual(
167 request3, archive.find_closest_request(request1, use_path=False))
168 self.assertEqual(
169 None, archive.find_closest_request(request1, use_path=True))
170
171 def test_find_closest_request_timestamp(self):
172 headers = {}
173 request1 = httparchive.ArchivedHttpRequest(
174 'GET', 'www.test.com', '/index.html?time=100000000&important=true',
175 None, headers)
176 request2 = httparchive.ArchivedHttpRequest(
177 'GET', 'www.test.com', '/index.html?time=99999999&important=true',
178 None, headers)
179 request3 = httparchive.ArchivedHttpRequest(
180 'GET', 'www.test.com', '/index.html?time=10000000&important=false',
181 None, headers)
182 archive = httparchive.HttpArchive()
183 # Add requests 2 and 3 and find closest match with request1
184 archive[request2] = self.RESPONSE
185 archive[request3] = self.RESPONSE
186
187 # Although request3 is lexicographically closer, request2 is semantically
188 # more similar.
189 self.assertEqual(
190 request2, archive.find_closest_request(request1, use_path=True))
191
192 def test_get_cmp_seq(self):
193 # The order of key-value pairs in query and header respectively should not
194 # matter.
195 headers = {'k2': 'v2', 'k1': 'v1'}
196 request = httparchive.ArchivedHttpRequest(
197 'GET', 'www.test.com', '/a?c=d&a=b;e=f', None, headers)
198 self.assertEqual([('a', 'b'), ('c', 'd'), ('e', 'f'),
199 ('k1', 'v1'), ('k2', 'v2')],
200 request._GetCmpSeq('c=d&a=b;e=f'))
201
202 def test_get_simple(self):
203 request = self.REQUEST
204 response = self.RESPONSE
205 archive = self.archive
206
207 self.assertEqual(archive.get(request), response)
208
209 false_request_headers = {'foo': 'bar'}
210 false_request = create_request(false_request_headers)
211 self.assertEqual(archive.get(false_request, default=None), None)
212
213 def test_get_modified_headers(self):
214 request = self.REQUEST
215 response = self.RESPONSE
216 archive = self.archive
217 not_modified_response = httparchive.create_response(304)
218
219 # Fail check and return response again
220 request_headers = {'if-modified-since': self.DATE_PAST}
221 request = create_request(request_headers)
222 self.assertEqual(archive.get(request), response)
223
224 # Succeed check and return 304 Not Modified
225 request_headers = {'if-modified-since': self.DATE_FUTURE}
226 request = create_request(request_headers)
227 self.assertEqual(archive.get(request), not_modified_response)
228
229 # Succeed check and return 304 Not Modified
230 request_headers = {'if-modified-since': self.DATE_PRESENT}
231 request = create_request(request_headers)
232 self.assertEqual(archive.get(request), not_modified_response)
233
234 # Invalid date, fail check and return response again
235 request_headers = {'if-modified-since': self.DATE_INVALID}
236 request = create_request(request_headers)
237 self.assertEqual(archive.get(request), response)
238
239 # fail check since the request is not a GET or HEAD request (as per RFC)
240 request_headers = {'if-modified-since': self.DATE_FUTURE}
241 request = httparchive.ArchivedHttpRequest(
242 'POST', 'www.test.com', '/', None, request_headers)
243 self.assertEqual(archive.get(request), response)
244
245 def test_get_unmodified_headers(self):
246 request = self.REQUEST
247 response = self.RESPONSE
248 archive = self.archive
249 not_modified_response = httparchive.create_response(304)
250
251 # Succeed check
252 request_headers = {'if-unmodified-since': self.DATE_PAST}
253 request = create_request(request_headers)
254 self.assertEqual(archive.get(request), not_modified_response)
255
256 # Fail check
257 request_headers = {'if-unmodified-since': self.DATE_FUTURE}
258 request = create_request(request_headers)
259 self.assertEqual(archive.get(request), response)
260
261 # Succeed check
262 request_headers = {'if-unmodified-since': self.DATE_PRESENT}
263 request = create_request(request_headers)
264 self.assertEqual(archive.get(request), not_modified_response)
265
266 # Fail check
267 request_headers = {'if-unmodified-since': self.DATE_INVALID}
268 request = create_request(request_headers)
269 self.assertEqual(archive.get(request), response)
270
271 # Fail check since the request is not a GET or HEAD request (as per RFC)
272 request_headers = {'if-modified-since': self.DATE_PAST}
273 request = httparchive.ArchivedHttpRequest(
274 'POST', 'www.test.com', '/', None, request_headers)
275 self.assertEqual(archive.get(request), response)
276
277 def test_get_etags(self):
278 request = self.REQUEST
279 response = self.RESPONSE
280 archive = self.archive
281 not_modified_response = httparchive.create_response(304)
282 precondition_failed_response = httparchive.create_response(412)
283
284 # if-match headers
285 request_headers = {'if-match': self.ETAG_VALID}
286 request = create_request(request_headers)
287 self.assertEqual(archive.get(request), response)
288
289 request_headers = {'if-match': self.ETAG_INVALID}
290 request = create_request(request_headers)
291 self.assertEqual(archive.get(request), precondition_failed_response)
292
293 # if-none-match headers
294 request_headers = {'if-none-match': self.ETAG_VALID}
295 request = create_request(request_headers)
296 self.assertEqual(archive.get(request), not_modified_response)
297
298 request_headers = {'if-none-match': self.ETAG_INVALID}
299 request = create_request(request_headers)
300 self.assertEqual(archive.get(request), response)
301
302 def test_get_multiple_match_headers(self):
303 request = self.REQUEST
304 response = self.RESPONSE
305 archive = self.archive
306 not_modified_response = httparchive.create_response(304)
307 precondition_failed_response = httparchive.create_response(412)
308
309 # if-match headers
310 # If the request would, without the If-Match header field,
311 # result in anything other than a 2xx or 412 status,
312 # then the If-Match header MUST be ignored.
313
314 request_headers = {
315 'if-match': self.ETAG_VALID,
316 'if-modified-since': self.DATE_PAST,
317 }
318 request = create_request(request_headers)
319 self.assertEqual(archive.get(request), response)
320
321 # Invalid etag, precondition failed
322 request_headers = {
323 'if-match': self.ETAG_INVALID,
324 'if-modified-since': self.DATE_PAST,
325 }
326 request = create_request(request_headers)
327 self.assertEqual(archive.get(request), precondition_failed_response)
328
329 # 304 response; ignore if-match header
330 request_headers = {
331 'if-match': self.ETAG_VALID,
332 'if-modified-since': self.DATE_FUTURE,
333 }
334 request = create_request(request_headers)
335 self.assertEqual(archive.get(request), not_modified_response)
336
337 # 304 response; ignore if-match header
338 request_headers = {
339 'if-match': self.ETAG_INVALID,
340 'if-modified-since': self.DATE_PRESENT,
341 }
342 request = create_request(request_headers)
343 self.assertEqual(archive.get(request), not_modified_response)
344
345 # Invalid etag, precondition failed
346 request_headers = {
347 'if-match': self.ETAG_INVALID,
348 'if-modified-since': self.DATE_INVALID,
349 }
350 request = create_request(request_headers)
351 self.assertEqual(archive.get(request), precondition_failed_response)
352
353 def test_get_multiple_none_match_headers(self):
354 request = self.REQUEST
355 response = self.RESPONSE
356 archive = self.archive
357 not_modified_response = httparchive.create_response(304)
358 precondition_failed_response = httparchive.create_response(412)
359
360 # if-none-match headers
361 # If the request would, without the If-None-Match header field,
362 # result in anything other than a 2xx or 304 status,
363 # then the If-None-Match header MUST be ignored.
364
365 request_headers = {
366 'if-none-match': self.ETAG_VALID,
367 'if-modified-since': self.DATE_PAST,
368 }
369 request = create_request(request_headers)
370 self.assertEqual(archive.get(request), response)
371
372 request_headers = {
373 'if-none-match': self.ETAG_INVALID,
374 'if-modified-since': self.DATE_PAST,
375 }
376 request = create_request(request_headers)
377 self.assertEqual(archive.get(request), response)
378
379 # etag match, precondition failed
380 request_headers = {
381 'if-none-match': self.ETAG_VALID,
382 'if-modified-since': self.DATE_FUTURE,
383 }
384 request = create_request(request_headers)
385 self.assertEqual(archive.get(request), not_modified_response)
386
387 request_headers = {
388 'if-none-match': self.ETAG_INVALID,
389 'if-modified-since': self.DATE_PRESENT,
390 }
391 request = create_request(request_headers)
392 self.assertEqual(archive.get(request), not_modified_response)
393
394 request_headers = {
395 'if-none-match': self.ETAG_INVALID,
396 'if-modified-since': self.DATE_INVALID,
397 }
398 request = create_request(request_headers)
399 self.assertEqual(archive.get(request), response)
400
401 def test_response__TrimHeaders(self):
402 response = httparchive.ArchivedHttpResponse
403 header1 = [('access-control-allow-origin', '*'),
404 ('content-type', 'image/jpeg'),
405 ('content-length', 2878)]
406 self.assertEqual(response._TrimHeaders(header1), header1)
407
408 header2 = [('content-type', 'text/javascript; charset=utf-8'),
409 ('connection', 'keep-alive'),
410 ('cache-control', 'private, must-revalidate, max-age=0'),
411 ('content-encoding', 'gzip')]
412 self.assertEqual(response._TrimHeaders(header2), header2)
413
414 header3 = [('content-security-policy', """\
415 default-src 'self' http://*.cnn.com:* https://*.cnn.com:* \
416 *.cnn.net:* *.turner.com:* *.ugdturner.com:* *.vgtf.net:*; \
417 script-src 'unsafe-inline' 'unsafe-eval' 'self' *; \
418 style-src 'unsafe-inline' 'self' *; frame-src 'self' *; \
419 object-src 'self' *; img-src 'self' * data:; media-src 'self' *; \
420 font-src 'self' *; connect-src 'self' *"""),
421 ('access-control-allow-origin', '*'),
422 ('content-type', 'text/html; charset=utf-8'),
423 ('content-encoding', 'gzip')]
424 self.assertEqual(response._TrimHeaders(header3), [
425 ('access-control-allow-origin', '*'),
426 ('content-type', 'text/html; charset=utf-8'),
427 ('content-encoding', 'gzip')
428 ])
429
430 header4 = [('content-security-policy', """\
431 default-src * data: blob:;script-src *.facebook.com *.fbcdn.net \
432 *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com \
433 127.0.0.1:* *.spotilocal.com:* 'unsafe-inline' 'unsafe-eval' \
434 fbstatic-a.akamaihd.net fbcdn-static-b-a.akamaihd.net *.atlassolutions.com \
435 blob: chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl \
436 *.liverail.com;style-src * 'unsafe-inline' data:;connect-src *.facebook.com \
437 *.fbcdn.net *.facebook.net *.spotilocal.com:* *.akamaihd.net \
438 wss://*.facebook.com:* https://fb.scanandcleanlocal.com:* \
439 *.atlassolutions.com attachment.fbsbx.com ws://localhost:* \
440 blob: 127.0.0.1:* *.liverail.com""")]
441 self.assertEqual(response._TrimHeaders(header4), [])
442
443
444 class ArchivedHttpResponse(unittest.TestCase):
445 PAST_DATE_A = 'Tue, 13 Jul 2010 03:47:07 GMT'
446 PAST_DATE_B = 'Tue, 13 Jul 2010 02:47:07 GMT' # PAST_DATE_A -1 hour
447 PAST_DATE_C = 'Tue, 13 Jul 2010 04:47:07 GMT' # PAST_DATE_A +1 hour
448 NOW_DATE_A = 'Wed, 20 Jul 2011 04:58:08 GMT'
449 NOW_DATE_B = 'Wed, 20 Jul 2011 03:58:08 GMT' # NOW_DATE_A -1 hour
450 NOW_DATE_C = 'Wed, 20 Jul 2011 05:58:08 GMT' # NOW_DATE_A +1 hour
451 NOW_SECONDS = calendar.timegm(email.utils.parsedate(NOW_DATE_A))
452
453 def setUp(self):
454 self.response = create_response([('date', self.PAST_DATE_A)])
455
456 def test_update_date_same_date(self):
457 self.assertEqual(
458 self.response.update_date(self.PAST_DATE_A, now=self.NOW_SECONDS),
459 self.NOW_DATE_A)
460
461 def test_update_date_before_date(self):
462 self.assertEqual(
463 self.response.update_date(self.PAST_DATE_B, now=self.NOW_SECONDS),
464 self.NOW_DATE_B)
465
466 def test_update_date_after_date(self):
467 self.assertEqual(
468 self.response.update_date(self.PAST_DATE_C, now=self.NOW_SECONDS),
469 self.NOW_DATE_C)
470
471 def test_update_date_bad_date_param(self):
472 self.assertEqual(
473 self.response.update_date('garbage date', now=self.NOW_SECONDS),
474 'garbage date')
475
476 def test_update_date_bad_date_header(self):
477 self.response.set_header('date', 'garbage date')
478 self.assertEqual(
479 self.response.update_date(self.PAST_DATE_B, now=self.NOW_SECONDS),
480 self.PAST_DATE_B)
481
482
483 if __name__ == '__main__':
484 unittest.main()
OLDNEW
« no previous file with comments | « telemetry/third_party/webpagereplay/httparchive.py ('k') | telemetry/third_party/webpagereplay/httpclient.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698