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

Unified Diff: tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/batch_test.py

Issue 1264873003: Add gsutil/third_party to telemetry/third_party/gsutilz/third_party. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove httplib2 Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/batch_test.py
diff --git a/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/batch_test.py b/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/batch_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf7736408bfb74ff86ad8349515adff7d91c9e7a
--- /dev/null
+++ b/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/batch_test.py
@@ -0,0 +1,509 @@
+"""Tests for google3.cloud.bigscience.apitools.base.py.batch."""
+
+import textwrap
+
+import mock
+from six.moves import http_client
+from six.moves.urllib import parse
+import unittest2
+
+from apitools.base.py import batch
+from apitools.base.py import exceptions
+from apitools.base.py import http_wrapper
+
+
+class FakeCredentials(object):
+
+ def __init__(self):
+ self.num_refreshes = 0
+
+ def refresh(self, _):
+ self.num_refreshes += 1
+
+
+class FakeHttp(object):
+
+ class FakeRequest(object):
+
+ def __init__(self, credentials=None):
+ if credentials is not None:
+ self.credentials = credentials
+
+ def __init__(self, credentials=None):
+ self.request = FakeHttp.FakeRequest(credentials=credentials)
+
+
+class FakeService(object):
+
+ """A service for testing."""
+
+ def GetMethodConfig(self, _):
+ return {}
+
+ def GetUploadConfig(self, _):
+ return {}
+
+ # pylint: disable=unused-argument
+ def PrepareHttpRequest(
+ self, method_config, request, global_params, upload_config):
+ return global_params['desired_request']
+ # pylint: enable=unused-argument
+
+ def ProcessHttpResponse(self, _, http_response):
+ return http_response
+
+
+class BatchTest(unittest2.TestCase):
+
+ def assertUrlEqual(self, expected_url, provided_url):
+
+ def parse_components(url):
+ parsed = parse.urlsplit(url)
+ query = parse.parse_qs(parsed.query)
+ return parsed._replace(query=''), query
+
+ expected_parse, expected_query = parse_components(expected_url)
+ provided_parse, provided_query = parse_components(provided_url)
+
+ self.assertEqual(expected_parse, provided_parse)
+ self.assertEqual(expected_query, provided_query)
+
+ def __ConfigureMock(self, mock_request, expected_request, response):
+
+ if isinstance(response, list):
+ response = list(response)
+
+ def CheckRequest(_, request, **unused_kwds):
+ self.assertUrlEqual(expected_request.url, request.url)
+ self.assertEqual(expected_request.http_method, request.http_method)
+ if isinstance(response, list):
+ return response.pop(0)
+ else:
+ return response
+
+ mock_request.side_effect = CheckRequest
+
+ def testRequestServiceUnavailable(self):
+ mock_service = FakeService()
+
+ desired_url = 'https://www.example.com'
+ batch_api_request = batch.BatchApiRequest(batch_url=desired_url,
+ retryable_codes=[])
+ # The request to be added. The actual request sent will be somewhat
+ # larger, as this is added to a batch.
+ desired_request = http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80)
+
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 419,
+ }, 'x' * 419),
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'multipart/mixed; boundary="boundary"',
+ }, textwrap.dedent("""\
+ --boundary
+ content-type: text/plain
+ content-id: <id+0>
+
+ HTTP/1.1 503 SERVICE UNAVAILABLE
+ nope
+ --boundary--"""), None))
+
+ batch_api_request.Add(
+ mock_service, 'unused', None,
+ global_params={'desired_request': desired_request})
+
+ api_request_responses = batch_api_request.Execute(
+ FakeHttp(), sleep_between_polls=0)
+
+ self.assertEqual(1, len(api_request_responses))
+
+ # Make sure we didn't retry non-retryable code 503.
+ self.assertEqual(1, mock_request.call_count)
+
+ self.assertTrue(api_request_responses[0].is_error)
+ self.assertIsNone(api_request_responses[0].response)
+ self.assertIsInstance(api_request_responses[0].exception,
+ exceptions.HttpError)
+
+ def testSingleRequestInBatch(self):
+ mock_service = FakeService()
+
+ desired_url = 'https://www.example.com'
+ batch_api_request = batch.BatchApiRequest(batch_url=desired_url)
+ # The request to be added. The actual request sent will be somewhat
+ # larger, as this is added to a batch.
+ desired_request = http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80)
+
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 419,
+ }, 'x' * 419),
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'multipart/mixed; boundary="boundary"',
+ }, textwrap.dedent("""\
+ --boundary
+ content-type: text/plain
+ content-id: <id+0>
+
+ HTTP/1.1 200 OK
+ content
+ --boundary--"""), None))
+
+ batch_api_request.Add(mock_service, 'unused', None, {
+ 'desired_request': desired_request,
+ })
+
+ api_request_responses = batch_api_request.Execute(FakeHttp())
+
+ self.assertEqual(1, len(api_request_responses))
+ self.assertEqual(1, mock_request.call_count)
+
+ self.assertFalse(api_request_responses[0].is_error)
+
+ response = api_request_responses[0].response
+ self.assertEqual({'status': '200'}, response.info)
+ self.assertEqual('content', response.content)
+ self.assertEqual(desired_url, response.request_url)
+
+ def testRefreshOnAuthFailure(self):
+ mock_service = FakeService()
+
+ desired_url = 'https://www.example.com'
+ batch_api_request = batch.BatchApiRequest(batch_url=desired_url)
+ # The request to be added. The actual request sent will be somewhat
+ # larger, as this is added to a batch.
+ desired_request = http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80)
+
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 419,
+ }, 'x' * 419), [
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'multipart/mixed; boundary="boundary"',
+ }, textwrap.dedent("""\
+ --boundary
+ content-type: text/plain
+ content-id: <id+0>
+
+ HTTP/1.1 401 UNAUTHORIZED
+ Invalid grant
+
+ --boundary--"""), None),
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'multipart/mixed; boundary="boundary"',
+ }, textwrap.dedent("""\
+ --boundary
+ content-type: text/plain
+ content-id: <id+0>
+
+ HTTP/1.1 200 OK
+ content
+ --boundary--"""), None)
+ ])
+
+ batch_api_request.Add(mock_service, 'unused', None, {
+ 'desired_request': desired_request,
+ })
+
+ credentials = FakeCredentials()
+ api_request_responses = batch_api_request.Execute(
+ FakeHttp(credentials=credentials), sleep_between_polls=0)
+
+ self.assertEqual(1, len(api_request_responses))
+ self.assertEqual(2, mock_request.call_count)
+ self.assertEqual(1, credentials.num_refreshes)
+
+ self.assertFalse(api_request_responses[0].is_error)
+
+ response = api_request_responses[0].response
+ self.assertEqual({'status': '200'}, response.info)
+ self.assertEqual('content', response.content)
+ self.assertEqual(desired_url, response.request_url)
+
+ def testNoAttempts(self):
+ desired_url = 'https://www.example.com'
+ batch_api_request = batch.BatchApiRequest(batch_url=desired_url)
+ batch_api_request.Add(FakeService(), 'unused', None, {
+ 'desired_request': http_wrapper.Request(desired_url, 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80),
+ })
+ api_request_responses = batch_api_request.Execute(None, max_retries=0)
+ self.assertEqual(1, len(api_request_responses))
+ self.assertIsNone(api_request_responses[0].response)
+ self.assertIsNone(api_request_responses[0].exception)
+
+ def _DoTestConvertIdToHeader(self, test_id, expected_result):
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertEqual(
+ expected_result % batch_request._BatchHttpRequest__base_id,
+ batch_request._ConvertIdToHeader(test_id))
+
+ def testConvertIdSimple(self):
+ self._DoTestConvertIdToHeader('blah', '<%s+blah>')
+
+ def testConvertIdThatNeedsEscaping(self):
+ self._DoTestConvertIdToHeader('~tilde1', '<%s+%%7Etilde1>')
+
+ def _DoTestConvertHeaderToId(self, header, expected_id):
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertEqual(expected_id,
+ batch_request._ConvertHeaderToId(header))
+
+ def testConvertHeaderToIdSimple(self):
+ self._DoTestConvertHeaderToId('<hello+blah>', 'blah')
+
+ def testConvertHeaderToIdWithLotsOfPlus(self):
+ self._DoTestConvertHeaderToId('<a+++++plus>', 'plus')
+
+ def _DoTestConvertInvalidHeaderToId(self, invalid_header):
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertRaises(exceptions.BatchError,
+ batch_request._ConvertHeaderToId, invalid_header)
+
+ def testHeaderWithoutAngleBrackets(self):
+ self._DoTestConvertInvalidHeaderToId('1+1')
+
+ def testHeaderWithoutPlus(self):
+ self._DoTestConvertInvalidHeaderToId('<HEADER>')
+
+ def testSerializeRequest(self):
+ request = http_wrapper.Request(body='Hello World', headers={
+ 'content-type': 'protocol/version',
+ })
+ expected_serialized_request = '\n'.join([
+ 'GET HTTP/1.1',
+ 'Content-Type: protocol/version',
+ 'MIME-Version: 1.0',
+ 'content-length: 11',
+ 'Host: ',
+ '',
+ 'Hello World',
+ ])
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertEqual(expected_serialized_request,
+ batch_request._SerializeRequest(request))
+
+ def testSerializeRequestPreservesHeaders(self):
+ # Now confirm that if an additional, arbitrary header is added
+ # that it is successfully serialized to the request. Merely
+ # check that it is included, because the order of the headers
+ # in the request is arbitrary.
+ request = http_wrapper.Request(body='Hello World', headers={
+ 'content-type': 'protocol/version',
+ 'key': 'value',
+ })
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertTrue(
+ 'key: value\n' in batch_request._SerializeRequest(request))
+
+ def testSerializeRequestNoBody(self):
+ request = http_wrapper.Request(body=None, headers={
+ 'content-type': 'protocol/version',
+ })
+ expected_serialized_request = '\n'.join([
+ 'GET HTTP/1.1',
+ 'Content-Type: protocol/version',
+ 'MIME-Version: 1.0',
+ 'Host: ',
+ ])
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ self.assertEqual(expected_serialized_request,
+ batch_request._SerializeRequest(request))
+
+ def testDeserializeRequest(self):
+ serialized_payload = '\n'.join([
+ 'GET HTTP/1.1',
+ 'Content-Type: protocol/version',
+ 'MIME-Version: 1.0',
+ 'content-length: 11',
+ 'key: value',
+ 'Host: ',
+ '',
+ 'Hello World',
+ ])
+ example_url = 'https://www.example.com'
+ expected_response = http_wrapper.Response({
+ 'content-length': str(len('Hello World')),
+ 'Content-Type': 'protocol/version',
+ 'key': 'value',
+ 'MIME-Version': '1.0',
+ 'status': '',
+ 'Host': ''
+ }, 'Hello World', example_url)
+
+ batch_request = batch.BatchHttpRequest(example_url)
+ self.assertEqual(
+ expected_response,
+ batch_request._DeserializeResponse(serialized_payload))
+
+ def testNewId(self):
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+
+ for i in range(100):
+ self.assertEqual(str(i), batch_request._NewId())
+
+ def testAdd(self):
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+
+ for x in range(100):
+ batch_request.Add(http_wrapper.Request(body=str(x)))
+
+ for key in batch_request._BatchHttpRequest__request_response_handlers:
+ value = batch_request._BatchHttpRequest__request_response_handlers[
+ key]
+ self.assertEqual(key, value.request.body)
+ self.assertFalse(value.request.url)
+ self.assertEqual('GET', value.request.http_method)
+ self.assertIsNone(value.response)
+ self.assertIsNone(value.handler)
+
+ def testInternalExecuteWithFailedRequest(self):
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request('https://www.example.com', 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80),
+ http_wrapper.Response({'status': '300'}, None, None))
+
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+
+ self.assertRaises(
+ exceptions.HttpError, batch_request._Execute, None)
+
+ def testInternalExecuteWithNonMultipartResponse(self):
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request('https://www.example.com', 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 80,
+ }, 'x' * 80),
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'blah/blah'
+ }, '', None))
+
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+
+ self.assertRaises(
+ exceptions.BatchError, batch_request._Execute, None)
+
+ def testInternalExecute(self):
+ with mock.patch.object(http_wrapper, 'MakeRequest',
+ autospec=True) as mock_request:
+ self.__ConfigureMock(
+ mock_request,
+ http_wrapper.Request('https://www.example.com', 'POST', {
+ 'content-type': 'multipart/mixed; boundary="None"',
+ 'content-length': 583,
+ }, 'x' * 583),
+ http_wrapper.Response({
+ 'status': '200',
+ 'content-type': 'multipart/mixed; boundary="boundary"',
+ }, textwrap.dedent("""\
+ --boundary
+ content-type: text/plain
+ content-id: <id+2>
+
+ HTTP/1.1 200 OK
+ Second response
+
+ --boundary
+ content-type: text/plain
+ content-id: <id+1>
+
+ HTTP/1.1 401 UNAUTHORIZED
+ First response
+
+ --boundary--"""), None))
+
+ test_requests = {
+ '1': batch.RequestResponseAndHandler(
+ http_wrapper.Request(body='first'), None, None),
+ '2': batch.RequestResponseAndHandler(
+ http_wrapper.Request(body='second'), None, None),
+ }
+
+ batch_request = batch.BatchHttpRequest('https://www.example.com')
+ batch_request._BatchHttpRequest__request_response_handlers = (
+ test_requests)
+
+ batch_request._Execute(FakeHttp())
+
+ test_responses = (
+ batch_request._BatchHttpRequest__request_response_handlers)
+
+ self.assertEqual(http_client.UNAUTHORIZED,
+ test_responses['1'].response.status_code)
+ self.assertEqual(http_client.OK,
+ test_responses['2'].response.status_code)
+
+ self.assertIn(
+ 'First response', test_responses['1'].response.content)
+ self.assertIn(
+ 'Second response', test_responses['2'].response.content)
+
+ def testPublicExecute(self):
+
+ def LocalCallback(response, exception):
+ self.assertEqual({'status': '418'}, response.info)
+ self.assertEqual('Teapot', response.content)
+ self.assertIsNone(response.request_url)
+ self.assertIsInstance(exception, exceptions.HttpError)
+
+ global_callback = mock.Mock()
+ batch_request = batch.BatchHttpRequest(
+ 'https://www.example.com', global_callback)
+
+ with mock.patch.object(batch.BatchHttpRequest, '_Execute',
+ autospec=True) as mock_execute:
+ mock_execute.return_value = None
+
+ test_requests = {
+ '0': batch.RequestResponseAndHandler(
+ None,
+ http_wrapper.Response({'status': '200'}, 'Hello!', None),
+ None),
+ '1': batch.RequestResponseAndHandler(
+ None,
+ http_wrapper.Response({'status': '418'}, 'Teapot', None),
+ LocalCallback),
+ }
+
+ batch_request._BatchHttpRequest__request_response_handlers = (
+ test_requests)
+ batch_request.Execute(None)
+
+ # Global callback was called once per handler.
+ self.assertEqual(len(test_requests), global_callback.call_count)

Powered by Google App Engine
This is Rietveld 408576698