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

Side by Side Diff: infra_libs/test/httplib2_utils_test.py

Issue 2213143002: Add infra_libs as a bootstrap dependency. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Removed the ugly import hack 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 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import os
6 import socket
7 import time
8 import unittest
9
10 import infra_libs
11 from infra_libs.ts_mon.common import http_metrics
12 from infra_libs import httplib2_utils
13 from infra_libs import ts_mon
14
15 import httplib2
16 import mock
17 import oauth2client.client
18
19
20 DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data')
21
22
23 class LoadJsonCredentialsTest(unittest.TestCase):
24 # Everything's good, should not raise any exceptions.
25 def test_valid_credentials(self):
26 creds = httplib2_utils.load_service_account_credentials(
27 'valid_creds.json',
28 service_accounts_creds_root=DATA_DIR)
29 self.assertIsInstance(creds, dict)
30 self.assertIn('type', creds)
31 self.assertIn('client_email', creds)
32 self.assertIn('private_key', creds)
33
34 # File exists but issue with the content: raises AuthError.
35 def test_missing_type(self):
36 with self.assertRaises(infra_libs.AuthError):
37 httplib2_utils.load_service_account_credentials(
38 'creds_missing_type.json',
39 service_accounts_creds_root=DATA_DIR)
40
41 def test_wrong_type(self):
42 with self.assertRaises(infra_libs.AuthError):
43 httplib2_utils.load_service_account_credentials(
44 'creds_wrong_type.json',
45 service_accounts_creds_root=DATA_DIR)
46
47 def test_missing_client_email(self):
48 with self.assertRaises(infra_libs.AuthError):
49 httplib2_utils.load_service_account_credentials(
50 'creds_missing_client_email.json',
51 service_accounts_creds_root=DATA_DIR)
52
53 def test_missing_private_key(self):
54 with self.assertRaises(infra_libs.AuthError):
55 httplib2_utils.load_service_account_credentials(
56 'creds_missing_private_key.json',
57 service_accounts_creds_root=DATA_DIR)
58
59 def test_malformed(self):
60 with self.assertRaises(infra_libs.AuthError):
61 httplib2_utils.load_service_account_credentials(
62 'creds_malformed.json',
63 service_accounts_creds_root=DATA_DIR)
64
65 # Problem with the file itself
66 def test_file_not_found(self):
67 with self.assertRaises(IOError):
68 httplib2_utils.load_service_account_credentials(
69 'this_file_should_not_exist.json',
70 service_accounts_creds_root=DATA_DIR)
71
72
73 class GetSignedJwtAssertionCredentialsTest(unittest.TestCase):
74 def test_valid_credentials(self):
75 creds = infra_libs.get_signed_jwt_assertion_credentials(
76 'valid_creds.json',
77 service_accounts_creds_root=DATA_DIR)
78 self.assertIsInstance(creds,
79 oauth2client.client.SignedJwtAssertionCredentials)
80 # A default scope must be provided, we don't care which one
81 self.assertTrue(creds.scope)
82
83 def test_valid_credentials_with_scope_as_string(self):
84 creds = infra_libs.get_signed_jwt_assertion_credentials(
85 'valid_creds.json',
86 scope='repo',
87 service_accounts_creds_root=DATA_DIR)
88 self.assertIsInstance(creds,
89 oauth2client.client.SignedJwtAssertionCredentials)
90 self.assertIn('repo', creds.scope)
91
92 def test_valid_credentials_with_scope_as_list(self):
93 creds = infra_libs.get_signed_jwt_assertion_credentials(
94 'valid_creds.json',
95 scope=['gist'],
96 service_accounts_creds_root=DATA_DIR)
97 self.assertIsInstance(creds,
98 oauth2client.client.SignedJwtAssertionCredentials)
99 self.assertIn('gist', creds.scope)
100
101 # Only test one malformed case and rely on LoadJsonCredentialsTest
102 # for the other cases.
103 def test_malformed_credentials(self):
104 with self.assertRaises(infra_libs.AuthError):
105 infra_libs.get_signed_jwt_assertion_credentials(
106 'creds_malformed.json',
107 service_accounts_creds_root=DATA_DIR)
108
109
110 class GetAuthenticatedHttp(unittest.TestCase):
111 def test_valid_credentials(self):
112 http = infra_libs.get_authenticated_http(
113 'valid_creds.json',
114 service_accounts_creds_root=DATA_DIR)
115 self.assertIsInstance(http, httplib2.Http)
116
117 def test_valid_credentials_authenticated(self):
118 http = infra_libs.get_authenticated_http(
119 'valid_creds.json',
120 service_accounts_creds_root=DATA_DIR,
121 http_identifier='test_case')
122 self.assertIsInstance(http, infra_libs.InstrumentedHttp)
123
124 # Only test one malformed case and rely on LoadJsonCredentialsTest
125 # for the other cases.
126 def test_malformed_credentials(self):
127 with self.assertRaises(infra_libs.AuthError):
128 infra_libs.get_authenticated_http(
129 'creds_malformed.json',
130 service_accounts_creds_root=DATA_DIR)
131
132 class RetriableHttplib2Test(unittest.TestCase):
133 def setUp(self):
134 super(RetriableHttplib2Test, self).setUp()
135 self.http = infra_libs.RetriableHttp(httplib2.Http())
136 self.http._http.request = mock.create_autospec(self.http._http.request,
137 spec_set=True)
138
139 _MOCK_REQUEST = mock.call('http://foo/', 'GET', None)
140
141 def test_authorize(self):
142 http = infra_libs.RetriableHttp(httplib2.Http())
143 creds = infra_libs.get_signed_jwt_assertion_credentials(
144 'valid_creds.json',
145 service_accounts_creds_root=DATA_DIR)
146 creds.authorize(http)
147
148 def test_delegate_get_attr(self):
149 """RetriableHttp should delegate getting attribute except request() to
150 Http"""
151 self.http._http.clear_credentials = mock.create_autospec(
152 self.http._http.clear_credentials, spec_set=True)
153 self.http.clear_credentials()
154 self.http._http.clear_credentials.assert_called_once_with()
155
156 def test_delegate_set_attr(self):
157 """RetriableHttp should delegate setting attributes to Http"""
158 self.http.ignore_etag = False
159 self.assertFalse(self.http.ignore_etag)
160 self.assertFalse(self.http._http.ignore_etag)
161 self.http.ignore_etag = True
162 self.assertTrue(self.http.ignore_etag)
163 self.assertTrue(self.http._http.ignore_etag)
164
165 @mock.patch('time.sleep', autospec=True)
166 def test_succeed(self, _sleep):
167 self.http._http.request.return_value = (
168 httplib2.Response({'status': 400}), 'content')
169 response, _ = self.http.request('http://foo/')
170 self.assertEqual(400, response.status)
171 self.http._http.request.assert_has_calls([ self._MOCK_REQUEST ])
172
173 @mock.patch('time.sleep', autospec=True)
174 def test_retry_succeed(self, _sleep):
175 self.http._http.request.side_effect = iter([
176 (httplib2.Response({'status': 500}), 'content'),
177 httplib2.HttpLib2Error,
178 (httplib2.Response({'status': 200}), 'content')
179 ])
180 response, _ = self.http.request('http://foo/')
181 self.assertEqual(200, response.status)
182 self.http._http.request.assert_has_calls([ self._MOCK_REQUEST ] * 3)
183
184 @mock.patch('time.sleep', autospec=True)
185 def test_fail_exception(self, _sleep):
186 self.http._http.request.side_effect = httplib2.HttpLib2Error()
187 self.assertRaises(httplib2.HttpLib2Error, self.http.request, 'http://foo/')
188 self.http._http.request.assert_has_calls([ self._MOCK_REQUEST ] * 5)
189
190 @mock.patch('time.sleep', autospec=True)
191 def test_fail_status_code(self, _sleep):
192 self.http._http.request.return_value = (
193 httplib2.Response({'status': 500}), 'content')
194 response, _ = self.http.request('http://foo/')
195 self.assertEqual(500, response.status)
196 self.http._http.request.assert_has_calls([ self._MOCK_REQUEST ] * 5)
197
198
199 class InstrumentedHttplib2Test(unittest.TestCase):
200 def setUp(self):
201 super(InstrumentedHttplib2Test, self).setUp()
202 self.mock_time = mock.create_autospec(time.time, spec_set=True)
203 self.mock_time.return_value = 42
204 self.http = infra_libs.InstrumentedHttp('test', time_fn=self.mock_time)
205 self.http._request = mock.Mock()
206 ts_mon.reset_for_unittest()
207
208 def test_success_status(self):
209 self.http._request.return_value = (
210 httplib2.Response({'status': 200}),
211 'content')
212
213 response, _ = self.http.request('http://foo/')
214 self.assertEqual(200, response.status)
215 self.assertEqual(1, http_metrics.response_status.get(
216 {'name': 'test', 'client': 'httplib2', 'status': 200}))
217 self.assertIsNone(http_metrics.response_status.get(
218 {'name': 'test', 'client': 'httplib2', 'status': 404}))
219
220 def test_error_status(self):
221 self.http._request.return_value = (
222 httplib2.Response({'status': 404}),
223 'content')
224
225 response, _ = self.http.request('http://foo/')
226 self.assertEqual(404, response.status)
227 self.assertIsNone(http_metrics.response_status.get(
228 {'name': 'test', 'client': 'httplib2', 'status': 200}))
229 self.assertEqual(1, http_metrics.response_status.get(
230 {'name': 'test', 'client': 'httplib2', 'status': 404}))
231
232 def test_timeout(self):
233 self.http._request.side_effect = socket.timeout
234
235 with self.assertRaises(socket.timeout):
236 self.http.request('http://foo/')
237 self.assertIsNone(http_metrics.response_status.get(
238 {'name': 'test', 'client': 'httplib2', 'status': 200}))
239 self.assertEqual(1, http_metrics.response_status.get(
240 {'name': 'test', 'client': 'httplib2',
241 'status': http_metrics.STATUS_TIMEOUT}))
242
243 def test_connection_error(self):
244 self.http._request.side_effect = socket.error
245
246 with self.assertRaises(socket.error):
247 self.http.request('http://foo/')
248 self.assertIsNone(http_metrics.response_status.get(
249 {'name': 'test', 'client': 'httplib2', 'status': 200}))
250 self.assertEqual(1, http_metrics.response_status.get(
251 {'name': 'test', 'client': 'httplib2',
252 'status': http_metrics.STATUS_ERROR}))
253
254 def test_exception(self):
255 self.http._request.side_effect = httplib2.HttpLib2Error
256
257 with self.assertRaises(httplib2.HttpLib2Error):
258 self.http.request('http://foo/')
259 self.assertIsNone(http_metrics.response_status.get(
260 {'name': 'test', 'client': 'httplib2', 'status': 200}))
261 self.assertEqual(1, http_metrics.response_status.get(
262 {'name': 'test', 'client': 'httplib2',
263 'status': http_metrics.STATUS_EXCEPTION}))
264
265 def test_response_bytes(self):
266 self.http._request.return_value = (
267 httplib2.Response({'status': 200}),
268 'content')
269
270 _, content = self.http.request('http://foo/')
271 self.assertEqual('content', content)
272 self.assertEqual(1, http_metrics.response_bytes.get(
273 {'name': 'test', 'client': 'httplib2'}).count)
274 self.assertEqual(7, http_metrics.response_bytes.get(
275 {'name': 'test', 'client': 'httplib2'}).sum)
276
277 def test_request_bytes(self):
278 self.http._request.return_value = (
279 httplib2.Response({'status': 200}),
280 'content')
281
282 _, content = self.http.request('http://foo/', body='wibblewibble')
283 self.assertEqual('content', content)
284 self.assertEqual(1, http_metrics.request_bytes.get(
285 {'name': 'test', 'client': 'httplib2'}).count)
286 self.assertEqual(12, http_metrics.request_bytes.get(
287 {'name': 'test', 'client': 'httplib2'}).sum)
288
289 def test_duration(self):
290 current_time = [4.2]
291
292 def time_side_effect():
293 ret = current_time[0]
294 current_time[0] += 0.3
295 return ret
296 self.mock_time.side_effect = time_side_effect
297
298 self.http._request.return_value = (
299 httplib2.Response({'status': 200}),
300 'content')
301
302 _, _ = self.http.request('http://foo/')
303 self.assertEqual(1, http_metrics.durations.get(
304 {'name': 'test', 'client': 'httplib2'}).count)
305 self.assertAlmostEqual(300, http_metrics.durations.get(
306 {'name': 'test', 'client': 'httplib2'}).sum)
307
308
309 class HttpMockTest(unittest.TestCase):
310 def test_empty(self):
311 http = infra_libs.HttpMock([])
312 with self.assertRaises(AssertionError):
313 http.request('https://www.google.com', 'GET')
314
315 def test_invalid_parameter(self):
316 with self.assertRaises(TypeError):
317 infra_libs.HttpMock(None)
318
319 def test_uris_wrong_length(self):
320 with self.assertRaises(ValueError):
321 infra_libs.HttpMock([(1, 2)])
322
323 def test_uris_wrong_type(self):
324 with self.assertRaises(ValueError):
325 infra_libs.HttpMock([(None,)])
326
327 def test_invalid_uri(self):
328 with self.assertRaises(TypeError):
329 infra_libs.HttpMock([(1, {'status': '100'}, None)])
330
331 def test_invalid_headers(self):
332 with self.assertRaises(TypeError):
333 infra_libs.HttpMock([('https://www.google.com', None, None)])
334
335 def test_headers_without_status(self):
336 with self.assertRaises(ValueError):
337 infra_libs.HttpMock([('https://www.google.com', {'foo': 'bar'}, None)])
338
339 def test_invalid_body(self):
340 with self.assertRaises(TypeError):
341 infra_libs.HttpMock([('https://www.google.com', {'status': '200'}, 42)])
342
343 def test_one_uri(self):
344 http = infra_libs.HttpMock([('https://www.google.com',
345 {'status': '403'},
346 'bar')])
347 response, body = http.request('https://www.google.com', 'GET')
348 self.assertIsInstance(response, httplib2.Response)
349 self.assertEqual(response.status, 403)
350 self.assertEqual(body, 'bar')
351
352 def test_two_uris(self):
353 http = infra_libs.HttpMock([('https://www.google.com',
354 {'status': 200}, 'foo'),
355 ('.*', {'status': 404}, '')])
356 response, body = http.request('https://mywebserver.woo.hoo', 'GET')
357 self.assertIsInstance(response, httplib2.Response)
358 self.assertEqual(response.status, 404)
359 self.assertEqual(body, '')
360
361 self.assertEqual(http.requests_made[0].uri, 'https://mywebserver.woo.hoo')
362 self.assertEqual(http.requests_made[0].method, 'GET')
363 self.assertEqual(http.requests_made[0].body, None)
364 self.assertEqual(http.requests_made[0].headers, None)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698