""" :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))]