1439
1439
"""Fake get_root."""
1440
1440
d.callback(mdid)
1442
class FakeClient(object):
1444
def __getattribute__(self, attr):
1445
"""Return a noop."""
1446
return lambda *args, **kwargs: None
1448
self.action_queue.client = FakeClient()
1442
self.action_queue.client = DummyClass()
1449
1443
self.action_queue.get_root = get_root
1450
1444
self.action_queue.server_rescan('foo', lambda: list())
1451
1445
def check(result):
1452
1446
self.assertEquals('foo', result)
1453
1447
d.addCallback(check)
1451
class SpecificException(Exception):
1452
"""The specific exception."""
1455
class SillyClass(object):
1456
"""Silly class that accepts the set of any attribute.
1458
We can't use object() directly, since its raises AttributeError.
1463
class ErrorHandlingTestCase(BasicTestCase):
1464
"""Error handling tests for ActionQueue."""
1468
BasicTestCase.setUp(self)
1471
self.action_queue.client = SillyClass()
1472
self.action_queue.deferred = defer.Deferred()
1473
self.patch(self.main, 'restart', lambda: None)
1477
def fail_please(self, an_exception):
1478
"""Raise the given exception."""
1479
def inner(*args, **kwargs):
1480
"""A request to the server that fails."""
1482
return defer.fail(an_exception)
1485
def succeed_please(self, result):
1486
"""Return the given result."""
1487
def inner(*args, **kwargs):
1488
"""A request to the server that succeeds."""
1490
return defer.succeed(result)
1493
def mock_caps(self, accepted):
1494
"""Reply to query caps with False."""
1495
def gset_caps(caps):
1496
"""get/set caps helper."""
1499
req.accepted = accepted
1500
return defer.succeed(req)
1503
def test_valid_event(self):
1504
"""SYS_SERVER_ERROR is valid in EventQueue."""
1505
event = 'SYS_SERVER_ERROR'
1506
self.assertTrue(event in EVENTS)
1507
self.assertEquals(('error',), EVENTS[event])
1509
@defer.inlineCallbacks
1510
def test_send_request_and_handle_errors_on_no_error(self):
1511
"""_send_request_and_handle_errors is correct when no error."""
1513
event = 'SYS_SPECIFIC_OK'
1514
EVENTS[event] = () # add event to the global valid events list
1515
self.addCleanup(lambda: EVENTS.pop(event))
1518
request = self.succeed_please(result)
1519
kwargs = dict(request=request, request_error=SpecificException,
1520
event_error='YADDA_YADDA', event_ok=event,
1521
args=(1, 2), kwargs={})
1522
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1523
actual_result = yield d
1525
self.assertTrue(self.called, 'the request was called')
1526
self.assertEqual(actual_result, result)
1527
self.assertEqual((event, (), {}),
1528
self.action_queue.event_queue.events[-1])
1530
# assert over logging
1531
self.assertEqual(1, len(self.handler.records))
1532
self.assertIn(request.__name__, self.handler.records[0].message)
1533
self.assertIn('OK', self.handler.records[0].message)
1535
# assert internal deferred wasn't fired
1536
self.assertFalse(self.action_queue.deferred.called)
1538
@defer.inlineCallbacks
1539
def test_send_request_and_handle_errors_with_no_event_ok(self):
1540
"""_send_request_and_handle_errors does not push event if is None."""
1541
original_events = self.action_queue.event_queue.events[:]
1544
request = self.succeed_please(result)
1545
kwargs = dict(request=request, request_error=SpecificException,
1546
event_error='YADDA_YADDA', event_ok=None)
1547
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1548
actual_result = yield d
1550
self.assertTrue(self.called, 'the request was called')
1551
self.assertEqual(actual_result, result)
1552
self.assertEqual(original_events,
1553
self.action_queue.event_queue.events)
1555
# assert over logging
1556
self.assertEqual(1, len(self.handler.records))
1557
self.assertIn(request.__name__, self.handler.records[0].message)
1558
self.assertIn('OK', self.handler.records[0].message)
1560
# assert internal deferred wasn't fired
1561
self.assertFalse(self.action_queue.deferred.called)
1563
@defer.inlineCallbacks
1564
def test_send_request_and_handle_errors_on_valid_error(self):
1565
"""_send_request_and_handle_errors is correct when expected error."""
1567
event = 'SYS_SPECIFIC_ERROR'
1568
EVENTS[event] = ('error',) # add event to the global valid events list
1569
self.addCleanup(lambda: EVENTS.pop(event))
1571
exc = SpecificException('The request failed! please be happy.')
1572
request = self.fail_please(exc)
1573
kwargs = dict(request=request, request_error=SpecificException,
1574
event_error=event, event_ok='YADDA_YADDA')
1575
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1578
self.assertTrue(self.called, 'the request was called')
1579
self.assertEqual((event, (), {'error': str(exc)}),
1580
self.action_queue.event_queue.events[-1])
1582
# assert over logging
1583
self.assertEqual(1, len(self.handler.records))
1584
self.assertIn(request.__name__, self.handler.records[0].message)
1585
self.assertIn(str(exc), self.handler.records[0].message)
1587
# assert internal deferred was fired
1588
self.assertTrue(self.action_queue.deferred.called)
1589
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1590
self.assertEqual(self.action_queue.deferred.result.value, exc)
1592
@defer.inlineCallbacks
1593
def assert_send_request_and_handle_errors_on_server_error(self, serr):
1594
"""_send_request_and_handle_errors is correct when server error."""
1595
# XXX: we need to replace this list with and exception list
1596
# once bug #557718 is resolved
1597
msg = protocol_pb2.Message()
1598
msg.type = protocol_pb2.Message.ERROR
1599
msg.error.type = serr
1600
msg.error.comment = 'Error message for %s.' % serr
1601
exc = errors.error_to_exception(serr)(request=None, message=msg)
1603
request = self.fail_please(exc)
1604
kwargs = dict(request=request, request_error=SpecificException,
1605
event_error='BAR', event_ok='FOO')
1606
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1609
self.assertEqual(( 'SYS_SERVER_ERROR', (), {'error': str(exc)}),
1610
self.action_queue.event_queue.events[-1])
1612
# assert over logging
1613
self.assertTrue(len(self.handler.records) > 0)
1614
self.assertIn(request.__name__, self.handler.records[-1].message)
1615
self.assertIn(str(exc), self.handler.records[-1].message)
1617
# assert internal deferred was fired
1618
self.assertTrue(self.action_queue.deferred.called)
1619
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1620
self.assertEqual(self.action_queue.deferred.result.value, exc)
1622
@defer.inlineCallbacks
1623
def test_send_request_and_handle_errors_on_try_again(self):
1624
"""_send_request_and_handle_errors is correct when server error."""
1625
serr = protocol_pb2.Error.TRY_AGAIN
1626
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1628
@defer.inlineCallbacks
1629
def test_send_request_and_handle_errors_on_internal_error(self):
1630
"""_send_request_and_handle_errors is correct when server error."""
1631
serr = protocol_pb2.Error.INTERNAL_ERROR
1632
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1634
@defer.inlineCallbacks
1635
def test_send_request_and_handle_errors_on_protocol_error(self):
1636
"""_send_request_and_handle_errors is correct when server error."""
1637
serr = protocol_pb2.Error.PROTOCOL_ERROR
1638
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1640
@defer.inlineCallbacks
1641
def test_send_request_and_handle_errors_on_unsupported_version(self):
1642
"""_send_request_and_handle_errors is correct when server error."""
1643
serr = protocol_pb2.Error.UNSUPPORTED_VERSION
1644
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1646
@defer.inlineCallbacks
1647
def test_send_request_and_handle_errors_on_authetication_failed(self):
1648
"""_send_request_and_handle_errors is correct when server error."""
1649
serr = protocol_pb2.Error.AUTHENTICATION_FAILED
1650
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1652
@defer.inlineCallbacks
1653
def test_send_request_and_handle_errors_on_no_permission(self):
1654
"""_send_request_and_handle_errors is correct when server error."""
1655
serr = protocol_pb2.Error.NO_PERMISSION
1656
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1658
@defer.inlineCallbacks
1659
def test_send_request_and_handle_errors_on_already_exists(self):
1660
"""_send_request_and_handle_errors is correct when server error."""
1661
serr = protocol_pb2.Error.ALREADY_EXISTS
1662
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1664
@defer.inlineCallbacks
1665
def test_send_request_and_handle_errors_on_does_not_exist(self):
1666
"""_send_request_and_handle_errors is correct when server error."""
1667
serr = protocol_pb2.Error.DOES_NOT_EXIST
1668
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1670
@defer.inlineCallbacks
1671
def test_send_request_and_handle_errors_on_not_a_dir(self):
1672
"""_send_request_and_handle_errors is correct when server error."""
1673
serr = protocol_pb2.Error.NOT_A_DIRECTORY
1674
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1676
@defer.inlineCallbacks
1677
def test_send_request_and_handle_errors_on_not_empty(self):
1678
"""_send_request_and_handle_errors is correct when server error."""
1679
serr = protocol_pb2.Error.NOT_EMPTY
1680
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1682
@defer.inlineCallbacks
1683
def test_send_request_and_handle_errors_on_not_available(self):
1684
"""_send_request_and_handle_errors is correct when server error."""
1685
serr = protocol_pb2.Error.NOT_AVAILABLE
1686
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1688
@defer.inlineCallbacks
1689
def test_send_request_and_handle_errors_on_upload_in_porgress(self):
1690
"""_send_request_and_handle_errors is correct when server error."""
1691
serr = protocol_pb2.Error.UPLOAD_IN_PROGRESS
1692
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1694
@defer.inlineCallbacks
1695
def test_send_request_and_handle_errors_on_upload_corrupt(self):
1696
"""_send_request_and_handle_errors is correct when server error."""
1697
serr = protocol_pb2.Error.UPLOAD_CORRUPT
1698
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1700
@defer.inlineCallbacks
1701
def test_send_request_and_handle_errors_on_upload_canceled(self):
1702
"""_send_request_and_handle_errors is correct when server error."""
1703
serr = protocol_pb2.Error.UPLOAD_CANCELED
1704
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1706
@defer.inlineCallbacks
1707
def test_send_request_and_handle_errors_on_conflict(self):
1708
"""_send_request_and_handle_errors is correct when server error."""
1709
serr = protocol_pb2.Error.CONFLICT
1710
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1712
@defer.inlineCallbacks
1713
def test_send_request_and_handle_errors_on_quota_exceeded(self):
1714
"""_send_request_and_handle_errors is correct when server error."""
1715
serr = protocol_pb2.Error.QUOTA_EXCEEDED
1716
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1718
@defer.inlineCallbacks
1719
def test_send_request_and_handle_errors_on_invalid_filename(self):
1720
"""_send_request_and_handle_errors is correct when server error."""
1721
serr = protocol_pb2.Error.INVALID_FILENAME
1722
yield self.assert_send_request_and_handle_errors_on_server_error(serr)
1724
@defer.inlineCallbacks
1725
def test_send_request_and_handle_errors_on_unknown_error(self):
1726
"""_send_request_and_handle_errors is correct when unknown error."""
1727
# XXX: we need to replace this list with and exception list
1728
# once bug #557718 is resolved
1729
serr = protocol_pb2.Error.AUTHENTICATION_REQUIRED
1730
msg = protocol_pb2.Message()
1731
msg.type = protocol_pb2.Message.ERROR
1732
msg.error.type = serr
1733
msg.error.comment = 'Error message for %s.' % serr
1734
exc = errors.error_to_exception(serr)(request=None, message=msg)
1736
request = self.fail_please(exc)
1737
kwargs = dict(request=request, request_error=SpecificException,
1738
event_error='BAR', event_ok='FOO')
1739
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1742
self.assertIn(('SYS_UNKNOWN_ERROR', (), {}),
1743
self.action_queue.event_queue.events)
1745
# assert over logging
1746
self.assertEqual(1, len(self.handler.records))
1747
self.assertIn(request.__name__, self.handler.records[0].message)
1748
self.assertIn(str(exc), self.handler.records[0].message)
1750
# assert internal deferred was fired
1751
self.assertTrue(self.action_queue.deferred.called)
1752
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1753
self.assertEqual(self.action_queue.deferred.result.value, exc)
1755
@defer.inlineCallbacks
1756
def test_send_request_and_handle_errors_on_no_protocol_error(self):
1757
"""_send_request_and_handle_errors is correct when no-protocol error."""
1759
event = 'SYS_UNKNOWN_ERROR'
1760
error_msg = 'Error message for any Exception.'
1761
exc = Exception(error_msg)
1762
request = self.fail_please(exc)
1763
kwargs = dict(request=request, request_error=SpecificException,
1764
event_error='BAR', event_ok='FOO')
1765
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1768
self.assertIn((event, (), {}),
1769
self.action_queue.event_queue.events)
1771
# assert over logging
1772
self.assertEqual(1, len(self.handler.records))
1773
self.assertIn(request.__name__, self.handler.records[0].message)
1774
self.assertIn(str(exc), self.handler.records[0].message)
1776
# assert internal deferred was fired
1777
self.assertTrue(self.action_queue.deferred.called)
1778
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1779
self.assertEqual(self.action_queue.deferred.result.value, exc)
1781
@defer.inlineCallbacks
1782
def test_send_request_and_handle_errors_on_client_mismatch(self):
1783
"""_send_request_and_handle_errors is correct when client mismatch."""
1785
def change_client(*args, **kwargs):
1786
"""Change AQ's client while doing the request."""
1787
self.action_queue.client = object()
1789
self.action_queue.event_queue.events = [] # event cleanup
1790
kwargs = dict(request=change_client, request_error=SpecificException,
1791
event_error='BAR', event_ok='FOO')
1792
d = self.action_queue._send_request_and_handle_errors(**kwargs)
1795
self.assertEqual([], self.action_queue.event_queue.events)
1797
# assert over logging
1798
self.assertEqual(1, len(self.handler.records))
1799
self.assertIn(change_client.__name__, self.handler.records[0].message)
1800
self.assertIn('Client mismatch', self.handler.records[0].message)
1802
# assert internal deferred wasn't fired
1803
self.assertFalse(self.action_queue.deferred.called)
1805
@defer.inlineCallbacks
1806
def test_check_version_when_unsupported_version_exception(self):
1807
"""Test error handling after UnsupportedVersionError."""
1808
# raise a UnsupportedVersionError
1809
msg = protocol_pb2.Message()
1810
msg.type = protocol_pb2.Message.ERROR
1811
msg.error.type = protocol_pb2.Error.UNSUPPORTED_VERSION
1812
msg.error.comment = 'This is a funny comment.'
1813
exc = errors.UnsupportedVersionError(request=None, message=msg)
1815
self.action_queue.client.protocol_version = self.fail_please(exc)
1816
yield self.action_queue.check_version()
1817
event = ('SYS_PROTOCOL_VERSION_ERROR', (), {'error': str(exc)})
1818
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1820
@defer.inlineCallbacks
1821
def test_set_capabilities_when_query_caps_not_accepted(self):
1822
"""Test error handling when the query caps are not accepeted."""
1824
# query_caps returns False
1825
self.action_queue.client.query_caps = self.mock_caps(accepted=False)
1827
yield self.action_queue.set_capabilities(caps=None)
1828
msg = "The server doesn't have the requested capabilities"
1829
event = ('SYS_SET_CAPABILITIES_ERROR', (), {'error': msg})
1830
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1831
self.assertNotIn(('SYS_SET_CAPABILITIES_OK', (), {}),
1832
self.action_queue.event_queue.events)
1834
# assert internal deferred was fired
1835
self.assertTrue(self.action_queue.deferred.called)
1836
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1837
self.assertIsInstance(self.action_queue.deferred.result.value,
1839
self.assertEqual(str(self.action_queue.deferred.result.value), msg)
1841
@defer.inlineCallbacks
1842
def test_set_capabilities_when_set_caps_not_accepted(self):
1843
"""Test error handling when the query caps are not accepeted."""
1845
# query_caps returns True and set_caps returns False
1846
self.action_queue.client.query_caps = self.mock_caps(accepted=True)
1847
self.action_queue.client.set_caps = self.mock_caps(accepted=False)
1849
caps = 'very difficult cap'
1850
yield self.action_queue.set_capabilities(caps=caps)
1851
msg = "The server denied setting '%s' capabilities" % caps
1852
event = ('SYS_SET_CAPABILITIES_ERROR', (), {'error': msg})
1853
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1854
self.assertNotIn(('SYS_SET_CAPABILITIES_OK', (), {}),
1855
self.action_queue.event_queue.events)
1857
# assert internal deferred was fired
1858
self.assertTrue(self.action_queue.deferred.called)
1859
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1860
self.assertIsInstance(self.action_queue.deferred.result.value,
1862
self.assertEqual(str(self.action_queue.deferred.result.value), msg)
1864
@defer.inlineCallbacks
1865
def test_set_capabilities_when_client_is_none(self):
1866
"""Test error handling when the client is None."""
1868
self.action_queue.client = None
1870
yield self.action_queue.set_capabilities(caps=None)
1871
msg = "'NoneType' object has no attribute 'query_caps'"
1872
event = ('SYS_SET_CAPABILITIES_ERROR', (), {'error': msg})
1873
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1874
self.assertNotIn(('SYS_SET_CAPABILITIES_OK', (), {}),
1875
self.action_queue.event_queue.events)
1877
# assert internal deferred was fired
1878
self.assertTrue(self.action_queue.deferred.called)
1879
self.assertIsInstance(self.action_queue.deferred.result, Failure)
1880
self.assertIsInstance(self.action_queue.deferred.result.value,
1882
self.assertEqual(str(self.action_queue.deferred.result.value), msg)
1884
@defer.inlineCallbacks
1885
def test_set_capabilities_when_set_caps_is_accepted(self):
1886
"""Test error handling when the query caps are not accepeted."""
1888
# query_caps returns True and set_caps returns True
1889
self.action_queue.client.query_caps = self.mock_caps(accepted=True)
1890
self.action_queue.client.set_caps = self.mock_caps(accepted=True)
1892
yield self.action_queue.set_capabilities(caps=None)
1893
event = ('SYS_SET_CAPABILITIES_OK', (), {})
1894
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1896
# assert internal deferred wasn't fired
1897
self.assertFalse(self.action_queue.deferred.called)
1899
@defer.inlineCallbacks
1900
def test_authenticate_when_authenticated(self):
1901
"""Test error handling after authenticate with no error."""
1903
self.action_queue.client.oauth_authenticate = \
1904
self.succeed_please(result=self.action_queue.client)
1905
yield self.action_queue.authenticate(oauth_consumer=object())
1906
event = ('SYS_AUTH_OK', (), {})
1907
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1909
# assert internal deferred was fired with the client as result
1910
self.assertTrue(self.action_queue.deferred.called)
1911
self.assertTrue(self.action_queue.deferred.result is self.action_queue.client)
1913
@defer.inlineCallbacks
1914
def test_authenticate_when_authentication_failed_exception(self):
1915
"""Test error handling after AuthenticationFailedError."""
1916
# raise a AuthenticationFailedError
1917
msg = protocol_pb2.Message()
1918
msg.type = protocol_pb2.Message.ERROR
1919
msg.error.type = protocol_pb2.Error.AUTHENTICATION_FAILED
1920
msg.error.comment = 'This is a funny comment.'
1921
exc = errors.AuthenticationFailedError(request=None, message=msg)
1923
self.action_queue.client.oauth_authenticate = self.fail_please(exc)
1924
yield self.action_queue.authenticate(oauth_consumer=object())
1925
event = ('SYS_AUTH_ERROR', (), {'error': str(exc)})
1926
self.assertEqual(event, self.action_queue.event_queue.events[-1])
1928
# assert internal deferred was fired
1929
self.assertTrue(self.action_queue.deferred.called)