Skip to content

Commit 07bd5ac

Browse files
committed
Updating tests
1 parent 97d0b84 commit 07bd5ac

File tree

2 files changed

+144
-104
lines changed

2 files changed

+144
-104
lines changed

firebase_admin/messaging.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ def send_all(self, messages, dry_run=False):
379379
"""Sends the given messages to FCM via the batch API."""
380380
if not isinstance(messages, list):
381381
raise ValueError('Messages must be an list of messaging.Message instances.')
382+
if len(messages) > 100:
383+
raise ValueError('send_all messages must not contain more than 100 messages.')
382384

383385
responses = []
384386

tests/test_messaging.py

Lines changed: 142 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,15 @@ def test_invalid_tokens_type(self, tokens):
5353
expected = 'MulticastMessage.tokens must be a list of strings.'
5454
assert str(excinfo.value) == expected
5555

56+
def test_tokens_over_one_hundred(self):
57+
with pytest.raises(ValueError) as excinfo:
58+
messaging.MulticastMessage(tokens=['token' for i in xrange(0, 101)])
59+
expected = 'MulticastMessage.tokens must not contain more than 100 tokens.'
60+
assert str(excinfo.value) == expected
61+
5662
def test_tokens_type(self):
5763
messaging.MulticastMessage(tokens=['token'])
64+
messaging.MulticastMessage(tokens=['token' for i in xrange(0, 100)])
5865

5966

6067
class TestMessageEncoder(object):
@@ -1335,12 +1342,7 @@ def test_send_fcm_error_code(self, status):
13351342
assert json.loads(recorder[0].body.decode()) == body
13361343

13371344

1338-
class TestSendAll(object):
1339-
1340-
_PAYLOAD_FORMAT = """--boundary\r\nContent-Type: application/http\r\n\
1341-
Content-ID: <uuid + 1>\r\n\r\nHTTP/1.1 {} Success\r\n\
1342-
Content-Type: application/json; charset=UTF-8\r\n\r\n{}\r\n\r\n--boundary--"""
1343-
_CLIENT_VERSION = 'fire-admin-python/{0}'.format(firebase_admin.__version__)
1345+
class TestBatch(object):
13441346

13451347
@classmethod
13461348
def setup_class(cls):
@@ -1364,8 +1366,19 @@ def _instrument_batch_messaging_service(self, app=None, status=200, payload=''):
13641366
])
13651367
return fcm_service
13661368

1367-
def _get_url(self, project_id):
1368-
return messaging._MessagingService.FCM_URL.format(project_id)
1369+
def _batch_payload(self, payloads):
1370+
# payloads should be a list of (status_code, content) tuples
1371+
payload = ''
1372+
_playload_format = """--boundary\r\nContent-Type: application/http\r\n\
1373+
Content-ID: <uuid + {}>\r\n\r\nHTTP/1.1 {} Success\r\n\
1374+
Content-Type: application/json; charset=UTF-8\r\n\r\n{}\r\n\r\n"""
1375+
for (index, (status_code, content)) in enumerate(payloads):
1376+
payload += _playload_format.format(str(index + 1), str(status_code), content)
1377+
payload += '--boundary--'
1378+
return payload
1379+
1380+
1381+
class TestSendAll(TestBatch):
13691382

13701383
def test_no_project_id(self):
13711384
def evaluate():
@@ -1385,62 +1398,86 @@ def test_invalid_send_all(self, msg):
13851398
expected = 'Messages must be an list of messaging.Message instances.'
13861399
assert str(excinfo.value) == expected
13871400

1401+
def test_invalid_over_one_hundred(self):
1402+
msg = messaging.Message(topic='foo')
1403+
with pytest.raises(ValueError) as excinfo:
1404+
messaging.send_all([msg for i in xrange(0, 101)])
1405+
expected = 'send_all messages must not contain more than 100 messages.'
1406+
assert str(excinfo.value) == expected
1407+
13881408
def test_send_all(self):
13891409
payload = json.dumps({'name': 'message-id'})
13901410
_ = self._instrument_batch_messaging_service(
1391-
payload=self._PAYLOAD_FORMAT.format('200', payload))
1411+
payload=self._batch_payload([(200, payload), (200, payload)]))
13921412
msg = messaging.Message(topic='foo')
1393-
batch_response = messaging.send_all([msg], dry_run=True)
1394-
assert batch_response.success_count is 1
1413+
batch_response = messaging.send_all([msg, msg], dry_run=True)
1414+
assert batch_response.success_count is 2
13951415
assert batch_response.failure_count is 0
1396-
assert len(batch_response.responses) == 1
1397-
assert [r.message_id for r in batch_response.responses] == ['message-id']
1416+
assert len(batch_response.responses) == 2
1417+
assert [r.message_id for r in batch_response.responses] == ['message-id', 'message-id']
13981418
assert all([r.success for r in batch_response.responses])
13991419
assert not any([r.exception for r in batch_response.responses])
14001420

