Skip to content

fix(fcm): Converting unexpected gapic runtime errors to FirebaseError #509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions firebase_admin/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import json

import googleapiclient
from googleapiclient import http
from googleapiclient import _auth
import requests
Expand Down Expand Up @@ -388,7 +387,7 @@ def batch_callback(_, response, error):

try:
batch.execute()
except googleapiclient.http.HttpError as error:
except Exception as error:
raise self._handle_batch_error(error)
else:
return BatchResponse(responses)
Expand Down
53 changes: 46 additions & 7 deletions tests/test_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1792,6 +1792,15 @@ def test_send_unknown_fcm_error_code(self, status):
assert json.loads(recorder[0].body.decode()) == body


class _HttpMockException:

def __init__(self, exc):
self._exc = exc

def request(self, url, **kwargs):
raise self._exc


class TestBatch:

@classmethod
Expand All @@ -1803,17 +1812,21 @@ def setup_class(cls):
def teardown_class(cls):
testutils.cleanup_apps()

def _instrument_batch_messaging_service(self, app=None, status=200, payload=''):
def _instrument_batch_messaging_service(self, app=None, status=200, payload='', exc=None):
if not app:
app = firebase_admin.get_app()

fcm_service = messaging._get_messaging_service(app)
if status == 200:
content_type = 'multipart/mixed; boundary=boundary'
if exc:
fcm_service._transport = _HttpMockException(exc)
else:
content_type = 'application/json'
fcm_service._transport = http.HttpMockSequence([
({'status': str(status), 'content-type': content_type}, payload),
])
if status == 200:
content_type = 'multipart/mixed; boundary=boundary'
else:
content_type = 'application/json'
fcm_service._transport = http.HttpMockSequence([
({'status': str(status), 'content-type': content_type}, payload),
])
return fcm_service

def _batch_payload(self, payloads):
Expand Down Expand Up @@ -2027,6 +2040,19 @@ def test_send_all_batch_fcm_error_code(self, status):
messaging.send_all([msg])
check_exception(excinfo.value, 'test error', status)

def test_send_all_runtime_exception(self):
exc = BrokenPipeError('Test error')
_ = self._instrument_batch_messaging_service(exc=exc)
msg = messaging.Message(topic='foo')

with pytest.raises(exceptions.UnknownError) as excinfo:
messaging.send_all([msg])

expected = 'Unknown error while making a remote service call: Test error'
assert str(excinfo.value) == expected
assert excinfo.value.cause is exc
assert excinfo.value.http_response is None


class TestSendMulticast(TestBatch):

Expand Down Expand Up @@ -2204,6 +2230,19 @@ def test_send_multicast_batch_fcm_error_code(self, status):
messaging.send_multicast(msg)
check_exception(excinfo.value, 'test error', status)

def test_send_multicast_runtime_exception(self):
exc = BrokenPipeError('Test error')
_ = self._instrument_batch_messaging_service(exc=exc)
msg = messaging.MulticastMessage(tokens=['foo'])

with pytest.raises(exceptions.UnknownError) as excinfo:
messaging.send_multicast(msg)

expected = 'Unknown error while making a remote service call: Test error'
assert str(excinfo.value) == expected
assert excinfo.value.cause is exc
assert excinfo.value.http_response is None


class TestTopicManagement:

Expand Down