def test_media_io_base_next_chunk_no_retry_403_not_configured(self): fd = BytesIO(b"i am png") upload = MediaIoBaseUpload( fd=fd, mimetype='image/png', chunksize=500, resumable=True) http = HttpMockSequence([ ({'status': '403'}, NOT_CONFIGURED_RESPONSE), ({'status': '200'}, '{}') ]) model = JsonModel() uri = u'https://www.googleapis.com/someapi/v1/upload/?foo=bar' method = u'POST' request = HttpRequest( http, model.response, uri, method=method, headers={}, resumable=upload) request._rand = lambda: 1.0 request._sleep = mock.MagicMock() with self.assertRaises(HttpError): request.execute(num_retries=3) request._sleep.assert_not_called()
def test_retry(self): num_retries = 5 resp_seq = [({'status': '500'}, '')] * (num_retries - 3) resp_seq.append(({'status': '403'}, RATE_LIMIT_EXCEEDED_RESPONSE)) resp_seq.append(({'status': '403'}, USER_RATE_LIMIT_EXCEEDED_RESPONSE)) resp_seq.append(({'status': '429'}, '')) resp_seq.append(({'status': '200'}, '{}')) http = HttpMockSequence(resp_seq) model = JsonModel() uri = u'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = u'POST' request = HttpRequest(http, model.response, uri, method=method, body=u'{}', headers={'content-type': 'application/json'}) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=num_retries) self.assertEqual(num_retries, len(sleeptimes)) for retry_num in range(num_retries): self.assertEqual(10 * 2**(retry_num + 1), sleeptimes[retry_num])
def test_no_retry_fails_fast(self): http = HttpMockSequence([({ 'status': '500' }, ''), ({ 'status': '200' }, '{}')]) model = JsonModel() uri = u'https://www.googleapis.com/someapi/v1/collection/?foo=bar' method = u'POST' request = HttpRequest(http, model.response, uri, method=method, body=u'{}', headers={'content-type': 'application/json'}) request._rand = lambda: 1.0 request._sleep = lambda _: self.fail( 'sleep should not have been called.') try: request.execute() self.fail('Should have raised an exception.') except HttpError: pass
def test_media_io_base_next_chunk_retries(self): try: import io except ImportError: return f = open(datafile('small.png'), 'r') fd = io.BytesIO(f.read()) upload = MediaIoBaseUpload(fd=fd, mimetype='image/png', chunksize=500, resumable=True) # Simulate 5XXs for both the request that creates the resumable upload and # the upload itself. http = HttpMockSequence([ ({ 'status': '500' }, ''), ({ 'status': '500' }, ''), ({ 'status': '503' }, ''), ({ 'status': '200', 'location': 'location' }, ''), ({ 'status': '500' }, ''), ({ 'status': '500' }, ''), ({ 'status': '503' }, ''), ({ 'status': '200' }, '{}'), ]) model = JsonModel() uri = u'https://www.googleapis.com/someapi/v1/upload/?foo=bar' method = u'POST' request = HttpRequest(http, model.response, uri, method=method, headers={}, resumable=upload) sleeptimes = [] request._sleep = lambda x: sleeptimes.append(x) request._rand = lambda: 10 request.execute(num_retries=3) self.assertEqual([20, 40, 80, 20, 40, 80], sleeptimes)
def test_good_response_wo_data(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({"status": "200"}) resp.reason = "OK" content = '{"foo": "is good"}' content = model.response(resp, content) self.assertEqual(content, {"foo": "is good"})
def test_no_content_response(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({"status": "204"}) resp.reason = "No Content" content = "" content = model.response(resp, content) self.assertEqual(content, {})
def test_no_content_response(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({'status': '204'}) resp.reason = 'No Content' content = '' content = model.response(resp, content) self.assertEqual(content, {})
def test_good_response_wo_data_str(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({'status': '200'}) resp.reason = 'OK' content = '"data goes here"' content = model.response(resp, content) self.assertEqual(content, 'data goes here')
def test_good_response_wo_data(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({'status': '200'}) resp.reason = 'OK' content = '{"foo": "is good"}' content = model.response(resp, content) self.assertEqual(content, {'foo': 'is good'})
def test_good_response(self): model = JsonModel(data_wrapper=True) resp = httplib2.Response({'status': '200'}) resp.reason = 'OK' content = '{"data": "is good"}' content = model.response(resp, content) self.assertEqual(content, 'is good')
def test_good_response_wo_data_str(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({"status": "200"}) resp.reason = "OK" content = '"data goes here"' content = model.response(resp, content) self.assertEqual(content, "data goes here")
def get(self, project, snapshot): if snapshot == valid_snapshot_name: http = HttpMock('tests/data/gcp/snapshots.get.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={}) elif snapshot == not_found_snapshot_name: http = HttpMock('tests/data/gcp/snapshots.get.notfound.json', {'status': '404'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={}) elif snapshot == invalid_snapshot_name: http = HttpMock('tests/data/gcp/snapshots.get.forbidden.json', {'status': '403'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={}) if snapshot == delete_snapshot_name: http = HttpMock('tests/data/gcp/snapshots.get.notfound.json', {'status': '404'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={})
def test_no_data_wrapper_deserialize_raise_type_error(self): buffer = io.StringIO() buffer.write('String buffer') model = JsonModel(data_wrapper=False) resp = httplib2.Response({"status": "500"}) resp.reason = "The JSON object must be str, bytes or bytearray, not StringIO" content = buffer with self.assertRaises(TypeError): model.response(resp, content)
def test_retry_connection_errors_non_resumable(self): model = JsonModel() request = HttpRequest( HttpMockWithErrors(3, {'status': '200'}, '{"foo": "bar"}'), model.response, u'https://www.example.com/json_api_endpoint') request._sleep = lambda _x: 0 # do nothing request._rand = lambda: 10 response = request.execute(num_retries=3) self.assertEqual({u'foo': u'bar'}, response)
def test_error_response(self): http = HttpMock(datafile('bad_request.json'), {'status': '400'}) model = JsonModel() request = HttpRequest( http, model.response, 'https://www.googleapis.com/someapi/v1/collection/?foo=bar', method='GET', headers={}) self.assertRaises(HttpError, request.execute)
def test_no_retry_connection_errors(self): model = JsonModel() request = HttpRequest( HttpMockWithNonRetriableErrors(1, {'status': '200'}, '{"foo": "bar"}'), model.response, u'https://www.example.com/json_api_endpoint') request._sleep = lambda _x: 0 # do nothing request._rand = lambda: 10 with self.assertRaises(socket.error): response = request.execute(num_retries=3)
def get(self, project, zone, operation): if operation == valid_operation_id: http = HttpMock( 'tests/data/gcp/zoneOperations.get.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest( http, model.response, uri, method=method, headers={} ) elif operation == pending_operation_id: http = HttpMock( 'tests/data/gcp/zoneOperations.get.running.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest( http, model.response, uri, method=method, headers={} ) elif operation == error_operation_id: http = HttpMock( 'tests/data/gcp/zoneOperations.get.error.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest( http, model.response, uri, method=method, headers={} ) else: return None
def aggregatedList(self, project, filter=None): http = HttpMock('tests/data/gcp/instances.aggregatedList.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={})
def test_bad_response(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({'status': '401'}) resp.reason = 'Unauthorized' content = '{"error": {"message": "not authorized"}}' try: content = model.response(resp, content) self.fail('Should have thrown an exception') except HttpError, e: self.assertTrue('not authorized' in str(e))
def delete(self, project, zone, disk): if disk == delete_disk_name or disk == valid_disk_name: http = HttpMock('tests/data/gcp/disks.delete.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'DELETE' return HttpRequest(http, model.response, uri, method=method, headers={})
def delete(self, project, snapshot): if snapshot == delete_snapshot_name or snapshot == valid_snapshot_name: http = HttpMock('tests/data/gcp/snapshots.delete.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'DELETE' return HttpRequest(http, model.response, uri, method=method, headers={})
def test_user_agent(self): model = JsonModel(data_wrapper=False) headers = {"user-agent": "my-test-app/1.23.4"} path_params = {} query_params = {} body = {} headers, unused_params, unused_query, body = model.request( headers, path_params, query_params, body) self.assertEqual(headers["user-agent"], "my-test-app/1.23.4 (gzip)")
def detachDisk(self, project, zone, instance, deviceName): if instance == valid_vm_id: http = HttpMock('tests/data/gcp/instances.detachDisk.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'POST' return HttpRequest(http, model.response, uri, method=method, headers={})
def build_from_document(service, base=None, future=None, http=None, developerKey=None, model=None, requestBuilder=HttpRequest): """Create a Resource for interacting with an API. Same as `build()`, but constructs the Resource object from a discovery document that is it given, as opposed to retrieving one over HTTP. Args: service: string or object, the JSON discovery document describing the API. The value passed in may either be the JSON string or the deserialized JSON. base: string, base URI for all HTTP requests, usually the discovery URI. This parameter is no longer used as rootUrl and servicePath are included within the discovery document. (deprecated) future: string, discovery document with future capabilities (deprecated). http: httplib2.Http, An instance of httplib2.Http or something that acts like it that HTTP requests will be made through. developerKey: string, Key for controlling API usage, generated from the API Console. model: Model class instance that serializes and de-serializes requests and responses. requestBuilder: Takes an http request and packages it up to be executed. Returns: A Resource object with methods for interacting with the service. """ # future is no longer used. future = {} if isinstance(service, basestring): service = simplejson.loads(service) base = urlparse.urljoin(service['rootUrl'], service['servicePath']) schema = Schemas(service) if model is None: features = service.get('features', []) model = JsonModel('dataWrapper' in features) return Resource(http=http, baseUrl=base, model=model, developerKey=developerKey, requestBuilder=requestBuilder, resourceDesc=service, rootDesc=service, schema=schema)
def createSnapshot(self, project, zone, disk, body): if disk == valid_disk_name: http = HttpMock('tests/data/gcp/disks.createSnapshot.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'POST' return HttpRequest(http, model.response, uri, method=method, headers={}) elif disk == invalid_disk_name: http = HttpMock('tests/data/gcp/disks.createSnapshot1.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'POST' return HttpRequest(http, model.response, uri, method=method, headers={})
def get(self, project, zone, instance): if instance == valid_vm_id: http = HttpMock('tests/data/gcp/instances.get.json', {'status': '200'}) model = JsonModel() uri = 'some_uri' method = 'GET' return HttpRequest(http, model.response, uri, method=method, headers={}) else: return None
def test_logging(self): class MockLogging(object): def __init__(self): self.info_record = [] self.debug_record = [] def info(self, message, *args): self.info_record.append(message % args) def debug(self, message, *args): self.debug_record.append(message % args) class MockResponse(dict): def __init__(self, items): super(MockResponse, self).__init__() self.status = items["status"] for key, value in six.iteritems(items): self[key] = value old_logging = googleapiclient.model.LOGGER googleapiclient.model.LOGGER = MockLogging() googleapiclient.model.dump_request_response = True model = JsonModel() request_body = {"field1": "value1", "field2": "value2"} body_string = model.request({}, {}, {}, request_body)[-1] json_body = json.loads(body_string) self.assertEqual(request_body, json_body) response = { "status": 200, "response_field_1": "response_value_1", "response_field_2": "response_value_2", } response_body = model.response(MockResponse(response), body_string) self.assertEqual(request_body, response_body) self.assertEqual( googleapiclient.model.LOGGER.info_record[:2], ["--request-start--", "-headers-start-"], ) self.assertTrue("response_field_1: response_value_1" in googleapiclient.model.LOGGER.info_record) self.assertTrue("response_field_2: response_value_2" in googleapiclient.model.LOGGER.info_record) self.assertEqual( json.loads(googleapiclient.model.LOGGER.info_record[-2]), request_body) self.assertEqual(googleapiclient.model.LOGGER.info_record[-1], "--response-end--") googleapiclient.model.LOGGER = old_logging
def test_json_body_data_wrapper(self): model = JsonModel(data_wrapper=True) headers = {} path_params = {} query_params = {} body = {} headers, unused_params, query, body = model.request( headers, path_params, query_params, body) self.assertEqual(headers["accept"], "application/json") self.assertEqual(headers["content-type"], "application/json") self.assertNotEqual(query, "") self.assertEqual(body, '{"data": {}}')
def test_json_no_body(self): model = JsonModel(data_wrapper=False) headers = {} path_params = {} query_params = {} body = None headers, unused_params, query, body = model.request( headers, path_params, query_params, body) self.assertEqual(headers["accept"], "application/json") self.assertTrue("content-type" not in headers) self.assertNotEqual(query, "") self.assertEqual(body, None)
def test_json_body(self): model = JsonModel(data_wrapper=False) headers = {} path_params = {} query_params = {} body = {} headers, unused_params, query, body = model.request( headers, path_params, query_params, body) self.assertEqual(headers['accept'], 'application/json') self.assertEqual(headers['content-type'], 'application/json') self.assertNotEqual(query, '') self.assertEqual(body, '{}')