mirror of git://git.psyced.org/git/pypsyc
397 lines
16 KiB
Python
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))]
|