pypsyc/mjacob2/tests/test_server/test_routing.py

354 lines
14 KiB
Python

"""
: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 == {}