1
# Copyright (C) 2006 Canonical Ltd
1
# Copyright (C) 2006, 2007 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
782
782
"""Error reported by server with no specific representation"""
783
783
self._captureVar('NO_SMART_VFS', None)
784
784
class FlakyTransport(object):
785
786
def get_bytes(self, path):
786
787
raise Exception("some random exception from inside server")
787
788
smart_server = server.SmartTCPServer(backing_transport=FlakyTransport())
819
820
self.server = server.SmartTCPServer(self.backing_transport)
820
821
self.server.start_background_thread()
821
822
self.transport = remote.SmartTCPTransport(self.server.get_url())
823
self.addCleanup(self.tearDownServer)
825
def tearDownServer(self):
824
826
if getattr(self, 'transport', None):
825
827
self.transport.disconnect()
826
829
if getattr(self, 'server', None):
827
830
self.server.stop_background_thread()
828
super(SmartTCPTests, self).tearDown()
834
class TestServerSocketUsage(SmartTCPTests):
836
def test_server_setup_teardown(self):
837
"""It should be safe to teardown the server with no requests."""
840
transport = remote.SmartTCPTransport(self.server.get_url())
841
self.tearDownServer()
842
self.assertRaises(errors.ConnectionError, transport.has, '.')
844
def test_server_closes_listening_sock_on_shutdown_after_request(self):
845
"""The server should close its listening socket when it's stopped."""
848
self.transport.has('.')
849
self.tearDownServer()
850
# if the listening socket has closed, we should get a BADFD error
851
# when connecting, rather than a hang.
852
transport = remote.SmartTCPTransport(server.get_url())
853
self.assertRaises(errors.ConnectionError, transport.has, '.')
831
856
class WritableEndToEndTests(SmartTCPTests):
832
857
"""Client to server tests that require a writable transport."""
917
942
self.setUpServer(readonly=True)
918
943
self.assertRaises(errors.TransportNotPossible, self.transport.mkdir,
947
class TestServerHooks(SmartTCPTests):
949
def capture_server_call(self, backing_url, public_url):
950
"""Record a server_started|stopped hook firing."""
951
self.hook_calls.append((backing_url, public_url))
953
def test_server_started_hook(self):
954
"""The server_started hook fires when the server is started."""
956
server.SmartTCPServer.hooks.install_hook('server_started',
957
self.capture_server_call)
959
# at this point, the server will be starting a thread up.
960
# there is no indicator at the moment, so bodge it by doing a request.
961
self.transport.has('.')
962
self.assertEqual([(self.backing_transport.base, self.transport.base)],
965
def test_server_stopped_hook_simple(self):
966
"""The server_stopped hook fires when the server is stopped."""
968
server.SmartTCPServer.hooks.install_hook('server_stopped',
969
self.capture_server_call)
971
result = [(self.backing_transport.base, self.transport.base)]
972
# check the stopping message isn't emitted up front.
973
self.assertEqual([], self.hook_calls)
974
# nor after a single message
975
self.transport.has('.')
976
self.assertEqual([], self.hook_calls)
977
# clean up the server
978
self.tearDownServer()
979
# now it should have fired.
980
self.assertEqual(result, self.hook_calls)
982
# TODO: test that when the server suffers an exception that it calls the
983
# server-stopped hook.
922
986
class SmartServerCommandTests(tests.TestCaseWithTransport):
923
987
"""Tests that call directly into the command objects, bypassing the network