""" :copyright: 2010 by Manuel Jacob :license: MIT """ from mock import Mock from nose.tools import assert_raises from tests.constants import (SERVER1, SERVER2, SERVER1_UNI, SERVER2_UNI, SERVER3_UNI, USER1, USER2, USER1_UNI, USER2_UNI, RESOURCE, RESOURCE1_UNI, RESOURCE2_UNI, PLACE_UNI, INTERFACE, IP, PORT, CONTENT) from tests.helpers import (inited_header, connect_circuits, mockified, AsyncMethod, PlaceHolder) from pypsyc.core.mmp import Uni from pypsyc.protocol import Error from pypsyc.server.routing import (InvalidTargetError, InvalidSourceError, ServerCircuit, _TreeNode, Routing) from pypsyc.util import DNSError class TestServerCircuit(object): def setup(self): self.sc = ServerCircuit() self.sc.factory = self.routing = Mock() self.sc.psyc = Mock() self.sc.allowed_sources.append(SERVER2_UNI) def _send(self, header): self.sc.packet_received(inited_header(header), CONTENT) def test_withtarget(self): HEADER1 = {'_target': SERVER1_UNI} HEADER2 = {'_target': SERVER1_UNI, '_source': SERVER2_UNI} HEADER3 = {'_target': SERVER1_UNI, '_source': SERVER3_UNI} self._send(HEADER1) assert self.routing.method_calls == [ ('route_singlecast', (HEADER1, CONTENT))] self._send(HEADER2) assert self.routing.method_calls == [ ('route_singlecast', (HEADER1, CONTENT)), ('route_singlecast', (HEADER2, CONTENT))] self._send(HEADER3) assert self.routing.method_calls == [ ('route_singlecast', (HEADER1, CONTENT)), ('route_singlecast', (HEADER2, CONTENT))] def test_withouttarget(self): HEADER1 = {} HEADER2 = {'_source': SERVER2_UNI} HEADER3 = {'_source': SERVER3_UNI} self._send(HEADER1) assert self.routing.method_calls == [] assert self.sc.psyc.method_calls == [ ('handle_packet', (HEADER1, CONTENT))] self._send(HEADER2) assert self.routing.method_calls == [] assert self.sc.psyc.method_calls == [ ('handle_packet', (HEADER1, CONTENT)), ('handle_packet', (HEADER2, CONTENT))] self._send(HEADER3) assert self.routing.method_calls == [] assert self.sc.psyc.method_calls == [ ('handle_packet', (HEADER1, CONTENT)), ('handle_packet', (HEADER2, CONTENT))] def test_context(self): HEADER1 = {'_context': PLACE_UNI} HEADER2 = {'_context': PLACE_UNI, '_target': USER1_UNI} self._send(HEADER1) assert self.routing.method_calls == [ ('route_multicast', (HEADER1, CONTENT))] self._send(HEADER2) assert self.routing.method_calls == [ ('route_multicast', (HEADER1, CONTENT)), ('route_singlecast', (HEADER2, CONTENT))] def test_context_withsource(self): HEADER1 = {'_context': PLACE_UNI, '_source': USER1_UNI} HEADER2 = {'_context': PLACE_UNI, '_source': USER2_UNI, '_target': USER1_UNI} assert_raises(NotImplementedError, self._send, HEADER1) assert self.routing.method_calls == [] assert_raises(NotImplementedError, self._send, HEADER2) assert self.routing.method_calls == [] def test_verification(self): sc1, sc2 = connect_circuits(ServerCircuit(), ServerCircuit()) sc2.factory = Mock() sc1.request_verification(SERVER1_UNI, SERVER2_UNI) assert sc2.factory.method_calls == [ ('verify_address', (sc2, SERVER1_UNI, SERVER2_UNI))] assert type(sc2.factory.method_calls[0][1][1]) is Uni assert sc1.allowed_sources == [SERVER2_UNI] assert sc2.allowed_sources == [SERVER1_UNI] assert type(sc2.allowed_sources[0]) is Uni def test_verification_invalid_source(self): sc1, sc2 = connect_circuits(ServerCircuit(), ServerCircuit()) sc2.factory = Mock() sc2.factory.verify_address.side_effect = InvalidSourceError assert_raises(InvalidSourceError, sc1.request_verification, SERVER1_UNI, SERVER2_UNI) assert sc1.allowed_sources == [] assert sc2.allowed_sources == [] def test_verification_invalid_target(self): sc1, sc2 = connect_circuits(ServerCircuit(), ServerCircuit()) sc2.factory = Mock() sc2.factory.verify_address.side_effect = InvalidTargetError assert_raises(InvalidTargetError, sc1.request_verification, SERVER1_UNI, SERVER2_UNI) assert sc1.allowed_sources == [] assert sc2.allowed_sources == [] def test_connection_lost(self): root = self.routing.root = _TreeNode() person = Mock() person_entity = _TreeNode(root, USER1) person_entity.packages = {'person': person} self.sc.allowed_sources.append(RESOURCE1_UNI) self.routing.srouting_table = {SERVER2: Mock()} self.sc.connectionLost(None) assert self.routing.srouting_table == {} assert person.method_calls == [('unlink', (RESOURCE,))] def test_treenode(): root = _TreeNode() assert root._root == root n1 = _TreeNode(root, 'n1') assert root.children == {'n1': n1} assert n1._parent == root assert n1._root == root n2 = _TreeNode(n1, 'n2') assert n1.children == {'n2': n2} assert n2._parent == n1 assert n2._root == root class StubEntity(_TreeNode): def __init__(self, *args, **kwds): _TreeNode.__init__(self, *args, **kwds) self.headers = [] def handle_packet(self, header, contents): self.headers.append(header) EXTERN_HEADER = {'_source': USER1_UNI, '_target': SERVER2_UNI} class TestRouting(object): def test_sroute_local(self): HEADER1 = {'_target': SERVER1_UNI} HEADER2 = {'_target': USER1_UNI} HEADER3 = {'_target': RESOURCE2_UNI} root = StubEntity() user1 = StubEntity(root, USER1) user2 = StubEntity(root, USER2) home = StubEntity(user2, RESOURCE) routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(inited_header(HEADER1), CONTENT) routing.route_singlecast(inited_header(HEADER2), CONTENT) routing.route_singlecast(inited_header(HEADER3), CONTENT) assert root.headers == [HEADER1] assert user1.headers == [HEADER2] assert user2.headers == [] assert home.headers == [HEADER3] def test_sroute_unkown_target(self): HEADER1 = inited_header({'_source': USER1_UNI, '_target': USER2_UNI}) HEADER2 = inited_header({'_target': USER2_UNI, '_tag': 'tag'}) KWDS = {'mc': '_error_unknown_target', '_uni': USER2_UNI, 'data': None} root = StubEntity() root.sendmsg = Mock() routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(HEADER1, CONTENT) routing.route_singlecast(HEADER2, CONTENT) assert root.sendmsg.call_args_list == [ ((USER1_UNI, None, None), KWDS), ((None, None, {'_tag_relay': 'tag'}), KWDS)] assert root.headers == [] def test_sroute_extern(self): routing = Routing(SERVER1, INTERFACE) circuit = routing.srouting_table[SERVER2] = Mock() routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) assert circuit.method_calls == [(('send'), (EXTERN_HEADER, CONTENT))] @mockified('pypsyc.server.routing', ['resolve_hostname', 'connect']) def test_sroute_extern_queued(self, resolve_hostname, connect): resolve_hostname.return_value = IP, PORT connected = connect.side_effect = AsyncMethod() root = Mock() root.uni = SERVER1_UNI routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) assert connect.call_args_list == [ ((IP, PORT, routing), {'bindAddress': (INTERFACE, 0)})] circuit = Mock() connected.callback(circuit) assert circuit.method_calls == [ ('request_verification', (SERVER1_UNI, SERVER2_UNI)), ('send', (EXTERN_HEADER, CONTENT)), ('send', (EXTERN_HEADER, CONTENT))] assert type(circuit.method_calls[0][1][1]) is Uni assert routing.srouting_table == {SERVER2: circuit} assert routing.queues == {} @mockified('pypsyc.server.routing', ['resolve_hostname']) def test_sroute_extern_resolution_fail(self, resolve_hostname): KWDS = {'mc': '_failure_unsuccessful_delivery', '_uni': SERVER2_UNI} resolved = resolve_hostname.side_effect = AsyncMethod() data_ph = KWDS['data'] = PlaceHolder() root = Mock() routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) resolved.errback(DNSError) assert root.method_calls == [ ('sendmsg', (USER1_UNI, None, None), KWDS)] * 2 assert 'resolve' in data_ph.obj assert routing.queues == {} @mockified('pypsyc.server.routing', ['resolve_hostname', 'connect']) def test_sroute_extern_connection_fail(self, resolve_hostname, connect): KWDS = {'mc': '_failure_unsuccessful_delivery', '_uni': SERVER2_UNI} resolve_hostname.return_value = None, None connected = connect.side_effect = AsyncMethod() data_ph = KWDS['data'] = PlaceHolder() root = Mock() routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) connected.errback(Exception('error')) assert root.method_calls == [ ('sendmsg', (USER1_UNI, None, None), KWDS)] assert 'connect' in data_ph.obj assert routing.queues == {} @mockified('pypsyc.server.routing', ['resolve_hostname', 'connect']) def test_sroute_extern_verification_fail(self, resolve_hostname, connect): KWDS = {'mc': '_failure_unsuccessful_delivery', '_uni': SERVER2_UNI} resolve_hostname.return_value = None, None circuit = connect.return_value verified = circuit.request_verification.side_effect = AsyncMethod() data_ph = KWDS['data'] = PlaceHolder() root = Mock() routing = Routing(SERVER1, INTERFACE) routing.init(root) routing.route_singlecast(inited_header(EXTERN_HEADER), CONTENT) verified.errback(Error) assert root.method_calls == [ ('sendmsg', (USER1_UNI, None, None), KWDS)] assert 'verify' in data_ph.obj assert routing.queues == {} @mockified('pypsyc.server.routing', ['resolve_hostname', 'connect']) def test_sroute_extern_no_source(self, resolve_hostname, connect): header = inited_header({'_target': SERVER2_UNI}) header.source = Mock() routing = Routing(SERVER1, INTERFACE) routing.route_singlecast(header, CONTENT) header['_source'] = '' routing.route_singlecast(header, CONTENT) assert resolve_hostname.call_args_list == [] assert connect.call_args_list == [] assert routing.srouting_table == {} assert routing.queues == {} def test_mroute(self): HEADER = {'_context': PLACE_UNI} circuit1 = Mock() circuit2 = Mock() routing = Routing(SERVER1, INTERFACE) routing.mrouting_table[PLACE_UNI] = [circuit1, circuit2] routing.route_multicast(inited_header(HEADER), iter(CONTENT)) assert circuit1.method_calls == [('send', (HEADER, CONTENT))] assert circuit2.method_calls == [('send', (HEADER, CONTENT))] @mockified('pypsyc.server.routing', ['reactor']) def test_listen(self, reactor): routing = Routing(SERVER1, INTERFACE) routing.listen(PORT) assert reactor.method_calls == [ ('listenTCP', (PORT, routing), {'interface': INTERFACE})] def _setup_verification(self): root = Mock() root.uni = SERVER1_UNI routing = Routing(SERVER1, INTERFACE) routing.init(root) circuit = Mock() circuit.transport.client = IP, 35771 return routing, circuit @mockified('pypsyc.server.routing', ['resolve_hostname']) def test_verification(self, resolve_hostname): resolve_hostname.return_value = IP, PORT routing, circuit = self._setup_verification() routing.verify_address(circuit, SERVER2_UNI, SERVER1_UNI) assert resolve_hostname.call_args_list == [((SERVER2,),)] assert routing.srouting_table == {SERVER2: circuit} @mockified('pypsyc.server.routing', ['resolve_hostname']) def test_verification_invalid_target(self, resolve_hostname): routing, circuit = self._setup_verification() assert_raises(InvalidTargetError, routing.verify_address, circuit, SERVER2_UNI, SERVER3_UNI) assert resolve_hostname.call_args_list == [] assert routing.srouting_table == {} @mockified('pypsyc.server.routing', ['resolve_hostname']) def test_verification_invalid_source(self, resolve_hostname): resolve_hostname.return_value = '10.0.0.2', PORT routing, circuit = self._setup_verification() assert_raises(InvalidSourceError, routing.verify_address, circuit, SERVER2_UNI, SERVER1_UNI) assert resolve_hostname.call_args_list == [((SERVER2,),)] assert routing.srouting_table == {}