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

Side by Side Diff: tests/run_isolated_test.py

Issue 23657003: Move url_open with dependencies to utils.net module. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/swarm_client
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import json 6 import json
7 import logging 7 import logging
8 import math
9 import os 8 import os
10 import shutil 9 import shutil
11 import StringIO
12 import sys 10 import sys
13 import tempfile 11 import tempfile
14 import time 12 import time
15 import unittest 13 import unittest
16 import urllib2
17 14
18 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 15 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 sys.path.insert(0, ROOT_DIR) 16 sys.path.insert(0, ROOT_DIR)
20 17
21 import auto_stub 18 import auto_stub
22 import run_isolated 19 import run_isolated
23 20
24 # Number of times self._now() is called per loop in HttpService._retry_loop(). 21 from utils import net
25 NOW_CALLS_PER_OPEN = 2
26 22
27 23
28 class RemoteTest(run_isolated.Remote): 24 class RemoteTest(run_isolated.Remote):
29 def get_file_handler(self, _): # pylint: disable=R0201 25 def get_file_handler(self, _): # pylint: disable=R0201
30 def upload_file(item, _dest): 26 def upload_file(item, _dest):
31 if type(item) == type(Exception) and issubclass(item, Exception): 27 if type(item) == type(Exception) and issubclass(item, Exception):
32 raise item() 28 raise item()
33 elif isinstance(item, int): 29 elif isinstance(item, int):
34 time.sleep(int(item) / 100) 30 time.sleep(int(item) / 100)
35 return upload_file 31 return upload_file
36 32
37 33
38 def fake_http_response(content, url):
39 """Returns run_isolated.HttpResponse with predefined content."""
40 stream = StringIO.StringIO(content)
41 stream.headers = {'content-length': len(content)}
42 return run_isolated.HttpResponse(stream, url)
43
44
45 class RunIsolatedTest(auto_stub.TestCase): 34 class RunIsolatedTest(auto_stub.TestCase):
46 def setUp(self): 35 def setUp(self):
47 super(RunIsolatedTest, self).setUp() 36 super(RunIsolatedTest, self).setUp()
48 self.tempdir = tempfile.mkdtemp(prefix='run_isolated') 37 self.tempdir = tempfile.mkdtemp(prefix='run_isolated')
49 os.chdir(self.tempdir) 38 os.chdir(self.tempdir)
50 39
51 def tearDown(self): 40 def tearDown(self):
52 os.chdir(ROOT_DIR) 41 os.chdir(ROOT_DIR)
53 shutil.rmtree(self.tempdir) 42 shutil.rmtree(self.tempdir)
54 super(RunIsolatedTest, self).tearDown() 43 super(RunIsolatedTest, self).tearDown()
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 119
131 def RaiseIOError(*_): 120 def RaiseIOError(*_):
132 raise IOError() 121 raise IOError()
133 remote._do_item = RaiseIOError 122 remote._do_item = RaiseIOError
134 remote.add_item(run_isolated.Remote.MED, 'ignored', '', 123 remote.add_item(run_isolated.Remote.MED, 'ignored', '',
135 run_isolated.UNKNOWN_FILE_SIZE) 124 run_isolated.UNKNOWN_FILE_SIZE)
136 self.assertRaises(IOError, remote.join) 125 self.assertRaises(IOError, remote.join)
137 self.assertEqual([], remote.join()) 126 self.assertEqual([], remote.join())
138 127
139 def test_zip_header_error(self): 128 def test_zip_header_error(self):
140 self.mock(run_isolated, 'url_open', 129 self.mock(run_isolated.net, 'url_open',
141 lambda url, **_kwargs: fake_http_response('111', url)) 130 lambda url, **_kwargs: net.HttpResponse.get_fake_response('111', url))
142 self.mock(run_isolated.time, 'sleep', lambda _x: None) 131 self.mock(run_isolated.time, 'sleep', lambda _x: None)
143 132
144 remote = run_isolated.Remote('https://fake-CAD.com/') 133 remote = run_isolated.Remote('https://fake-CAD.com/')
145 134
146 # Both files will fail to be unzipped due to incorrect headers, 135 # Both files will fail to be unzipped due to incorrect headers,
147 # ensure that we don't accept the files (even if the size is unknown)}. 136 # ensure that we don't accept the files (even if the size is unknown)}.
148 remote.add_item(run_isolated.Remote.MED, 'zipped_A', 'A', 137 remote.add_item(run_isolated.Remote.MED, 'zipped_A', 'A',
149 run_isolated.UNKNOWN_FILE_SIZE) 138 run_isolated.UNKNOWN_FILE_SIZE)
150 remote.add_item(run_isolated.Remote.MED, 'zipped_B', 'B', 5) 139 remote.add_item(run_isolated.Remote.MED, 'zipped_B', 'B', 5)
151 self.assertRaises(IOError, remote.get_one_result) 140 self.assertRaises(IOError, remote.get_one_result)
152 self.assertRaises(IOError, remote.get_one_result) 141 self.assertRaises(IOError, remote.get_one_result)
153 # Need to use join here, since get_one_result will hang. 142 # Need to use join here, since get_one_result will hang.
154 self.assertEqual([], remote.join()) 143 self.assertEqual([], remote.join())
155 144
156 145
157
158 class HttpServiceTest(auto_stub.TestCase):
159
160 # HttpService that doesn't sleep in retries and doesn't write cookie files.
161 class HttpServiceNoSideEffects(run_isolated.HttpService):
162 def __init__(self, *args, **kwargs):
163 super(HttpServiceTest.HttpServiceNoSideEffects, self).__init__(
164 *args, **kwargs)
165 self.sleeps = []
166 self._count = 0.
167
168 def _now(self): # pylint: disable=W0221
169 x = self._count
170 self._count += 1
171 return x
172
173 def sleep_before_retry(self, attempt, max_wait):
174 self.sleeps.append((attempt, max_wait))
175
176 def load_cookie_jar(self): # pylint: disable=W0221
177 pass
178
179 def save_cookie_jar(self): # pylint: disable=W0221
180 pass
181
182 def mocked_http_service(self, url='http://example.com', **kwargs):
183 service = HttpServiceTest.HttpServiceNoSideEffects(url)
184 for name, fn in kwargs.iteritems():
185 self.assertTrue(getattr(service, name))
186 setattr(service, name, fn)
187 return service
188
189 def test_request_GET_success(self):
190 service_url = 'http://example.com'
191 request_url = '/some_request'
192 response = 'True'
193
194 def mock_url_open(request, **_kwargs):
195 self.assertTrue(request.get_full_url().startswith(service_url +
196 request_url))
197 return StringIO.StringIO(response)
198
199 service = self.mocked_http_service(url=service_url, _url_open=mock_url_open)
200 self.assertEqual(service.request(request_url).read(), response)
201 self.assertEqual([], service.sleeps)
202
203 def test_request_POST_success(self):
204 service_url = 'http://example.com'
205 request_url = '/some_request'
206 response = 'True'
207
208 def mock_url_open(request, **_kwargs):
209 self.assertTrue(request.get_full_url().startswith(service_url +
210 request_url))
211 self.assertEqual('', request.get_data())
212 return StringIO.StringIO(response)
213
214 service = self.mocked_http_service(url=service_url, _url_open=mock_url_open)
215 self.assertEqual(service.request(request_url, data={}).read(), response)
216 self.assertEqual([], service.sleeps)
217
218 def test_request_success_after_failure(self):
219 response = 'True'
220
221 def mock_url_open(request, **_kwargs):
222 if run_isolated.COUNT_KEY + '=1' not in request.get_data():
223 raise urllib2.URLError('url')
224 return StringIO.StringIO(response)
225
226 service = self.mocked_http_service(_url_open=mock_url_open)
227 self.assertEqual(service.request('/', data={}).read(), response)
228 self.assertEqual(
229 [(0, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN)],
230 service.sleeps)
231
232 def test_request_failure_max_attempts_default(self):
233 def mock_url_open(_request, **_kwargs):
234 raise urllib2.URLError('url')
235 service = self.mocked_http_service(_url_open=mock_url_open)
236 self.assertEqual(service.request('/'), None)
237 retries = [
238 (i, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN * (i + 1))
239 for i in xrange(run_isolated.URL_OPEN_MAX_ATTEMPTS)
240 ]
241 self.assertEqual(retries, service.sleeps)
242
243 def test_request_failure_max_attempts(self):
244 def mock_url_open(_request, **_kwargs):
245 raise urllib2.URLError('url')
246 service = self.mocked_http_service(_url_open=mock_url_open)
247 self.assertEqual(service.request('/', max_attempts=23), None)
248 retries = [
249 (i, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN * (i + 1))
250 for i in xrange(23)
251 ]
252 self.assertEqual(retries, service.sleeps)
253
254 def test_request_failure_timeout(self):
255 def mock_url_open(_request, **_kwargs):
256 raise urllib2.URLError('url')
257 service = self.mocked_http_service(_url_open=mock_url_open)
258 self.assertEqual(service.request('/', max_attempts=10000), None)
259 retries = [
260 (i, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN * (i + 1))
261 # Currently 179 for timeout == 360.
262 for i in xrange(
263 int(run_isolated.URL_OPEN_TIMEOUT) / NOW_CALLS_PER_OPEN - 1)
264 ]
265 self.assertEqual(retries, service.sleeps)
266
267 def test_request_failure_timeout_default(self):
268 def mock_url_open(_request, **_kwargs):
269 raise urllib2.URLError('url')
270 service = self.mocked_http_service(_url_open=mock_url_open)
271 self.assertEqual(service.request('/', timeout=10.), None)
272 retries = [(i, 8. - (NOW_CALLS_PER_OPEN * i)) for i in xrange(4)]
273 self.assertEqual(retries, service.sleeps)
274
275 def test_request_HTTP_error_no_retry(self):
276 count = []
277 def mock_url_open(request, **_kwargs):
278 count.append(request)
279 raise urllib2.HTTPError(
280 'url', 400, 'error message', None, StringIO.StringIO())
281
282 service = self.mocked_http_service(_url_open=mock_url_open)
283 self.assertEqual(service.request('/', data={}), None)
284 self.assertEqual(1, len(count))
285 self.assertEqual([], service.sleeps)
286
287 def test_request_HTTP_error_retry_404(self):
288 response = 'data'
289 def mock_url_open(request, **_kwargs):
290 if run_isolated.COUNT_KEY + '=1' in request.get_data():
291 return StringIO.StringIO(response)
292 raise urllib2.HTTPError(
293 'url', 404, 'error message', None, StringIO.StringIO())
294
295 service = self.mocked_http_service(_url_open=mock_url_open)
296 result = service.request('/', data={}, retry_404=True)
297 self.assertEqual(result.read(), response)
298 self.assertEqual(
299 [(0, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN)],
300 service.sleeps)
301
302 def test_request_HTTP_error_with_retry(self):
303 response = 'response'
304
305 def mock_url_open(request, **_kwargs):
306 if run_isolated.COUNT_KEY + '=1' not in request.get_data():
307 raise urllib2.HTTPError(
308 'url', 500, 'error message', None, StringIO.StringIO())
309 return StringIO.StringIO(response)
310
311 service = self.mocked_http_service(_url_open=mock_url_open)
312 self.assertTrue(service.request('/', data={}).read(), response)
313 self.assertEqual(
314 [(0, run_isolated.URL_OPEN_TIMEOUT - NOW_CALLS_PER_OPEN)],
315 service.sleeps)
316
317 def test_count_key_in_data_failure(self):
318 data = {run_isolated.COUNT_KEY: 1}
319 service = self.mocked_http_service()
320 self.assertEqual(service.request('/', data=data), None)
321 self.assertEqual([], service.sleeps)
322
323 def test_auth_success(self):
324 count = []
325 response = 'response'
326 def mock_url_open(_request, **_kwargs):
327 if not count:
328 raise urllib2.HTTPError(
329 'url', 403, 'error message', None, StringIO.StringIO())
330 return StringIO.StringIO(response)
331 def mock_authenticate():
332 self.assertEqual(len(count), 0)
333 count.append(1)
334 return True
335 service = self.mocked_http_service(_url_open=mock_url_open,
336 authenticate=mock_authenticate)
337 self.assertEqual(service.request('/').read(), response)
338 self.assertEqual(len(count), 1)
339 self.assertEqual([], service.sleeps)
340
341 def test_auth_failure(self):
342 count = []
343 def mock_url_open(_request, **_kwargs):
344 raise urllib2.HTTPError(
345 'url', 403, 'error message', None, StringIO.StringIO())
346 def mock_authenticate():
347 count.append(1)
348 return False
349 service = self.mocked_http_service(_url_open=mock_url_open,
350 authenticate=mock_authenticate)
351 self.assertEqual(service.request('/'), None)
352 self.assertEqual(len(count), 1) # single attempt only
353 self.assertEqual([], service.sleeps)
354
355 def test_request_attempted_before_auth(self):
356 calls = []
357 def mock_url_open(_request, **_kwargs):
358 calls.append('url_open')
359 raise urllib2.HTTPError(
360 'url', 403, 'error message', None, StringIO.StringIO())
361 def mock_authenticate():
362 calls.append('authenticate')
363 return False
364 service = self.mocked_http_service(_url_open=mock_url_open,
365 authenticate=mock_authenticate)
366 self.assertEqual(service.request('/'), None)
367 self.assertEqual(calls, ['url_open', 'authenticate'])
368 self.assertEqual([], service.sleeps)
369
370 def test_sleep_before_retry(self):
371 # Verifies bounds. Because it's using a pseudo-random number generator and
372 # not a read random source, it's basically guaranteed to never return the
373 # same value twice consecutively.
374 a = run_isolated.HttpService.calculate_sleep_before_retry(0, 0)
375 b = run_isolated.HttpService.calculate_sleep_before_retry(0, 0)
376 self.assertTrue(a >= math.pow(1.5, -1), a)
377 self.assertTrue(b >= math.pow(1.5, -1), b)
378 self.assertTrue(a < 1.5 + math.pow(1.5, -1), a)
379 self.assertTrue(b < 1.5 + math.pow(1.5, -1), b)
380 self.assertNotEqual(a, b)
381
382 def test_url_read(self):
383 # Successfully reads the data.
384 self.mock(run_isolated, 'url_open',
385 lambda url, **_kwargs: fake_http_response('111', url))
386 self.assertEqual(run_isolated.url_read('https://fake_url.com/test'), '111')
387
388 # Respects url_open connection errors.
389 self.mock(run_isolated, 'url_open', lambda _url, **_kwargs: None)
390 self.assertIsNone(run_isolated.url_read('https://fake_url.com/test'))
391
392 # Respects read timeout errors.
393 def timeouting_http_response(url):
394 def read_mock(_size=None):
395 raise run_isolated.TimeoutError()
396 stream = StringIO.StringIO('')
397 stream.headers = {'content-length': 0}
398 response = run_isolated.HttpResponse(stream, url)
399 response.read = read_mock
400 return response
401
402 self.mock(run_isolated, 'url_open',
403 lambda url, **_kwargs: timeouting_http_response(url))
404 self.assertIsNone(run_isolated.url_read('https://fake_url.com/test'))
405
406
407 if __name__ == '__main__': 146 if __name__ == '__main__':
408 logging.basicConfig( 147 logging.basicConfig(
409 level=(logging.DEBUG if '-v' in sys.argv else logging.FATAL)) 148 level=(logging.DEBUG if '-v' in sys.argv else logging.FATAL))
410 if '-v' in sys.argv: 149 if '-v' in sys.argv:
411 unittest.TestCase.maxDiff = None 150 unittest.TestCase.maxDiff = None
412 unittest.main() 151 unittest.main()
OLDNEW
« swarming.py ('K') | « tests/net_test.py ('k') | tests/swarming_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698