示例#1
0
    def test_send_to_new_contact_failed_to_connect(self):
        """
        Sending a message to a new but unreachable contact results in the
        resulting deferred to be resolved with the expected exception.
        """
        nc = NetstringConnector(self.event_loop)
        contact = PeerNode(PUBLIC_KEY, self.version,
                           'netstring://192.168.0.1:1908')
        msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
        protocol = mock.MagicMock()

        def side_effect(*args, **kwargs):
            raise ValueError()

        protocol.send_string = mock.MagicMock(side_effect=side_effect)
        sender = Node(PUBLIC_KEY, PRIVATE_KEY, self.event_loop, nc, 1908)

        @asyncio.coroutine
        def faux_connect(protocol=protocol):
            return ('foo', protocol)

        with mock.patch.object(self.event_loop, 'create_connection',
                               return_value=faux_connect()):
            result = nc.send(contact, msg, sender)
            with self.assertRaises(ValueError) as ex:
                self.event_loop.run_until_complete(result)
            self.assertEqual(1, protocol.send_string.call_count)
            self.assertTrue(result.done())
            self.assertEqual(ex.exception, result.exception())
            self.assertNotIn(contact.network_id, nc._connections)
示例#2
0
    def test_send_to_new_contact_successful_connection(self):
        """
        Send a message to a new contact causes a new connection to be made
        whose associated protocol object is cached for later use.
        """
        nc = NetstringConnector(self.event_loop)
        contact = PeerNode(PUBLIC_KEY, self.version,
                           'netstring://192.168.0.1:1908')
        msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
        protocol = mock.MagicMock()
        protocol.send_string = mock.MagicMock()
        sender = Node(PUBLIC_KEY, PRIVATE_KEY, self.event_loop, nc, 1908)

        @asyncio.coroutine
        def faux_connect(protocol=protocol):
            return ('foo', protocol)

        with mock.patch.object(self.event_loop, 'create_connection',
                               return_value=faux_connect()):
            result = nc.send(contact, msg, sender)
            self.event_loop.run_until_complete(result)
            self.assertEqual(1, protocol.send_string.call_count)
            self.assertTrue(result.done())
            self.assertEqual(True, result.result())
            self.assertIn(contact.network_id, nc._connections)
            self.assertEqual(nc._connections[contact.network_id], protocol)
            expected = to_dict(msg)
            actual = json.loads(protocol.send_string.call_args[0][0])
            self.assertEqual(expected, actual)
示例#3
0
 def test_ok(self):
     """
     Expected behaviour of a ok message.
     """
     ok = OK(self.uuid, self.recipient, self.sender, self.reply_port,
             self.version, self.seal)
     self.assertEqual(self.uuid, ok.uuid)
     self.assertEqual(self.recipient, ok.recipient)
     self.assertEqual(self.sender, ok.sender)
     self.assertEqual(self.reply_port, ok.reply_port)
     self.assertEqual(self.version, ok.version)
     self.assertEqual(self.seal, ok.seal)
示例#4
0
 def test_check_seal_bad_seal(self):
     """
     Ensure a message with a bad seal (i.e. malformed junk) fails the check.
     """
     ok_dict = {
         'uuid': str(uuid.uuid4()),
         'recipient': PUBLIC_KEY,
         'sender': BAD_PUBLIC_KEY,
         'reply_port': 1908,
         'version': get_version()
     }
     seal = 'not a seal'
     ok = OK(ok_dict['uuid'], ok_dict['recipient'], ok_dict['sender'],
             ok_dict['reply_port'], ok_dict['version'], seal)
     self.assertFalse(check_seal(ok))
示例#5
0
 def test_check_seal_invalid_seal(self):
     """
     Ensure a message with an invalid seal fails the check.
     """
     ok_dict = {
         'uuid': str(uuid.uuid4()),
         'recipient': PUBLIC_KEY,
         'sender': BAD_PUBLIC_KEY,
         'reply_port': 1908,
         'version': get_version()
     }
     seal = get_seal(ok_dict, PRIVATE_KEY)
     ok = OK(ok_dict['uuid'], ok_dict['recipient'], ok_dict['sender'],
             ok_dict['reply_port'], ok_dict['version'], seal)
     self.assertFalse(check_seal(ok))
示例#6
0
 def test_check_seal(self):
     """
     Make sure message objects that contain a valid seal are correctly
     checked.
     """
     ok_dict = {
         'uuid': str(uuid.uuid4()),
         'recipient': PUBLIC_KEY,
         'sender': PUBLIC_KEY,
         'reply_port': 1908,
         'version': get_version()
     }
     seal = get_seal(ok_dict, PRIVATE_KEY)
     ok = OK(ok_dict['uuid'], ok_dict['recipient'], ok_dict['sender'],
             ok_dict['reply_port'], ok_dict['version'], seal)
     self.assertTrue(check_seal(ok))
