pypsyc/mjacob2/tests/test_protocol.py

397 lines
16 KiB
Python

"""
:copyright: 2010 by Manuel Jacob
:license: MIT
"""
import hmac
from hashlib import sha256
from mock import Mock
from nose.tools import assert_raises
from tests.constants import (SERVER1, USER1, USER2, USER1_UNI, USER2_UNI,
USER1_NICK, RESOURCE, RESOURCE1_UNI, RESOURCE2_UNI, PLACE, PLACE_UNI,
INTERFACE, VARIABLES, PASSWORD, MESSAGE, ONLINE, PENDING, OFFERED,
ESTABLISHED, ERROR)
from tests.helpers import connect_circuits, PlaceHolder
from pypsyc.client.model import ClientCircuit
from pypsyc.core.psyc import PSYCPacket
from pypsyc.protocol import (UnknownTargetError, DeliveryFailedError,
RoutingErrorRoot, RoutingErrorRelaying, RoutingErrorClient,
AuthenticationError, LinkingServer, LinkingClient, Messaging,
MessageRelaying, ConferencingServer, ConferencingClient, EntryDeniedError,
ContextMaster, ContextSlave, UnauthorizedError, ClientInterfaceServer,
ClientInterfaceClient, FriendshipServer, FriendshipClient)
from pypsyc.server import Entity
from pypsyc.server.person import Resource
from pypsyc.server.routing import Routing
def _setup():
server = Mock()
server.hostname = SERVER1
routing = Routing(server.hostname, INTERFACE)
server.routing = routing
routing.init(_entity(server=server))
return routing
def _entity(*args, **kwds):
entity = Entity(*args, **kwds)
entity.package = Mock()
entity.package.entity = entity
return entity
def _c2s_circuit(routing, link_to=None):
sc, cc = connect_circuits(routing.buildProtocol(None), ClientCircuit())
cc.package = Mock()
cc.package.psyc = cc.psyc
if link_to is not None:
Resource(link_to, RESOURCE, sc)
cc.psyc.uni = link_to.uni.chain(RESOURCE)
return sc, cc
def _enter(routing, entity, sc):
routing.mrouting_table[entity.uni].add(sc)
state = entity.context_master.add_member(USER1_UNI)
sc.send({'_context': entity.uni}, PSYCPacket({'=': state}).render())
class TestRoutingErrorProtocol(object):
def setup(self):
routing = _setup()
self.root = routing.root
self.user1 = _entity(routing.root, USER1)
self.sc, self.client = _c2s_circuit(routing, link_to=self.user1)
def test_unknown_target_error(self):
rer = RoutingErrorRoot(self.root.package)
self.client.psyc.add_handler(RoutingErrorClient(self.client.package))
rer.send_unknown_target_error(RESOURCE1_UNI, USER2_UNI)
assert self.client.package.method_calls == [
('unknown_target_error', (USER2_UNI,))]
def test_relay_unknown_target_error1(self):
rer = RoutingErrorRoot(self.root.package)
self.user1.add_handler(RoutingErrorRelaying(self.user1.package))
rer.send_unknown_target_error(USER1_UNI, USER2_UNI)
assert self.user1.package.method_calls == [
('unknown_target_error', (USER2_UNI,))]
def test_relay_unknown_target_error2(self):
rer = RoutingErrorRelaying(self.root.package)
self.client.psyc.add_handler(RoutingErrorClient(self.client.package))
rer.relay_unknown_target_error(RESOURCE1_UNI, USER2_UNI)
assert self.client.package.method_calls == [
('unknown_target_error', (USER2_UNI,))]
def test_delivery_failed_error(self):
rer = RoutingErrorRoot(self.root.package)
self.client.psyc.add_handler(RoutingErrorClient(self.client.package))
rer.send_delivery_failed_error(RESOURCE1_UNI, USER2_UNI, ERROR)
assert self.client.package.method_calls == [
('delivery_failed_error', (USER2_UNI, ERROR))]
def test_relay_delivery_failed_error1(self):
rer = RoutingErrorRoot(self.root.package)
self.user1.add_handler(RoutingErrorRelaying(self.user1.package))
rer.send_delivery_failed_error(USER1_UNI, USER2_UNI, ERROR)
assert self.user1.package.method_calls == [
('delivery_failed_error', (USER2_UNI, ERROR))]
def test_relay_delivery_failed_error2(self):
rer = RoutingErrorRelaying(self.root.package)
self.client.psyc.add_handler(RoutingErrorClient(self.client.package))
rer.relay_delivery_failed_error(RESOURCE1_UNI, USER2_UNI, ERROR)
assert self.client.package.method_calls == [
('delivery_failed_error', (USER2_UNI, ERROR))]
class TestLinkingProtocol(object):
def setup(self):
routing = _setup()
self.user1 = _entity(routing.root, USER1)
self.sc, self.client = _c2s_circuit(routing)
def test_linking(self):
lc = LinkingClient(self.client.package)
self.user1.add_handler(LinkingServer(self.user1.package))
pw = PlaceHolder()
lc.link(USER1_UNI, RESOURCE, PASSWORD)
assert self.user1.package.method_calls == [
('authenticate', (pw, self.sc, RESOURCE))]
assert pw.obj[0] == 'hmac'
assert pw.obj[1] == hmac.new(PASSWORD, pw.obj[2], sha256).digest()
def test_incorrect_password(self):
lc = LinkingClient(self.client.package)
self.user1.add_handler(LinkingServer(self.user1.package))
self.user1.package.authenticate.side_effect = AuthenticationError('xy')
with assert_raises(AuthenticationError) as cm:
lc.link(USER1_UNI, RESOURCE, 'pw')
assert cm.exception.args == ('xy',)
class TestMessagingProtocol(object):
def setup(self):
routing = _setup()
self.user1 = _entity(routing.root, USER1)
self.user2 = _entity(routing.root, USER2)
sc1, self.client1 = _c2s_circuit(routing, link_to=self.user1)
sc2, self.client2 = _c2s_circuit(routing, link_to=self.user2)
def test_private_message(self):
msg1 = Messaging(self.client1.package)
self.client2.psyc.add_handler(Messaging(self.client2.package))
msg1.send_private_message(RESOURCE2_UNI, MESSAGE)
assert self.client2.package.method_calls == [
('private_message', (RESOURCE1_UNI, MESSAGE))]
def test_message_relaying1(self):
msg1 = Messaging(self.client1.package)
self.user1.add_handler(MessageRelaying(self.user1.package))
msg1.send_private_message(USER2_UNI, MESSAGE, relay=USER1_UNI)
assert self.user1.package.method_calls == [
('private_message_relay', (RESOURCE1_UNI, USER2_UNI, MESSAGE))]
def test_message_relaying2(self):
msg_relaying1 = MessageRelaying(self.user1.package)
self.user2.add_handler(MessageRelaying(self.user2.package))
msg_relaying1.send_private_message(USER2_UNI, MESSAGE)
assert self.user2.package.method_calls == [
('private_message', (USER1_UNI, MESSAGE))]
def test_message_relaying3(self):
msg_relaying2 = MessageRelaying(self.user2.package)
self.client2.psyc.add_handler(Messaging(self.client2.package))
msg_relaying2.relay_private_message(USER1_UNI, RESOURCE2_UNI, MESSAGE)
assert self.client2.package.method_calls == [
('private_message', (USER1_UNI, MESSAGE))]
class TestConferencingProtocol(object):
def setup(self):
routing = self.routing = _setup()
self.place = _entity(routing.root, PLACE)
self.user1 = _entity(routing.root, USER1)
self.user2 = _entity(routing.root, USER2)
self.sc1, self.client1 = _c2s_circuit(routing, link_to=self.user1)
self.sc2, self.client2 = _c2s_circuit(routing, link_to=self.user2)
_enter(routing, self.place, self.sc1)
def test_cast_member(self):
con_server = ConferencingServer(self.place.package)
self.client1.add_pvar_handler(ConferencingClient(self.client1.package))
self.client2.add_pvar_handler(ConferencingClient(self.client2.package))
con_server.cast_member_entered(USER1_UNI, USER1_NICK)
assert self.client1.package.method_calls == [
('member_entered', (PLACE_UNI, USER1_UNI, USER1_NICK))]
_enter(self.routing, self.place, self.sc2)
assert self.client2.package.method_calls == [
('member_entered', (PLACE_UNI, USER1_UNI, USER1_NICK))]
self.client1.package.reset_mock()
con_server.cast_member_left(USER1_UNI)
assert self.client1.package.method_calls == [
('member_left', (PLACE_UNI, USER1_UNI))]
def test_public_message1(self):
con_client = ConferencingClient(self.client1.package)
self.place.add_handler(ConferencingServer(self.place.package))
con_client.send_public_message(PLACE_UNI, MESSAGE)
assert self.place.package.method_calls == [
('public_message', (RESOURCE1_UNI, MESSAGE))]
def test_public_message2(self):
con_server = ConferencingServer(self.place.package)
self.client1.psyc.add_handler(ConferencingClient(self.client1.package))
self.client2.psyc.add_handler(ConferencingClient(self.client2.package))
con_server.cast_public_message(USER1_UNI, MESSAGE)
assert self.client1.package.method_calls == [
('public_message', (PLACE_UNI, USER1_UNI, MESSAGE))]
class TestContextProtocol(object):
def setup(self):
routing = _setup()
self.place = _entity(routing.root, PLACE)
self.user1 = _entity(routing.root, USER1)
def test_enter(self):
cs = ContextSlave(self.user1.package)
self.place.add_handler(ContextMaster(self.place.package))
self.place.package.enter_request.return_value = VARIABLES
state = cs.enter(PLACE_UNI)
assert state == VARIABLES
assert self.place.package.method_calls == [
('enter_request', (USER1_UNI,))]
def test_enter_denied(self):
cs = ContextSlave(self.user1.package)
self.place.add_handler(ContextMaster(self.place.package))
self.place.package.enter_request.side_effect = EntryDeniedError('xy')
with assert_raises(EntryDeniedError) as cm:
cs.enter(PLACE_UNI)
assert cm.exception.args == ('xy',)
def test_leave(self):
cs = ContextSlave(self.user1.package)
self.place.add_handler(ContextMaster(self.place.package))
cs.leave(PLACE_UNI)
assert self.place.package.method_calls == [
('leave_context', (USER1_UNI,))]
class TestClientInterface(object):
def setup(self):
routing = self.routing = _setup()
self.user1 = _entity(routing.root, USER1)
_, self.client = _c2s_circuit(routing, link_to=self.user1)
self.client.package.uni = USER1_UNI
self.ci_client = ClientInterfaceClient(self.client.package)
self.user1.add_handler(ClientInterfaceServer(self.user1.package))
def test_unauthorized(self):
user2 = _entity(self.routing.root, USER2)
_, client2 = _c2s_circuit(self.routing, link_to=user2)
client2.package.uni = USER1_UNI
ci_client2 = ClientInterfaceClient(client2.package)
assert_raises(UnauthorizedError, ci_client2.subscribe, PLACE_UNI)
assert self.user1.package.method_calls == []
def test_unknown_target_error(self):
error = UnknownTargetError('xy')
self.user1.package.client_subscribe.side_effect = error
with assert_raises(UnknownTargetError) as cm:
self.ci_client.subscribe(PLACE_UNI)
assert cm.exception.args == ('xy',)
def test_delivery_failed_error(self):
error = DeliveryFailedError('x', 'y')
self.user1.package.client_subscribe.side_effect = error
with assert_raises(DeliveryFailedError) as cm:
self.ci_client.subscribe(PLACE_UNI)
assert cm.exception.args == ('x', 'y')
def test_subscribe(self):
self.ci_client.subscribe(PLACE_UNI)
assert self.user1.package.method_calls == [
('client_subscribe', (PLACE_UNI, RESOURCE1_UNI))]
def test_unsubscribe(self):
self.ci_client.unsubscribe(PLACE_UNI)
assert self.user1.package.method_calls == [
('client_unsubscribe', (PLACE_UNI, RESOURCE1_UNI))]
def test_presence(self):
self.ci_client.cast_presence(ONLINE)
assert self.user1.package.method_calls == [
('client_presence', (ONLINE,))]
def test_add_friend(self):
self.ci_client.add_friend(USER2_UNI)
assert self.user1.package.method_calls == [
('client_add_friend', (USER2_UNI,))]
def test_remove_friend(self):
self.ci_client.remove_friend(USER2_UNI)
assert self.user1.package.method_calls == [
('client_remove_friend', (USER2_UNI,))]
class TestFriendshipProtocol(object):
def setup(self):
routing = _setup()
self.user1 = _entity(routing.root, USER1)
self.user2 = _entity(routing.root, USER2)
sc1, self.client1 = _c2s_circuit(routing, link_to=self.user1)
sc2, self.client2 = _c2s_circuit(routing, link_to=self.user2)
routing.mrouting_table[USER1_UNI] = [sc2]
def test_establish_pending(self):
friendship_server1 = FriendshipServer(self.user1.package)
self.user2.add_handler(FriendshipServer(self.user2.package))
self.user2.package.friendship_request.return_value = PENDING
state = friendship_server1.establish(USER2_UNI)
assert state == PENDING
assert self.user2.package.method_calls == [
('friendship_request', (USER1_UNI,))]
def test_establish_established(self):
friendship_server1 = FriendshipServer(self.user1.package)
self.user2.add_handler(FriendshipServer(self.user2.package))
self.user2.package.friendship_request.return_value = ESTABLISHED
state = friendship_server1.establish(USER2_UNI)
assert state == ESTABLISHED
assert self.user2.package.method_calls == [
('friendship_request', (USER1_UNI,))]
def test_remove(self):
friendship_server1 = FriendshipServer(self.user1.package)
self.user2.add_handler(FriendshipServer(self.user2.package))
friendship_server1.remove(USER2_UNI)
assert self.user2.package.method_calls == [
('friendship_cancel', (USER1_UNI,))]
def test_friendships(self):
friendship_server = FriendshipServer(self.user1.package)
self.client1.psyc.add_handler(FriendshipClient(self.client1.package))
friendship_server.send_friendships(RESOURCE1_UNI, {
USER1_UNI: {'state': ESTABLISHED},
USER2_UNI: {'state': OFFERED}})
friendship_server.send_friendships(RESOURCE1_UNI, {})
assert self.client1.package.method_calls == [
('friendship', (USER1_UNI, ESTABLISHED)),
('friendship', (USER2_UNI, OFFERED))]
def test_updated_friendship(self):
friendship_server = FriendshipServer(self.user1.package)
self.client1.psyc.add_handler(FriendshipClient(self.client1.package))
friendship_server.send_updated_friendship(RESOURCE1_UNI, USER1_UNI,
{'state': 'established'})
assert self.client1.package.method_calls == [
('friendship', (USER1_UNI, ESTABLISHED))]
def test_removed_friendship(self):
friendship_server = FriendshipServer(self.user1.package)
self.client1.psyc.add_handler(FriendshipClient(self.client1.package))
friendship_server.send_removed_friendship(RESOURCE1_UNI, USER1_UNI)
assert self.client1.package.method_calls == [
('friendship_removed', (USER1_UNI,))]
def test_presence(self):
friendship_server = FriendshipServer(self.user1.package)
self.client2.add_pvar_handler(FriendshipClient(self.client2.package))
friendship_server.cast_presence(ONLINE)
assert self.client2.package.method_calls == [
('presence', (USER1_UNI, ONLINE))]