def test_pushdevice_different(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() old_token = apn.hex_to_b64(u'1111') new_token = apn.hex_to_b64(u'2222') res.canonical = {old_token: new_token} res.needs_retry.return_value = False mock_send.return_value = res def get_count(hex_token): # type: (text_type) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) self.assertEqual(get_count(u'2222'), 1) data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) mock_info.assert_called_once_with( "GCM: Got canonical ref %s, dropping %s" % (new_token, old_token)) self.assertEqual(get_count(u'1111'), 0) self.assertEqual(get_count(u'2222'), 1)
def test_pushdevice_not_present(self, mock_send, mock_warning): # type: (mock.MagicMock, mock.MagicMock) -> None res = {} t1 = apn.hex_to_b64(u'1111') t2 = apn.hex_to_b64(u'3333') res['canonical'] = {t1: t2} mock_send.return_value = res def get_count(hex_token): # type: (Text) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) self.assertEqual(get_count(u'3333'), 0) data = self.get_gcm_data() apn.send_android_push_notification_to_user(self.user_profile, data) msg = ("GCM: Got canonical ref %s " "replacing %s but new ID not " "registered! Updating.") mock_warning.assert_called_once_with(msg % (t2, t1)) self.assertEqual(get_count(u'1111'), 0) self.assertEqual(get_count(u'3333'), 1)
def setUp(self): # type: () -> None super(GCMTest, self).setUp() apn.gcm = gcm.GCM('fake key') self.gcm_tokens = [u'1111', u'2222'] for token in self.gcm_tokens: PushDeviceToken.objects.create(kind=PushDeviceToken.GCM, token=apn.hex_to_b64(token), user=self.user_profile, ios_app_id=None)
def test_cache_exists(self, mock_warn): # type: (mock.MagicMock) -> None self.redis_client.hmset(apn.get_apns_key(100), self.get_cache_value()) err_rsp = self.get_error_response(identifier=100, status=1) apn.response_listener(err_rsp) b64_token = apn.hex_to_b64('aaaa') errmsg = apn.ERROR_CODES[int(err_rsp['status'])] msg = ("APNS: Failed to deliver APNS notification to %s, " "reason: %s" % (b64_token, errmsg)) mock_warn.assert_called_once_with(msg)
def test_error_code_eight(self, mock_warn): # type: (mock.MagicMock) -> None self.redis_client.hmset(apn.get_apns_key(100), self.get_cache_value()) err_rsp = self.get_error_response(identifier=100, status=8) b64_token = apn.hex_to_b64('aaaa') self.assertEqual(PushDeviceToken.objects.filter( user=self.user_profile, token=b64_token).count(), 1) apn.response_listener(err_rsp) self.assertEqual(mock_warn.call_count, 2) self.assertEqual(PushDeviceToken.objects.filter( user=self.user_profile, token=b64_token).count(), 0)
def setUp(self): # type: () -> None super().setUp() apn.gcm = gcm.GCM('fake key') self.gcm_tokens = [u'1111', u'2222'] for token in self.gcm_tokens: PushDeviceToken.objects.create( kind=PushDeviceToken.GCM, token=apn.hex_to_b64(token), user=self.user_profile, ios_app_id=None)
def test_failure(self, mock_send, mock_warn): # type: (mock.MagicMock, mock.MagicMock) -> None res = {} token = apn.hex_to_b64(u'1111') res['errors'] = {'Failed': [token]} mock_send.return_value = res data = self.get_gcm_data() apn.send_android_push_notification_to_user(self.user_profile, data) c1 = call("GCM: Delivery to %s failed: Failed" % (token,)) mock_warn.assert_has_calls([c1], any_order=True)
def test_end_to_end(self): # type: () -> None remote_gcm_tokens = [u'dddd'] for token in remote_gcm_tokens: RemotePushDeviceToken.objects.create( kind=RemotePushDeviceToken.GCM, token=apn.hex_to_b64(token), user_id=self.user_profile.id, server=RemoteZulipServer.objects.get(uuid=self.server_uuid), ) message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) missed_message = { 'message_id': message.id, 'triggers': { 'private_message': True, 'mentioned': False, 'stream_push_notify': False, }, } with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=''), \ mock.patch('zerver.lib.push_notifications.requests.request', side_effect=self.bounce_request), \ mock.patch('zerver.lib.push_notifications.gcm') as mock_gcm, \ mock.patch('zerver.lib.push_notifications._apns_client') as mock_apns, \ mock.patch('logging.info') as mock_info, \ mock.patch('logging.warning'): apns_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.APNS) ] gcm_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.GCM) ] mock_gcm.json_request.return_value = { 'success': {gcm_devices[0][2]: message.id}} mock_apns.get_notification_result.return_value = 'Success' apn.handle_push_notification(self.user_profile.id, missed_message) for _, _, token in apns_devices: mock_info.assert_any_call( "APNs: Success sending for user %d to device %s", self.user_profile.id, token) for _, _, token in gcm_devices: mock_info.assert_any_call( "GCM: Sent %s as %s" % (token, message.id))
def test_failure(self, mock_send, mock_warn): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() token = apn.hex_to_b64(u'1111') res.failed = {token: 1} res.needs_retry.return_value = True mock_send.return_value = res data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) c1 = call("GCM: Delivery to %s failed: 1" % (token,)) c2 = call("GCM: delivery needs a retry but ignoring") mock_warn.assert_has_calls([c1, c2], any_order=True)
def test_end_to_end_connection_error(self): # type: () -> None remote_gcm_tokens = [u'dddd'] for token in remote_gcm_tokens: RemotePushDeviceToken.objects.create( kind=RemotePushDeviceToken.GCM, token=apn.hex_to_b64(token), user_id=self.user_profile.id, server=RemoteZulipServer.objects.get(uuid=self.server_uuid), ) message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) def retry(queue_name, event, processor): # type: (Any, Any, Any) -> None apn.handle_push_notification(event['user_profile_id'], event) missed_message = { 'user_profile_id': self.user_profile.id, 'message_id': message.id, 'triggers': { 'private_message': True, 'mentioned': False, 'stream_push_notify': False, }, } with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=''), \ mock.patch('zerver.lib.push_notifications.requests.request', side_effect=self.bounce_request), \ mock.patch('zerver.lib.push_notifications.gcm') as mock_gcm, \ mock.patch('zerver.lib.push_notifications.send_notifications_to_bouncer', side_effect=requests.ConnectionError), \ mock.patch('zerver.lib.queue.queue_json_publish', side_effect=retry) as mock_retry, \ mock.patch('logging.warning') as mock_warn: gcm_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.GCM) ] mock_gcm.json_request.return_value = { 'success': {gcm_devices[0][2]: message.id}} apn.handle_push_notification(self.user_profile.id, missed_message) self.assertEqual(mock_retry.call_count, 3) mock_warn.assert_called_with("Maximum retries exceeded for " "trigger:%s event:" "push_notification" % (self.user_profile.id,))
def setUp(self): # type: () -> None super().setUp() self.user_profile = self.example_user('hamlet') self.tokens = [u'aaaa', u'bbbb'] for token in self.tokens: PushDeviceToken.objects.create( kind=PushDeviceToken.APNS, token=apn.hex_to_b64(token), user=self.user_profile, ios_app_id=settings.ZULIP_IOS_APP_ID) self.remote_tokens = [u'cccc'] for token in self.remote_tokens: RemotePushDeviceToken.objects.create( kind=RemotePushDeviceToken.APNS, token=apn.hex_to_b64(token), user_id=self.user_profile.id, server=RemoteZulipServer.objects.get(uuid=self.server_uuid), ) self.sending_client = get_client('test') self.sender = self.example_user('hamlet')
def setUp(self): # type: () -> None email = '*****@*****.**' apn.connection = apn.get_connection('fake-cert', 'fake-key') self.redis_client = apn.redis_client = MockRedis() # type: ignore apn.dbx_connection = apn.get_connection('fake-cert', 'fake-key') self.user_profile = get_user_profile_by_email(email) self.tokens = [u'aaaa', u'bbbb'] for token in self.tokens: PushDeviceToken.objects.create( kind=PushDeviceToken.APNS, token=apn.hex_to_b64(token), user=self.user_profile, ios_app_id=settings.ZULIP_IOS_APP_ID)
def test_end_to_end(self): # type: () -> None remote_gcm_tokens = [u'dddd'] for token in remote_gcm_tokens: RemotePushDeviceToken.objects.create( kind=RemotePushDeviceToken.GCM, token=apn.hex_to_b64(token), user_id=self.user_profile.id, server=RemoteZulipServer.objects.get(uuid=self.server_uuid), ) message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) missed_message = { 'message_id': message.id, 'trigger': 'private_message', } with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=''), \ mock.patch('zerver.lib.push_notifications.requests.request', side_effect=self.bounce_request), \ mock.patch('zerver.lib.push_notifications.gcm') as mock_gcm, \ mock.patch('zerver.lib.push_notifications._apns_client') as mock_apns, \ mock.patch('logging.info') as mock_info, \ mock.patch('logging.warning'): apns_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.APNS) ] gcm_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.GCM) ] mock_gcm.json_request.return_value = { 'success': {gcm_devices[0][2]: message.id}} mock_apns.get_notification_result.return_value = 'Success' apn.handle_push_notification(self.user_profile.id, missed_message) for _, _, token in apns_devices: mock_info.assert_any_call( "APNs: Success sending for user %d to device %s", self.user_profile.id, token) for _, _, token in gcm_devices: mock_info.assert_any_call( "GCM: Sent %s as %s" % (token, message.id))
def test_pushdevice_different(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = {} old_token = apn.hex_to_b64(u'1111') new_token = apn.hex_to_b64(u'2222') res['canonical'] = {old_token: new_token} mock_send.return_value = res def get_count(hex_token): # type: (Text) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) self.assertEqual(get_count(u'2222'), 1) data = self.get_gcm_data() apn.send_android_push_notification_to_user(self.user_profile, data) mock_info.assert_called_once_with( "GCM: Got canonical ref %s, dropping %s" % (new_token, old_token)) self.assertEqual(get_count(u'1111'), 0) self.assertEqual(get_count(u'2222'), 1)
def test_end_to_end_connection_error(self): # type: () -> None remote_gcm_tokens = [u'dddd'] for token in remote_gcm_tokens: RemotePushDeviceToken.objects.create( kind=RemotePushDeviceToken.GCM, token=apn.hex_to_b64(token), user_id=self.user_profile.id, server=RemoteZulipServer.objects.get(uuid=self.server_uuid), ) message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) def retry(queue_name, event, processor): # type: (Any, Any, Any) -> None apn.handle_push_notification(event['user_profile_id'], event) missed_message = { 'user_profile_id': self.user_profile.id, 'message_id': message.id, 'trigger': 'private_message', } with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=''), \ mock.patch('zerver.lib.push_notifications.requests.request', side_effect=self.bounce_request), \ mock.patch('zerver.lib.push_notifications.gcm') as mock_gcm, \ mock.patch('zerver.lib.push_notifications.send_notifications_to_bouncer', side_effect=requests.ConnectionError), \ mock.patch('zerver.lib.queue.queue_json_publish', side_effect=retry) as mock_retry, \ mock.patch('logging.warning') as mock_warn: gcm_devices = [ (apn.b64_to_hex(device.token), device.ios_app_id, device.token) for device in RemotePushDeviceToken.objects.filter( kind=PushDeviceToken.GCM) ] mock_gcm.json_request.return_value = { 'success': {gcm_devices[0][2]: message.id}} apn.handle_push_notification(self.user_profile.id, missed_message) self.assertEqual(mock_retry.call_count, 3) mock_warn.assert_called_with("Maximum retries exceeded for " "trigger:%s event:" "push_notification" % (self.user_profile.id,))
def test_non_bouncer_push(self): # type: () -> None message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) for token in [u'dddd']: PushDeviceToken.objects.create( kind=PushDeviceToken.GCM, token=apn.hex_to_b64(token), user=self.user_profile) android_devices = list( PushDeviceToken.objects.filter(user=self.user_profile, kind=PushDeviceToken.GCM)) apple_devices = list( PushDeviceToken.objects.filter(user=self.user_profile, kind=PushDeviceToken.APNS)) missed_message = { 'message_id': message.id, 'triggers': { 'private_message': True, 'mentioned': False, 'stream_push_notify': False, }, } with mock.patch('zerver.lib.push_notifications.get_apns_payload', return_value={'apns': True}), \ mock.patch('zerver.lib.push_notifications.get_gcm_payload', return_value={'gcm': True}), \ mock.patch('zerver.lib.push_notifications' '.send_apple_push_notification') as mock_send_apple, \ mock.patch('zerver.lib.push_notifications' '.send_android_push_notification') as mock_send_android: apn.handle_push_notification(self.user_profile.id, missed_message) mock_send_apple.assert_called_with(self.user_profile.id, apple_devices, {'apns': True}) mock_send_android.assert_called_with(android_devices, {'gcm': True})
def test_not_registered(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = {} token = apn.hex_to_b64(u'1111') res['errors'] = {'NotRegistered': [token]} mock_send.return_value = res def get_count(hex_token): # type: (Text) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) data = self.get_gcm_data() apn.send_android_push_notification_to_user(self.user_profile, data) mock_info.assert_called_once_with("GCM: Removing %s" % (token,)) self.assertEqual(get_count(u'1111'), 0)
def test_not_registered(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() token = apn.hex_to_b64(u'1111') res.not_registered = [token] res.needs_retry.return_value = False mock_send.return_value = res def get_count(hex_token): # type: (text_type) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) mock_info.assert_called_once_with("GCM: Removing %s" % (token,)) self.assertEqual(get_count(u'1111'), 0)
def test_non_bouncer_push(self): # type: () -> None message = self.get_message(Recipient.PERSONAL, type_id=1) UserMessage.objects.create( user_profile=self.user_profile, message=message ) for token in [u'dddd']: PushDeviceToken.objects.create( kind=PushDeviceToken.GCM, token=apn.hex_to_b64(token), user=self.user_profile) android_devices = list( PushDeviceToken.objects.filter(user=self.user_profile, kind=PushDeviceToken.GCM)) apple_devices = list( PushDeviceToken.objects.filter(user=self.user_profile, kind=PushDeviceToken.APNS)) missed_message = { 'message_id': message.id, 'trigger': 'private_message', } with mock.patch('zerver.lib.push_notifications.get_apns_payload', return_value={'apns': True}), \ mock.patch('zerver.lib.push_notifications.get_gcm_payload', return_value={'gcm': True}), \ mock.patch('zerver.lib.push_notifications' '.send_apple_push_notification') as mock_send_apple, \ mock.patch('zerver.lib.push_notifications' '.send_android_push_notification') as mock_send_android: apn.handle_push_notification(self.user_profile.id, missed_message) mock_send_apple.assert_called_with(self.user_profile.id, apple_devices, {'apns': True}) mock_send_android.assert_called_with(android_devices, {'gcm': True})
def get_count(hex_token): # type: (Text) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count()