""" :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, USER1_UNI, USER2_UNI, RESOURCE, RESOURCE1_UNI, RESOURCE2_UNI, PLACE_UNI, VARIABLES, PASSWORD, MESSAGE, ONLINE, ERROR) from tests.helpers import mockified from pypsyc.protocol import (AuthenticationError, FriendshipPendingError, FriendshipEstablishedError, EntryDeniedError) from pypsyc.server import Entity from pypsyc.server.db import Database from pypsyc.server.person import Person class TestPerson(object): def setup(self): self.server = Mock() self.server.hostname = SERVER1 self.server.database = Database(':memory:') root = Entity(server=self.server) self.entity = Entity(root, USER1) @mockified('pypsyc.server.person', ['RoutingErrorRelaying']) def test_unknown_target_error(self, RoutingErrorRelaying): RESOURCE1 = USER1_UNI.chain('*resource1') RESOURCE2 = USER1_UNI.chain('*resource2') Entity(self.entity, '*resource1') Entity(self.entity, '*resource2') routing_error_relaying = RoutingErrorRelaying.return_value person = Person(self.entity) assert RoutingErrorRelaying.call_args_list == [((person,),)] person.unknown_target_error(USER2_UNI) assert routing_error_relaying.method_calls == [ ('relay_unknown_target_error', (RESOURCE1, USER2_UNI)), ('relay_unknown_target_error', (RESOURCE2, USER2_UNI))] @mockified('pypsyc.server.person', ['RoutingErrorRelaying']) def test_unknown_target_error(self, RoutingErrorRelaying): RESOURCE1 = USER1_UNI.chain('*resource1') RESOURCE2 = USER1_UNI.chain('*resource2') Entity(self.entity, '*resource1') Entity(self.entity, '*resource2') routing_error_relaying = RoutingErrorRelaying.return_value person = Person(self.entity) assert RoutingErrorRelaying.call_args_list == [((person,),)] person.delivery_failed_error(USER2_UNI, ERROR) assert routing_error_relaying.method_calls == [ ('relay_delivery_failed_error', (RESOURCE1, USER2_UNI, ERROR)), ('relay_delivery_failed_error', (RESOURCE2, USER2_UNI, ERROR))] @mockified('pypsyc.server.person', ['LinkingServer', 'FriendshipProtocol', 'ContextSlave']) def test_authenticate(self, LinkingServer, FriendshipProtocol, ContextSlave): NONCE = 'random_nonce' DIGEST = hmac.new(PASSWORD, NONCE, sha256).digest() circuit = Mock() circuit.allowed_sources = [] friendship_protocol = FriendshipProtocol.return_value context_slave = ContextSlave.return_value person = Person(self.entity) person.register(PASSWORD) assert LinkingServer.call_args_list == [((person,),)] assert_raises(AuthenticationError, person.authenticate, ('hmac', 'wrong', NONCE), None, RESOURCE) sql = "INSERT INTO friendships VALUES(?, ?, 'established')" self.server.database.execute(sql, USER1_UNI, USER2_UNI) person.authenticate(('hmac', DIGEST, NONCE), circuit, RESOURCE) assert self.entity.children[RESOURCE].circuit == circuit assert circuit.allowed_sources == [RESOURCE1_UNI] friendships = {USER2_UNI: {'state': 'established'}} assert friendship_protocol.method_calls == [ ('cast_presence', (7,)), ('send_friendships', (RESOURCE1_UNI, friendships))] assert context_slave.method_calls == [ ('enter', (USER2_UNI, RESOURCE1_UNI))] friendship_protocol.reset_mock() context_slave.reset_mock() person.unlink(RESOURCE) assert self.entity.children == {} assert friendship_protocol.method_calls == [('cast_presence', (1,))] assert context_slave.method_calls == [('leave_all',)] @mockified('pypsyc.server.person', ['MessageRelaying']) def test_message_relay(self, MessageRelaying): message_relaying = MessageRelaying.return_value person = Person(self.entity) assert MessageRelaying.call_args_list == [((person,),)] person.private_message_relay(RESOURCE1_UNI, USER2_UNI, MESSAGE) person.private_message_relay(RESOURCE2_UNI, USER2_UNI, MESSAGE) assert message_relaying.method_calls == [ ('send_private_message', (USER2_UNI, MESSAGE))] @mockified('pypsyc.server.person', ['MessageRelaying']) def test_message(self, MessageRelaying): RESOURCE1 = USER1_UNI.chain('*resource1') RESOURCE2 = USER1_UNI.chain('*resource2') Entity(self.entity, '*resource1') Entity(self.entity, '*resource2') message_relaying = MessageRelaying.return_value person = Person(self.entity) person.private_message(USER2_UNI, MESSAGE) assert message_relaying.method_calls == [ ('relay_private_message', (USER2_UNI, RESOURCE1, MESSAGE)), ('relay_private_message', (USER2_UNI, RESOURCE2, MESSAGE))] @mockified('pypsyc.server.person', ['FriendshipProtocol', 'ContextSlave']) def test_outgoing_friendship(self, FriendshipProtocol, ContextSlave): friendship_protocol = FriendshipProtocol.return_value context_slave = ContextSlave.return_value person = Person(self.entity) person.register('') Entity(self.entity, RESOURCE) person.client_add_friend(USER2_UNI) fs = {'state': 'pending'} assert friendship_protocol.method_calls == [ ('establish', (USER2_UNI,)), ('send_updated_friendship', (RESOURCE1_UNI, USER2_UNI, fs))] friendship_protocol.reset_mock() assert_raises(FriendshipPendingError, person.client_add_friend, USER2_UNI) state = person.friendship_request(USER2_UNI) assert state == 'established' state = person.friendship_request(USER2_UNI) assert state == 'established' fs = {'state': 'established'} assert friendship_protocol.method_calls == [ ('send_updated_friendship', (RESOURCE1_UNI, USER2_UNI, fs))] assert context_slave.method_calls == [('enter', (USER2_UNI,))] assert_raises(FriendshipEstablishedError, person.client_add_friend, USER2_UNI) @mockified('pypsyc.server.person', ['FriendshipProtocol', 'ContextSlave']) def test_incoming_friendship(self, FriendshipProtocol, ContextSlave): friendship_protocol = FriendshipProtocol.return_value context_slave = ContextSlave.return_value person = Person(self.entity) person.register('') Entity(self.entity, RESOURCE) state = person.friendship_request(USER2_UNI) assert state == 'pending' state = person.friendship_request(USER2_UNI) assert state == 'pending' fs = {'state': 'offered'} assert friendship_protocol.method_calls == [ ('send_updated_friendship', (RESOURCE1_UNI, USER2_UNI, fs))] friendship_protocol.reset_mock() person.client_add_friend(USER2_UNI) fs = {'state': 'established'} assert friendship_protocol.method_calls == [ ('establish', (USER2_UNI,)), ('send_updated_friendship', (RESOURCE1_UNI, USER2_UNI, fs))] assert context_slave.method_calls == [('enter', (USER2_UNI,))] assert_raises(FriendshipEstablishedError, person.client_add_friend, USER2_UNI) @mockified('pypsyc.server.person', ['FriendshipProtocol', 'ContextSlave']) def test_cancel_friendship(self, FriendshipProtocol, ContextSlave): friendship_protocol = FriendshipProtocol.return_value context_slave = ContextSlave.return_value person = Person(self.entity) person.register('') Entity(self.entity, RESOURCE) person.friendship_cancel(USER2_UNI) assert context_slave.method_calls == [('leave', (USER2_UNI,))] assert friendship_protocol.method_calls == [ ('send_removed_friendship', (RESOURCE1_UNI, USER2_UNI))] @mockified('pypsyc.server.person', ['FriendshipProtocol', 'ContextSlave']) def test_remove_friend(self, FriendshipProtocol, ContextSlave): friendship_protocol = FriendshipProtocol.return_value context_slave = ContextSlave.return_value person = Person(self.entity) person.register('') Entity(self.entity, RESOURCE) person.client_remove_friend(USER2_UNI) assert context_slave.method_calls == [('leave', (USER2_UNI,))] assert friendship_protocol.method_calls == [ ('remove', (USER2_UNI,)), ('send_removed_friendship', (RESOURCE1_UNI, USER2_UNI))] @mockified('pypsyc.server.person', ['FriendshipProtocol', 'ContextSlave', 'ContextMasterProtocol']) def test_enter_context(self, FriendshipProtocol, ContextSlave, ContextMasterProtocol): cm = self.entity.context_master = Mock() cm.add_member.return_value = VARIABLES person = Person(self.entity) person.register('') person.friendship_request(USER2_UNI) person.client_add_friend(USER2_UNI) assert ContextMasterProtocol.call_args_list == [((person,),)] state = person.enter_request(USER2_UNI) assert state == VARIABLES assert cm.method_calls == [('add_member', (USER2_UNI,))] def test_enter_context_entry_denied(self): person = Person(self.entity) person.register('') assert_raises(EntryDeniedError, person.enter_request, USER2_UNI) def test_leave_context(self): cm = self.entity.context_master = Mock() person = Person(self.entity) person.leave_context(USER2_UNI) assert cm.method_calls == [('remove_member', (USER2_UNI,))] @mockified('pypsyc.server.person', ['FriendshipProtocol']) def test_client_presence(self, FriendshipProtocol): friendship_protocol = FriendshipProtocol.return_value person = Person(self.entity) assert FriendshipProtocol.call_args_list == [((person,),)] person.client_presence(ONLINE) assert friendship_protocol.method_calls == [ ('cast_presence', (ONLINE,))] @mockified('pypsyc.server.person', ['ContextSlave', 'ClientInterfaceProtocol']) def test_client_subscribe(self, ContextSlave, ClientInterfaceProtocol): context_slave = ContextSlave.return_value person = Person(self.entity) assert ContextSlave.call_args_list == [((person,),)] assert ClientInterfaceProtocol.call_args_list == [((person,),)] person.client_subscribe(PLACE_UNI, RESOURCE1_UNI) assert context_slave.method_calls == [ ('enter', (PLACE_UNI, RESOURCE1_UNI))] @mockified('pypsyc.server.person', ['ContextSlave']) def test_client_unsubscribe(self, ContextSlave): context_slave = ContextSlave.return_value person = Person(self.entity) person.client_unsubscribe(PLACE_UNI, RESOURCE1_UNI) assert context_slave.method_calls == [ ('leave', (PLACE_UNI, RESOURCE1_UNI))]