示例#7
0
 def test_send_with_cached_protocol(self):
     """
     Send the message to the referenced contact using a cached protocol
     object.
     """
     nc = NetstringConnector(self.event_loop)
     nc._send_message_with_protocol = mock.MagicMock()
     contact = PeerNode(PUBLIC_KEY, self.version,
                        'netstring://192.168.0.1:1908')
     msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
     protocol = mock.MagicMock()
     sender = Node(PUBLIC_KEY, PRIVATE_KEY, self.event_loop, nc, 1908)
     nc._connections[contact.network_id] = protocol
     result = nc.send(contact, msg, sender)
     self.assertIsInstance(result, asyncio.Future)
     self.assertTrue(result.done())
     self.assertEqual(result.result(), True)
     nc._send_message_with_protocol.assert_called_once_with(msg, protocol)
示例#8
0
 def test_send_message_with_protocol(self):
     """
     Ensures that the message is translated into a dictionary and passed
     into the protocol object in the expected way.
     """
     nc = NetstringConnector(self.event_loop)
     protocol = mock.MagicMock()
     protocol.send_string = mock.MagicMock()
     msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
     nc._send_message_with_protocol(msg, protocol)
     expected = {
         'message': 'ok',
         'uuid': 'uuid',
         'recipient': 'recipient',
         'sender': 'sender',
         'reply_port': 9999,
         'version': 'version',
         'seal': 'seal'
     }
     actual = json.loads(protocol.send_string.call_args[0][0])
     self.assertEqual(expected, actual)
示例#9
0
    def test_send(self):
        """
        Test the good case. We should end up with a task wrapping an
        appropriate call to aiohttp.request.
        """
        contact = PeerNode(PUBLIC_KEY, self.version, 'http://192.168.0.1:80')
        msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
        msg_json = json.dumps(to_dict(msg))
        headers = {'content-type': 'application/json'}
        connector = HttpConnector(self.event_loop)

        @asyncio.coroutine
        def faux_request(*args, **kwargs):
            return 'foo'

        with mock.patch.object(aiohttp, 'request',
                               return_value=faux_request()) as request:
            result = connector.send(contact, msg)
            self.assertIsInstance(result, asyncio.Task)
            request.assert_called_once_with('post', contact.uri, data=msg_json,
                                            headers=headers)
示例#10
0
    def test_send_with_failing_cached_protocol(self):
        """
        Attempting to send a message to the referenced contact using a
        cached protocol object that cannot send (e.g. perhaps the transport
        was dropped?) causes a retry as if the contact were new.
        """
        nc = NetstringConnector(self.event_loop)
        contact = PeerNode(PUBLIC_KEY, self.version,
                           'netstring://192.168.0.1:1908')
        msg = OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')
        protocol = mock.MagicMock()

        def side_effect(*args, **kwargs):
            raise ValueError()

        protocol.send_string = mock.MagicMock(side_effect=side_effect)
        nc._connections[contact.network_id] = protocol

        new_protocol = mock.MagicMock()
        new_protocol.send_string = mock.MagicMock()
        sender = Node(PUBLIC_KEY, PRIVATE_KEY, self.event_loop, nc, 1908)

        @asyncio.coroutine
        def faux_connect(protocol=new_protocol):
            return ('foo', protocol)

        with mock.patch.object(self.event_loop, 'create_connection',
                               return_value=faux_connect()):
            result = nc.send(contact, msg, sender)
            self.event_loop.run_until_complete(result)
            self.assertEqual(1, new_protocol.send_string.call_count)
            self.assertTrue(result.done())
            self.assertEqual(True, result.result())
            self.assertIn(contact.network_id, nc._connections)
            self.assertEqual(nc._connections[contact.network_id],
                             new_protocol)
            expected = to_dict(msg)
            actual = json.loads(protocol.send_string.call_args[0][0])
            self.assertEqual(expected, actual)
示例#11
0
 def test_handle_response_wrong_message_type(self):
     """
     Ensure that a response that isn't a Nodes or Value message results in
     the responding peer node being blacklisted and the error being
     correctly handled.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = OK(uuid, self.node.network_id, self.node.network_id,
              self.reply_port, self.version, self.seal)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], TypeError)
     self.assertEqual(args[2].args[0],
                      "Unexpected response type from {}".format(contact))
示例#12
0
 def faux_receive(*args, **kwargs):
     return OK('uuid', 'recipient', 'sender', 9999, 'version', 'seal')