def test_non_200_status(self):
        """
    The node sends back a non-200 response that we don't know how to
    handle.
    """
        adapter = HttpAdapter('http://localhost')

        decoded_response = {'message': 'Request limit exceeded.'}

        mocked_response = create_http_response(
            status=429,
            content=json.dumps(decoded_response),
        )

        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            with self.assertRaises(BadApiResponse) as context:
                adapter.send_request({'command': 'helloWorld'})

        self.assertEqual(
            text_type(context.exception),
            '429 response from node: {decoded}'.format(
                decoded=decoded_response),
        )
    def test_exception_response(self):
        """
    Simulates sending a command to the node and getting an exception
    response.
    """
        adapter = HttpAdapter('http://localhost:14265')

        error_message = 'java.lang.ArrayIndexOutOfBoundsException: 4'

        mocked_response = create_http_response(
            status=500,
            content=json.dumps({
                'exception': error_message,
                'duration': 16,
            }),
        )

        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            with self.assertRaises(BadApiResponse) as context:
                adapter.send_request({'command': 'helloWorld'})

        self.assertEqual(
            text_type(context.exception),
            '500 response from node: {error}'.format(error=error_message),
        )
    def test_default_timeout(self, request_mock):
        # create dummy response
        request_mock.return_value = mock.Mock(text='{ "dummy": "payload"}',
                                              status_code=200)

        # create adapter
        mock_payload = {'dummy': 'payload'}
        adapter = HttpAdapter('http://localhost:14265')

        # test with default timeout
        adapter.send_request(payload=mock_payload)
        _, kwargs = request_mock.call_args
        self.assertEqual(kwargs['timeout'], socket.getdefaulttimeout())
    def test_argument_overriding_init_timeout(self, request_mock):
        # create dummy response
        request_mock.return_value = mock.Mock(text='{ "dummy": "payload"}',
                                              status_code=200)

        # create adapter
        mock_payload = {'dummy': 'payload'}
        adapter = HttpAdapter('http://localhost:14265')

        # test with timeout at adapter creation
        adapter = HttpAdapter('http://localhost:14265', timeout=99)
        adapter.send_request(payload=mock_payload)
        _, kwargs = request_mock.call_args
        self.assertEqual(kwargs['timeout'], 99)
    def test_instance_attribute_timeout(self, request_mock):
        # create dummy response
        request_mock.return_value = mock.Mock(text='{ "dummy": "payload"}',
                                              status_code=200)

        # create adapter
        mock_payload = {'dummy': 'payload'}
        adapter = HttpAdapter('http://localhost:14265')

        # test with explicit attribute
        adapter.timeout = 77
        adapter.send_request(payload=mock_payload)
        _, kwargs = request_mock.call_args
        self.assertEqual(kwargs['timeout'], 77)
    def test_success_response(self):
        """
    Simulates sending a command to the node and getting a success
    response.
    """
        adapter = HttpAdapter('http://localhost:14265')

        payload = {'command': 'helloWorld'}
        expected_result = {'message': 'Hello, IOTA!'}

        mocked_response = create_http_response(json.dumps(expected_result))
        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            result = adapter.send_request(payload)

        self.assertEqual(result, expected_result)

        # https://github.com/iotaledger/iota.lib.py/issues/84
        mocked_sender.assert_called_once_with(
            headers={
                'Content-type': 'application/json',
                'X-IOTA-API-Version': API_VERSION,
            },
            payload=json.dumps(payload),
            url=adapter.node_url,
        )
    def test_empty_response(self):
        """
    The response is empty.
    """
        adapter = HttpAdapter('http://localhost:14265')

        mocked_response = create_http_response('')

        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            with self.assertRaises(BadApiResponse) as context:
                adapter.send_request({'command': 'helloWorld'})

        self.assertEqual(
            text_type(context.exception),
            'Empty 200 response from node.',
        )
    def test_non_json_response(self):
        """
    The response is not JSON.
    """
        adapter = HttpAdapter('http://localhost:14265')

        invalid_response = 'EHLO iotatoken.com'  # Erm...
        mocked_response = create_http_response(invalid_response)

        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            with self.assertRaises(BadApiResponse) as context:
                adapter.send_request({'command': 'helloWorld'})

        self.assertEqual(
            text_type(context.exception),
            'Non-JSON 200 response from node: ' + invalid_response,
        )
    def test_non_object_response(self):
        """
    The response is valid JSON, but it's not an object.
    """
        adapter = HttpAdapter('http://localhost:14265')

        invalid_response = ['message', 'Hello, IOTA!']
        mocked_response = create_http_response(json.dumps(invalid_response))

        mocked_sender = mock.Mock(return_value=mocked_response)

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            with self.assertRaises(BadApiResponse) as context:
                adapter.send_request({'command': 'helloWorld'})

        self.assertEqual(
            text_type(context.exception),
            'Malformed 200 response from node: {response!r}'.format(
                response=invalid_response, ),
        )
    def test_trytes_in_request():
        """
    Sending a request that includes trytes.
    """
        adapter = HttpAdapter('http://localhost:14265')

        # Response is not important for this test; we just need to make
        # sure that the request is converted correctly.
        mocked_sender = mock.Mock(return_value=create_http_response('{}'))

        # noinspection PyUnresolvedReferences
        with mock.patch.object(adapter, '_send_http_request', mocked_sender):
            adapter.send_request({
                'command':
                'helloWorld',
                'trytes': [
                    TryteString(b'RBTC9D9DCDQAEASBYBCCKBFA'),
                    TryteString(
                        b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA',
                    ),
                ],
            })

        mocked_sender.assert_called_once_with(
            url=adapter.node_url,
            payload=json.dumps({
                'command':
                'helloWorld',

                # Tryte sequences are converted to strings for transport.
                'trytes': [
                    'RBTC9D9DCDQAEASBYBCCKBFA',
                    'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA',
                ],
            }),
            headers={
                'Content-type': 'application/json',
                'X-IOTA-API-Version': API_VERSION,
            },
        )