14011421
@pytest.mark.parametrize('status', HTTP_ERRORS)
14021422
def test_send_all_detailed_error(self, status):
1403-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1423+
success_payload = json.dumps({'name': 'message-id'})
1424+
error_payload = json.dumps({
14041425
'error': {
14051426
'status': 'INVALID_ARGUMENT',
14061427
'message': 'test error'
14071428
}
1408-
}))
1409-
_ = self._instrument_batch_messaging_service(payload=payload)
1429+
})
1430+
_ = self._instrument_batch_messaging_service(
1431+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
14101432
msg = messaging.Message(topic='foo')
1411-
batch_response = messaging.send_all([msg])
1412-
assert batch_response.success_count is 0
1433+
batch_response = messaging.send_all([msg, msg])
1434+
assert batch_response.success_count is 1
14131435
assert batch_response.failure_count is 1
1414-
assert len(batch_response.responses) == 1
1415-
assert not any([r.message_id for r in batch_response.responses])
1416-
assert not all([r.success for r in batch_response.responses])
1417-
exception = batch_response.responses[0].exception
1436+
assert len(batch_response.responses) == 2
1437+
success_response = batch_response.responses[0]
1438+
assert success_response.message_id == 'message-id'
1439+
assert success_response.success
1440+
assert success_response.exception is None
1441+
error_response = batch_response.responses[1]
1442+
assert error_response.message_id is None
1443+
assert not error_response.success
1444+
assert error_response.exception
1445+
exception = error_response.exception
14181446
assert str(exception) == 'test error'
14191447
assert str(exception.code) == 'invalid-argument'
14201448

14211449
@pytest.mark.parametrize('status', HTTP_ERRORS)
14221450
def test_send_all_canonical_error_code(self, status):
1423-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1451+
success_payload = json.dumps({'name': 'message-id'})
1452+
error_payload = json.dumps({
14241453
'error': {
14251454
'status': 'NOT_FOUND',
14261455
'message': 'test error'
14271456
}
1428-
}))
1429-
_ = self._instrument_batch_messaging_service(payload=payload)
1457+
})
1458+
_ = self._instrument_batch_messaging_service(
1459+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
14301460
msg = messaging.Message(topic='foo')
1431-
batch_response = messaging.send_all([msg])
1432-
assert batch_response.success_count is 0
1461+
batch_response = messaging.send_all([msg, msg])
1462+
assert batch_response.success_count is 1
14331463
assert batch_response.failure_count is 1
1434-
assert len(batch_response.responses) == 1
1435-
assert not any([r.message_id for r in batch_response.responses])
1436-
assert not all([r.success for r in batch_response.responses])
1437-
exception = batch_response.responses[0].exception
1464+
assert len(batch_response.responses) == 2
1465+
success_response = batch_response.responses[0]
1466+
assert success_response.message_id == 'message-id'
1467+
assert success_response.success
1468+
assert success_response.exception is None
1469+
error_response = batch_response.responses[1]
1470+
assert error_response.message_id is None
1471+
assert not error_response.success
1472+
assert error_response.exception
1473+
exception = error_response.exception
14381474
assert str(exception) == 'test error'
14391475
assert str(exception.code) == 'registration-token-not-registered'
14401476

14411477
@pytest.mark.parametrize('status', HTTP_ERRORS)
14421478
def test_send_all_fcm_error_code(self, status):
1443-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1479+
success_payload = json.dumps({'name': 'message-id'})
1480+
error_payload = json.dumps({
14441481
'error': {
14451482
'status': 'INVALID_ARGUMENT',
14461483
'message': 'test error',
@@ -1451,16 +1488,23 @@ def test_send_all_fcm_error_code(self, status):
14511488
},
14521489
],
14531490
}
1454-
}))
1455-
_ = self._instrument_batch_messaging_service(payload=payload)
1491+
})
1492+
_ = self._instrument_batch_messaging_service(
1493+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
14561494
msg = messaging.Message(topic='foo')
1457-
batch_response = messaging.send_all([msg])
1458-
assert batch_response.success_count is 0
1495+
batch_response = messaging.send_all([msg, msg])
1496+
assert batch_response.success_count is 1
14591497
assert batch_response.failure_count is 1
1460-
assert len(batch_response.responses) == 1
1461-
assert not any([r.message_id for r in batch_response.responses])
1462-
assert not all([r.success for r in batch_response.responses])
1463-
exception = batch_response.responses[0].exception
1498+
assert len(batch_response.responses) == 2
1499+
success_response = batch_response.responses[0]
1500+
assert success_response.message_id == 'message-id'
1501+
assert success_response.success
1502+
assert success_response.exception is None
1503+
error_response = batch_response.responses[1]
1504+
assert error_response.message_id is None
1505+
assert not error_response.success
1506+
assert error_response.exception
1507+
exception = error_response.exception
14641508
assert str(exception) == 'test error'
14651509
assert str(exception.code) == 'registration-token-not-registered'
14661510

@@ -1526,37 +1570,7 @@ def test_send_all_batch_fcm_error_code(self, status):
15261570
assert str(excinfo.value.code) == 'registration-token-not-registered'
15271571

15281572

1529-
class TestSendMulticast(object):
1530-
1531-
_PAYLOAD_FORMAT = """--boundary\r\nContent-Type: application/http\r\n\
1532-
Content-ID: <uuid + 1>\r\n\r\nHTTP/1.1 {} Success\r\n\
1533-
Content-Type: application/json; charset=UTF-8\r\n\r\n{}\r\n\r\n--boundary--"""
1534-
_CLIENT_VERSION = 'fire-admin-python/{0}'.format(firebase_admin.__version__)
1535-
1536-
@classmethod
1537-
def setup_class(cls):
1538-
cred = testutils.MockCredential()
1539-
firebase_admin.initialize_app(cred, {'projectId': 'explicit-project-id'})
1540-
1541-
@classmethod
1542-
def teardown_class(cls):
1543-
testutils.cleanup_apps()
1544-
1545-
def _instrument_batch_messaging_service(self, app=None, status=200, payload=''):
1546-
if not app:
1547-
app = firebase_admin.get_app()
1548-
fcm_service = messaging._get_messaging_service(app)
1549-
if status == 200:
1550-
content_type = 'multipart/mixed; boundary=boundary'
1551-
else:
1552-
content_type = 'application/json'
1553-
fcm_service._transport = HttpMockSequence([
1554-
({'status': str(status), 'content-type': content_type}, payload),
1555-
])
1556-
return fcm_service
1557-
1558-
def _get_url(self, project_id):
1559-
return messaging._MessagingService.FCM_URL.format(project_id)
1573+
class TestSendMulticast(TestBatch):
15601574

15611575
def test_no_project_id(self):
15621576
def evaluate():
@@ -1575,59 +1589,76 @@ def test_invalid_send_multicast(self, msg):
15751589
def test_send_multicast(self):
15761590
payload = json.dumps({'name': 'message-id'})
15771591
_ = self._instrument_batch_messaging_service(
1578-
payload=self._PAYLOAD_FORMAT.format('200', payload))
1579-
msg = messaging.MulticastMessage(tokens=['foo'])
1592+
payload=self._batch_payload([(200, payload), (200, payload)]))
1593+
msg = messaging.MulticastMessage(tokens=['foo', 'foo'])
15801594
batch_response = messaging.send_multicast(msg, dry_run=True)
1581-
assert batch_response.success_count is 1
1595+
assert batch_response.success_count is 2
15821596
assert batch_response.failure_count is 0
1583-
assert len(batch_response.responses) == 1
1584-
assert [r.message_id for r in batch_response.responses] == ['message-id']
1597+
assert len(batch_response.responses) == 2
1598+
assert [r.message_id for r in batch_response.responses] == ['message-id', 'message-id']
15851599
assert all([r.success for r in batch_response.responses])
15861600
assert not any([r.exception for r in batch_response.responses])
15871601

