From 8a77ba6ca53aa495d20da6c7b64b42335fced622 Mon Sep 17 00:00:00 2001 From: jr conlin Date: Fri, 10 Nov 2017 14:27:44 -0800 Subject: [PATCH] bug: fix up tests and integration for new gcmclient Issue #1068 --- autopush/router/gcm.py | 7 +- autopush/tests/test_endpoint.py | 7 -- autopush/tests/test_gcmclient.py | 2 +- autopush/tests/test_integration.py | 2 +- autopush/tests/test_router.py | 125 ++++++++++++++++------------- 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/autopush/router/gcm.py b/autopush/router/gcm.py index f9241ae9..ea768590 100644 --- a/autopush/router/gcm.py +++ b/autopush/router/gcm.py @@ -35,10 +35,7 @@ def __init__(self, conf, router_conf, metrics): for sid in router_conf.get("senderIDs"): auth = router_conf.get("senderIDs").get(sid).get("auth") self.senderIDs[sid] = auth - try: - self.gcm[sid] = gcmclient.GCM(auth) - except Exception: - raise IOError("GCM Bridge not initiated in main") + self.gcm[sid] = gcmclient.GCM(auth) self._base_tags = ["platform:gcm"] self.log.debug("Starting GCM router...") @@ -151,7 +148,7 @@ def _process_reply(self, reply, uaid_data, ttl, notification): # acks: # for reg_id, msg_id in reply.success.items(): # updates - for old_id, new_id in reply.canonical.items(): + for old_id, new_id in reply.canonicals.items(): self.log.debug("GCM id changed : {old} => {new}", old=old_id, new=new_id) self.metrics.increment("notification.bridge.error", diff --git a/autopush/tests/test_endpoint.py b/autopush/tests/test_endpoint.py index fdf38cc9..af7426aa 100644 --- a/autopush/tests/test_endpoint.py +++ b/autopush/tests/test_endpoint.py @@ -121,13 +121,6 @@ def test_delete_db_error(self): tok = ":".join(["m", dummy_uaid.hex, str(dummy_chid)]) self.fernet_mock.decrypt.return_value = tok - def raise_condition(*args, **kwargs): - import autopush.db - raise autopush.db.g_client.exceptions.ClientError( - {'Error': {'Code': 'ConditionalCheckFailedException'}}, - 'mock_update_item' - ) - self.message_mock.configure_mock(**{"delete_message.return_value": False}) resp = yield self.client.delete(self.url(message_id="ignored")) diff --git a/autopush/tests/test_gcmclient.py b/autopush/tests/test_gcmclient.py index 520ba750..cbb0ecc9 100644 --- a/autopush/tests/test_gcmclient.py +++ b/autopush/tests/test_gcmclient.py @@ -51,7 +51,7 @@ def test_canonical(self): "multicast_id": 5174939174563864884, "success": 1, "failure": 0, - "canonical_ids": 0, + "canonical_ids": 1, "results": [ { "message_id": "0:1510011451922224%7a0e7efbaab8b7cc", diff --git a/autopush/tests/test_integration.py b/autopush/tests/test_integration.py index 98b5b667..9d54b032 100644 --- a/autopush/tests/test_integration.py +++ b/autopush/tests/test_integration.py @@ -1572,7 +1572,7 @@ class TestGCMBridgeIntegration(IntegrationBase): class MockReply(object): success = dict() - canonical = dict() + canonicals = dict() failed_items = dict() not_registered = dict() failed = dict() diff --git a/autopush/tests/test_router.py b/autopush/tests/test_router.py index 79a8e7e7..338fb58a 100644 --- a/autopush/tests/test_router.py +++ b/autopush/tests/test_router.py @@ -4,6 +4,7 @@ import time import json import decimal +import requests from autopush.utils import WebPushNotification from mock import Mock, PropertyMock, patch @@ -297,8 +298,7 @@ def check_results(result): class GCMRouterTestCase(unittest.TestCase): - @patch("autopush.router.gcmclient.GCM", spec=gcmclient.GCM) - def setUp(self, fgcm): + def setUp(self): conf = AutopushConfig( hostname="localhost", statsd_host=None, @@ -307,8 +307,24 @@ def setUp(self, fgcm): 'ttl': 60, 'senderIDs': {'test123': {"auth": "12345678abcdefg"}}} - self.gcm = fgcm + self.response = Mock(spec=requests.Response) + self.response.status_code = 200 + self.response.headers = dict() + self.response.content = json.dumps({ + "multicast_id": 5174939174563864884, + "success": 1, + "failure": 0, + "canonical_ids": 0, + "results": [ + { + "message_id": "0:1510011451922224%7a0e7efbaab8b7cc" + } + ] + }) + self.gcm = gcmclient.GCM(api_key="SomeKey") + self.gcm._sender = Mock(return_value=self.response) self.router = GCMRouter(conf, self.gcm_config, SinkMetrics()) + self.router.gcm['test123'] = self.gcm self.headers = {"content-encoding": "aesgcm", "encryption": "test", "encryption-key": "test"} @@ -326,20 +342,13 @@ def setUp(self, fgcm): router_data=dict( token="connect_data", creds=dict(senderID="test123", auth="12345678abcdefg"))) - mock_result = Mock(spec=gcmclient.Result) - mock_result.canonical = dict() - mock_result.failed = dict() - mock_result.not_registered = dict() - mock_result.retry_after = None - self.mock_result = mock_result - fgcm.send.return_value = mock_result def _check_error_call(self, exc, code, response=None, errno=None): assert isinstance(exc, RouterException) assert exc.status_code == code if errno is not None: assert exc.errno == errno - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called if response: assert exc.response_body == response self.flushLoggedErrors() @@ -365,37 +374,23 @@ def test_register_bad(self): with pytest.raises(RouterException): self.router.register("uaid", router_data={}, app_id="") with pytest.raises(RouterException): - self.router.register("uaid", router_data={}, app_id='') + self.router.register("uaid", router_data={}, app_id=None) with pytest.raises(RouterException): self.router.register( "uaid", router_data={"token": "abcd1234"}, app_id="invalid123") - @patch("autopush.router.gcmclient.GCM") - def test_gcmclient_fail(self, fgcm): - fgcm.side_effect = Exception - conf = AutopushConfig( - hostname="localhost", - statsd_host=None, - ) - with pytest.raises(IOError): - GCMRouter( - conf, - {"senderIDs": {"test123": {"auth": "abcd"}}}, - SinkMetrics() - ) - def test_route_notification(self): self.router.gcm['test123'] = self.gcm d = self.router.route_notification(self.notif, self.router_data) def check_results(result): assert isinstance(result, RouterResponse) - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called # Make sure the data was encoded as base64 - data = self.router.gcm[ - 'test123'].send.call_args[0][0].payload['data'] + payload = json.loads(self.gcm._sender.call_args[1]['data']) + data = payload['data'] assert data['body'] == 'q60d6g' assert data['enc'] == 'test' assert data['chid'] == dummy_chid @@ -421,9 +416,9 @@ def check_results(result): assert result.status_code == 201 assert result.logged_status == 200 assert "TTL" in result.headers - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called # Make sure the data was encoded as base64 - payload = self.router.gcm['test123'].send.call_args[0][0].payload + payload = json.loads(self.gcm._sender.call_args[1]['data']) data = payload['data'] assert data['body'] == 'q60d6g' assert data['enc'] == 'test' @@ -449,9 +444,9 @@ def test_ttl_high(self): def check_results(result): assert isinstance(result, RouterResponse) - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called # Make sure the data was encoded as base64 - payload = self.router.gcm['test123'].send.call_args[0][0].payload + payload = json.loads(self.gcm._sender.call_args[1]['data']) data = payload['data'] assert data['body'] == 'q60d6g' assert data['enc'] == 'test' @@ -484,22 +479,18 @@ def check_results(result): return d def test_route_crypto_notification(self): - self.router.gcm['test123'] = self.gcm del(self.notif.headers['encryption_key']) self.notif.headers['crypto_key'] = 'crypto' d = self.router.route_notification(self.notif, self.router_data) def check_results(result): assert isinstance(result, RouterResponse) - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called d.addCallback(check_results) return d def test_router_notification_gcm_auth_error(self): - def throw_auth(arg): - raise gcmclient.GCMAuthenticationError() - self.gcm.send.side_effect = throw_auth - self.router.gcm['test123'] = self.gcm + self.response.status_code = 401 d = self.router.route_notification(self.notif, self.router_data) def check_results(fail): @@ -508,10 +499,7 @@ def check_results(fail): return d def test_router_notification_gcm_other_error(self): - def throw_other(arg): - raise Exception("oh my!") - self.gcm.send.side_effect = throw_other - self.router.gcm['test123'] = self.gcm + self.gcm._sender.side_effect = Exception d = self.router.route_notification(self.notif, self.router_data) def check_results(fail): @@ -525,7 +513,7 @@ def test_router_notification_connection_error(self): def throw_other(*args, **kwargs): raise ConnectionError("oh my!") - self.gcm.send.side_effect = throw_other + self.gcm._sender.side_effect = throw_other self.router.gcm['test123'] = self.gcm d = self.router.route_notification(self.notif, self.router_data) @@ -535,8 +523,18 @@ def check_results(fail): return d def test_router_notification_gcm_id_change(self): - self.mock_result.canonical["old"] = "new" - self.router.gcm['test123'] = self.gcm + self.response.content = json.dumps({ + "multicast_id": 5174939174563864884, + "success": 1, + "failure": 0, + "canonical_ids": 1, + "results": [ + { + "message_id": "0:1510011451922224%7a0e7efbaab8b7cc", + "registration_id": "new", + } + ] + }) self.router.metrics = Mock() d = self.router.route_notification(self.notif, self.router_data) @@ -548,13 +546,22 @@ def check_results(result): self.router.metrics.increment.call_args[1]['tags'].sort() assert self.router.metrics.increment.call_args[1]['tags'] == [ 'platform:gcm', 'reason:reregister'] - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called d.addCallback(check_results) return d def test_router_notification_gcm_not_regged(self): - self.mock_result.not_registered = {"connect_data": True} - self.router.gcm['test123'] = self.gcm + self.response.content = json.dumps({ + "multicast_id": 5174939174563864884, + "success": 1, + "failure": 1, + "canonical_ids": 0, + "results": [ + { + "error": "NotRegistered" + } + ] + }) self.router.metrics = Mock() d = self.router.route_notification(self.notif, self.router_data) @@ -566,13 +573,22 @@ def check_results(result): self.router.metrics.increment.call_args[1]['tags'].sort() assert self.router.metrics.increment.call_args[1]['tags'] == [ 'platform:gcm', 'reason:unregistered'] - assert self.router.gcm['test123'].send.called + assert self.gcm._sender.called d.addCallback(check_results) return d def test_router_notification_gcm_failed_items(self): - self.mock_result.failed = dict(connect_data=True) - self.router.gcm['test123'] = self.gcm + self.response.content = json.dumps({ + "multicast_id": 5174939174563864884, + "success": 1, + "failure": 1, + "canonical_ids": 0, + "results": [ + { + "error": "InvalidRegistration" + } + ] + }) self.router.metrics = Mock() d = self.router.route_notification(self.notif, self.router_data) @@ -589,8 +605,9 @@ def check_results(fail): return d def test_router_notification_gcm_needs_retry(self): - self.mock_result.retry_after = 1000 - self.router.gcm['test123'] = self.gcm + self.response.headers['Retry-After'] = "123" + self.response.status_code = 500 + self.response.content = "" self.router.metrics = Mock() d = self.router.route_notification(self.notif, self.router_data)