# Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import json import socket import httplib2 import pytest import requests from requests import models from googleapiclient import errors from firebase_admin import exceptions from firebase_admin import _utils _NOT_FOUND_ERROR_DICT = { 'status': 'NOT_FOUND', 'message': 'test error' } _NOT_FOUND_PAYLOAD = json.dumps({ 'error': _NOT_FOUND_ERROR_DICT, }) class TestRequests: def test_timeout_error(self): error = requests.exceptions.Timeout('Test error') firebase_error = _utils.handle_requests_error(error) assert isinstance(firebase_error, exceptions.DeadlineExceededError) assert str(firebase_error) == 'Timed out while making an API call: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_requests_connection_error(self): error = requests.exceptions.ConnectionError('Test error') firebase_error = _utils.handle_requests_error(error) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == 'Failed to establish a connection: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_unknown_transport_error(self): error = requests.exceptions.RequestException('Test error') firebase_error = _utils.handle_requests_error(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == 'Unknown error while making a remote service call: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_http_response(self): resp, error = self._create_response() firebase_error = _utils.handle_requests_error(error) assert isinstance(firebase_error, exceptions.InternalError) assert str(firebase_error) == 'Test error' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_http_response_with_unknown_status(self): resp, error = self._create_response(status=501) firebase_error = _utils.handle_requests_error(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == 'Test error' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_http_response_with_message(self): resp, error = self._create_response() firebase_error = _utils.handle_requests_error(error, message='Explicit error message') assert isinstance(firebase_error, exceptions.InternalError) assert str(firebase_error) == 'Explicit error message' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_http_response_with_code(self): resp, error = self._create_response() firebase_error = _utils.handle_requests_error(error, code=exceptions.UNAVAILABLE) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == 'Test error' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_http_response_with_message_and_code(self): resp, error = self._create_response() firebase_error = _utils.handle_requests_error( error, message='Explicit error message', code=exceptions.UNAVAILABLE) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == 'Explicit error message' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_handle_platform_error(self): resp, error = self._create_response(payload=_NOT_FOUND_PAYLOAD) firebase_error = _utils.handle_platform_error_from_requests(error) assert isinstance(firebase_error, exceptions.NotFoundError) assert str(firebase_error) == 'test error' assert firebase_error.cause is error assert firebase_error.http_response is resp def test_handle_platform_error_with_no_response(self): error = requests.exceptions.RequestException('Test error') firebase_error = _utils.handle_platform_error_from_requests(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == 'Unknown error while making a remote service call: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_handle_platform_error_with_no_error_code(self): resp, error = self._create_response(payload='no error code') firebase_error = _utils.handle_platform_error_from_requests(error) assert isinstance(firebase_error, exceptions.InternalError) message = 'Unexpected HTTP response with status: 500; body: no error code' assert str(firebase_error) == message assert firebase_error.cause is error assert firebase_error.http_response is resp def test_handle_platform_error_with_custom_handler(self): resp, error = self._create_response(payload=_NOT_FOUND_PAYLOAD) invocations = [] def _custom_handler(cause, message, error_dict): invocations.append((cause, message, error_dict)) return exceptions.InvalidArgumentError('Custom message', cause, cause.response) firebase_error = _utils.handle_platform_error_from_requests(error, _custom_handler) assert isinstance(firebase_error, exceptions.InvalidArgumentError) assert str(firebase_error) == 'Custom message' assert firebase_error.cause is error assert firebase_error.http_response is resp assert len(invocations) == 1 args = invocations[0] assert len(args) == 3 assert args[0] is error assert args[1] == 'test error' assert args[2] == _NOT_FOUND_ERROR_DICT def test_handle_platform_error_with_custom_handler_ignore(self): resp, error = self._create_response(payload=_NOT_FOUND_PAYLOAD) invocations = [] def _custom_handler(cause, message, error_dict): invocations.append((cause, message, error_dict)) firebase_error = _utils.handle_platform_error_from_requests(error, _custom_handler) assert isinstance(firebase_error, exceptions.NotFoundError) assert str(firebase_error) == 'test error' assert firebase_error.cause is error assert firebase_error.http_response is resp assert len(invocations) == 1 args = invocations[0] assert len(args) == 3 assert args[0] is error assert args[1] == 'test error' assert args[2] == _NOT_FOUND_ERROR_DICT def _create_response(self, status=500, payload=None): resp = models.Response() resp.status_code = status if payload: resp.raw = io.BytesIO(payload.encode()) exc = requests.exceptions.RequestException('Test error', response=resp) return resp, exc class TestGoogleApiClient: @pytest.mark.parametrize('error', [ socket.timeout('Test error'), socket.error('Read timed out') ]) def test_googleapicleint_timeout_error(self, error): firebase_error = _utils.handle_googleapiclient_error(error) assert isinstance(firebase_error, exceptions.DeadlineExceededError) assert str(firebase_error) == 'Timed out while making an API call: {0}'.format(error) assert firebase_error.cause is error assert firebase_error.http_response is None def test_googleapiclient_connection_error(self): error = httplib2.ServerNotFoundError('Test error') firebase_error = _utils.handle_googleapiclient_error(error) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == 'Failed to establish a connection: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_unknown_transport_error(self): error = socket.error('Test error') firebase_error = _utils.handle_googleapiclient_error(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == 'Unknown error while making a remote service call: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_http_response(self): error = self._create_http_error() firebase_error = _utils.handle_googleapiclient_error(error) assert isinstance(firebase_error, exceptions.InternalError) assert str(firebase_error) == str(error) assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == 'Body' def test_http_response_with_unknown_status(self): error = self._create_http_error(status=501) firebase_error = _utils.handle_googleapiclient_error(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == str(error) assert firebase_error.cause is error assert firebase_error.http_response.status_code == 501 assert firebase_error.http_response.content.decode() == 'Body' def test_http_response_with_message(self): error = self._create_http_error() firebase_error = _utils.handle_googleapiclient_error( error, message='Explicit error message') assert isinstance(firebase_error, exceptions.InternalError) assert str(firebase_error) == 'Explicit error message' assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == 'Body' def test_http_response_with_code(self): error = self._create_http_error() firebase_error = _utils.handle_googleapiclient_error( error, code=exceptions.UNAVAILABLE) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == str(error) assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == 'Body' def test_http_response_with_message_and_code(self): error = self._create_http_error() firebase_error = _utils.handle_googleapiclient_error( error, message='Explicit error message', code=exceptions.UNAVAILABLE) assert isinstance(firebase_error, exceptions.UnavailableError) assert str(firebase_error) == 'Explicit error message' assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == 'Body' def test_handle_platform_error(self): error = self._create_http_error(payload=_NOT_FOUND_PAYLOAD) firebase_error = _utils.handle_platform_error_from_googleapiclient(error) assert isinstance(firebase_error, exceptions.NotFoundError) assert str(firebase_error) == 'test error' assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == _NOT_FOUND_PAYLOAD def test_handle_platform_error_with_no_response(self): error = socket.error('Test error') firebase_error = _utils.handle_platform_error_from_googleapiclient(error) assert isinstance(firebase_error, exceptions.UnknownError) assert str(firebase_error) == 'Unknown error while making a remote service call: Test error' assert firebase_error.cause is error assert firebase_error.http_response is None def test_handle_platform_error_with_no_error_code(self): error = self._create_http_error(payload='no error code') firebase_error = _utils.handle_platform_error_from_googleapiclient(error) assert isinstance(firebase_error, exceptions.InternalError) message = 'Unexpected HTTP response with status: 500; body: no error code' assert str(firebase_error) == message assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == 'no error code' def test_handle_platform_error_with_custom_handler(self): error = self._create_http_error(payload=_NOT_FOUND_PAYLOAD) invocations = [] def _custom_handler(cause, message, error_dict, http_response): invocations.append((cause, message, error_dict, http_response)) return exceptions.InvalidArgumentError('Custom message', cause, http_response) firebase_error = _utils.handle_platform_error_from_googleapiclient(error, _custom_handler) assert isinstance(firebase_error, exceptions.InvalidArgumentError) assert str(firebase_error) == 'Custom message' assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == _NOT_FOUND_PAYLOAD assert len(invocations) == 1 args = invocations[0] assert len(args) == 4 assert args[0] is error assert args[1] == 'test error' assert args[2] == _NOT_FOUND_ERROR_DICT assert args[3] is not None def test_handle_platform_error_with_custom_handler_ignore(self): error = self._create_http_error(payload=_NOT_FOUND_PAYLOAD) invocations = [] def _custom_handler(cause, message, error_dict, http_response): invocations.append((cause, message, error_dict, http_response)) firebase_error = _utils.handle_platform_error_from_googleapiclient(error, _custom_handler) assert isinstance(firebase_error, exceptions.NotFoundError) assert str(firebase_error) == 'test error' assert firebase_error.cause is error assert firebase_error.http_response.status_code == 500 assert firebase_error.http_response.content.decode() == _NOT_FOUND_PAYLOAD assert len(invocations) == 1 args = invocations[0] assert len(args) == 4 assert args[0] is error assert args[1] == 'test error' assert args[2] == _NOT_FOUND_ERROR_DICT assert args[3] is not None def _create_http_error(self, status=500, payload='Body'): resp = httplib2.Response({'status': status}) return errors.HttpError(resp, payload.encode())