15881602
@pytest.mark.parametrize('status', HTTP_ERRORS)
15891603
def test_send_multicast_detailed_error(self, status):
1590-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1604+
success_payload = json.dumps({'name': 'message-id'})
1605+
error_payload = json.dumps({
15911606
'error': {
15921607
'status': 'INVALID_ARGUMENT',
15931608
'message': 'test error'
15941609
}
1595-
}))
1596-
_ = self._instrument_batch_messaging_service(payload=payload)
1597-
msg = messaging.MulticastMessage(tokens=['foo'])
1610+
})
1611+
_ = self._instrument_batch_messaging_service(
1612+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
1613+
msg = messaging.MulticastMessage(tokens=['foo', 'foo'])
15981614
batch_response = messaging.send_multicast(msg)
1599-
assert batch_response.success_count is 0
1615+
assert batch_response.success_count is 1
16001616
assert batch_response.failure_count is 1
1601-
assert len(batch_response.responses) == 1
1602-
assert not any([r.message_id for r in batch_response.responses])
1603-
assert not all([r.success for r in batch_response.responses])
1604-
exception = batch_response.responses[0].exception
1617+
assert len(batch_response.responses) == 2
1618+
success_response = batch_response.responses[0]
1619+
assert success_response.message_id == 'message-id'
1620+
assert success_response.success
1621+
assert success_response.exception is None
1622+
error_response = batch_response.responses[1]
1623+
assert error_response.message_id is None
1624+
assert not error_response.success
1625+
assert error_response.exception
1626+
exception = error_response.exception
16051627
assert str(exception) == 'test error'
16061628
assert str(exception.code) == 'invalid-argument'
16071629

16081630
@pytest.mark.parametrize('status', HTTP_ERRORS)
16091631
def test_send_multicast_canonical_error_code(self, status):
1610-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1632+
success_payload = json.dumps({'name': 'message-id'})
1633+
error_payload = json.dumps({
16111634
'error': {
16121635
'status': 'NOT_FOUND',
16131636
'message': 'test error'
16141637
}
1615-
}))
1616-
_ = self._instrument_batch_messaging_service(payload=payload)
1617-
msg = messaging.MulticastMessage(tokens=['foo'])
1638+
})
1639+
_ = self._instrument_batch_messaging_service(
1640+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
1641+
msg = messaging.MulticastMessage(tokens=['foo', 'foo'])
16181642
batch_response = messaging.send_multicast(msg)
1619-
assert batch_response.success_count is 0
1643+
assert batch_response.success_count is 1
16201644
assert batch_response.failure_count is 1
1621-
assert len(batch_response.responses) == 1
1622-
assert not any([r.message_id for r in batch_response.responses])
1623-
assert not all([r.success for r in batch_response.responses])
1624-
exception = batch_response.responses[0].exception
1645+
assert len(batch_response.responses) == 2
1646+
success_response = batch_response.responses[0]
1647+
assert success_response.message_id == 'message-id'
1648+
assert success_response.success
1649+
assert success_response.exception is None
1650+
error_response = batch_response.responses[1]
1651+
assert error_response.message_id is None
1652+
assert not error_response.success
1653+
assert error_response.exception
1654+
exception = error_response.exception
16251655
assert str(exception) == 'test error'
16261656
assert str(exception.code) == 'registration-token-not-registered'
16271657

16281658
@pytest.mark.parametrize('status', HTTP_ERRORS)
1629-
def test_send_multicast_fcm_error_code(self, status):
1630-
payload = self._PAYLOAD_FORMAT.format(str(status), json.dumps({
1659+
def test_send_multicast_canonical_error_code(self, status):
1660+
success_payload = json.dumps({'name': 'message-id'})
1661+
error_payload = json.dumps({
16311662
'error': {
16321663
'status': 'INVALID_ARGUMENT',
16331664
'message': 'test error',
@@ -1638,16 +1669,23 @@ def test_send_multicast_fcm_error_code(self, status):
16381669
},
16391670
],
16401671
}
1641-
}))
1642-
_ = self._instrument_batch_messaging_service(payload=payload)
1643-
msg = messaging.MulticastMessage(tokens=['foo'])
1672+
})
1673+
_ = self._instrument_batch_messaging_service(
1674+
payload=self._batch_payload([(200, success_payload), (status, error_payload)]))
1675+
msg = messaging.MulticastMessage(tokens=['foo', 'foo'])
16441676
batch_response = messaging.send_multicast(msg)
1645-
assert batch_response.success_count is 0
1677+
assert batch_response.success_count is 1
16461678
assert batch_response.failure_count is 1
1647-
assert len(batch_response.responses) == 1
1648-
assert not any([r.message_id for r in batch_response.responses])
1649-
assert not all([r.success for r in batch_response.responses])
1650-
exception = batch_response.responses[0].exception
1679+
assert len(batch_response.responses) == 2
1680+
success_response = batch_response.responses[0]
1681+
assert success_response.message_id == 'message-id'
1682+
assert success_response.success
1683+
assert success_response.exception is None
1684+
error_response = batch_response.responses[1]
1685+
assert error_response.message_id is None
1686+
assert not error_response.success
1687+
assert error_response.exception
1688+
exception = error_response.exception
16511689
assert str(exception) == 'test error'
16521690
assert str(exception.code) == 'registration-token-not-registered'
16531691

0 commit comments

Comments
 (0)