@@ -53,8 +53,15 @@ def test_invalid_tokens_type(self, tokens):
53
53
expected = 'MulticastMessage.tokens must be a list of strings.'
54
54
assert str (excinfo .value ) == expected
55
55
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
+
56
62
def test_tokens_type (self ):
57
63
messaging .MulticastMessage (tokens = ['token' ])
64
+ messaging .MulticastMessage (tokens = ['token' for i in xrange (0 , 100 )])
58
65
59
66
60
67
class TestMessageEncoder (object ):
@@ -1335,12 +1342,7 @@ def test_send_fcm_error_code(self, status):
1335
1342
assert json .loads (recorder [0 ].body .decode ()) == body
1336
1343
1337
1344
1338
- class TestSendAll (object ):
1339
-
1340
- _PAYLOAD_FORMAT = """--boundary\r \n Content-Type: application/http\r \n \
1341
- Content-ID: <uuid + 1>\r \n \r \n HTTP/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 ):
1344
1346
1345
1347
@classmethod
1346
1348
def setup_class (cls ):
@@ -1364,8 +1366,19 @@ def _instrument_batch_messaging_service(self, app=None, status=200, payload=''):
1364
1366
])
1365
1367
return fcm_service
1366
1368
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 \n Content-Type: application/http\r \n \
1373
+ Content-ID: <uuid + {}>\r \n \r \n HTTP/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 ):
1369
1382
1370
1383
def test_no_project_id (self ):
1371
1384
def evaluate ():
@@ -1385,62 +1398,86 @@ def test_invalid_send_all(self, msg):
1385
1398
expected = 'Messages must be an list of messaging.Message instances.'
1386
1399
assert str (excinfo .value ) == expected
1387
1400
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
+
1388
1408
def test_send_all (self ):
1389
1409
payload = json .dumps ({'name' : 'message-id' })
1390
1410
_ = self ._instrument_batch_messaging_service (
1391
- payload = self ._PAYLOAD_FORMAT . format ( ' 200' , payload ))
1411
+ payload = self ._batch_payload ([( 200 , payload ), ( 200 , payload )] ))
1392
1412
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
1395
1415
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' ]
1398
1418
assert all ([r .success for r in batch_response .responses ])
1399
1419
assert not any ([r .exception for r in batch_response .responses ])
1400
1420
1401
1421
@pytest .mark .parametrize ('status' , HTTP_ERRORS )
1402
1422
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 ({
1404
1425
'error' : {
1405
1426
'status' : 'INVALID_ARGUMENT' ,
1406
1427
'message' : 'test error'
1407
1428
}
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 )]))
1410
1432
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
1413
1435
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
1418
1446
assert str (exception ) == 'test error'
1419
1447
assert str (exception .code ) == 'invalid-argument'
1420
1448
1421
1449
@pytest .mark .parametrize ('status' , HTTP_ERRORS )
1422
1450
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 ({
1424
1453
'error' : {
1425
1454
'status' : 'NOT_FOUND' ,
1426
1455
'message' : 'test error'
1427
1456
}
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 )]))
1430
1460
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
1433
1463
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
1438
1474
assert str (exception ) == 'test error'
1439
1475
assert str (exception .code ) == 'registration-token-not-registered'
1440
1476
1441
1477
@pytest .mark .parametrize ('status' , HTTP_ERRORS )
1442
1478
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 ({
1444
1481
'error' : {
1445
1482
'status' : 'INVALID_ARGUMENT' ,
1446
1483
'message' : 'test error' ,
@@ -1451,16 +1488,23 @@ def test_send_all_fcm_error_code(self, status):
1451
1488
},
1452
1489
],
1453
1490
}
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 )]))
1456
1494
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
1459
1497
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
1464
1508
assert str (exception ) == 'test error'
1465
1509
assert str (exception .code ) == 'registration-token-not-registered'
1466
1510
@@ -1526,37 +1570,7 @@ def test_send_all_batch_fcm_error_code(self, status):
1526
1570
assert str (excinfo .value .code ) == 'registration-token-not-registered'
1527
1571
1528
1572
1529
- class TestSendMulticast (object ):
1530
-
1531
- _PAYLOAD_FORMAT = """--boundary\r \n Content-Type: application/http\r \n \
1532
- Content-ID: <uuid + 1>\r \n \r \n HTTP/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 ):
1560
1574
1561
1575
def test_no_project_id (self ):
1562
1576
def evaluate ():
@@ -1575,59 +1589,76 @@ def test_invalid_send_multicast(self, msg):
1575
1589
def test_send_multicast (self ):
1576
1590
payload = json .dumps ({'name' : 'message-id' })
1577
1591
_ = 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' ])
1580
1594
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
1582
1596
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' ]
1585
1599
assert all ([r .success for r in batch_response .responses ])
1586
1600
assert not any ([r .exception for r in batch_response .responses ])
1587
1601
1588
1602
@pytest .mark .parametrize ('status' , HTTP_ERRORS )
1589
1603
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 ({
1591
1606
'error' : {
1592
1607
'status' : 'INVALID_ARGUMENT' ,
1593
1608
'message' : 'test error'
1594
1609
}
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' ])
1598
1614
batch_response = messaging .send_multicast (msg )
1599
- assert batch_response .success_count is 0
1615
+ assert batch_response .success_count is 1
1600
1616
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
1605
1627
assert str (exception ) == 'test error'
1606
1628
assert str (exception .code ) == 'invalid-argument'
1607
1629
1608
1630
@pytest .mark .parametrize ('status' , HTTP_ERRORS )
1609
1631
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 ({
1611
1634
'error' : {
1612
1635
'status' : 'NOT_FOUND' ,
1613
1636
'message' : 'test error'
1614
1637
}
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' ])
1618
1642
batch_response = messaging .send_multicast (msg )
1619
- assert batch_response .success_count is 0
1643
+ assert batch_response .success_count is 1
1620
1644
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
1625
1655
assert str (exception ) == 'test error'
1626
1656
assert str (exception .code ) == 'registration-token-not-registered'
1627
1657
1628
1658
@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 ({
1631
1662
'error' : {
1632
1663
'status' : 'INVALID_ARGUMENT' ,
1633
1664
'message' : 'test error' ,
@@ -1638,16 +1669,23 @@ def test_send_multicast_fcm_error_code(self, status):
1638
1669
},
1639
1670
],
1640
1671
}
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' ])
1644
1676
batch_response = messaging .send_multicast (msg )
1645
- assert batch_response .success_count is 0
1677
+ assert batch_response .success_count is 1
1646
1678
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
1651
1689
assert str (exception ) == 'test error'
1652
1690
assert str (exception .code ) == 'registration-token-not-registered'
1653
1691
0 commit comments