예제 #1
0
    def test_url_defaults(self):
        """
        When the container client is configured with a host address and port,
        and some URL defaults are set, requests are made to that address and
        port with the expected URL.
        """
        client = ContainerHttpClient('127.0.0.1',
                                     '12345',
                                     url_defaults={
                                         'scheme': 'https',
                                         'fragment': 'test',
                                     })

        responses.add(responses.GET, 'https://127.0.0.1:12345/baz', status=200)
        response = client.request('GET',
                                  '/baz',
                                  url_kwargs={
                                      'query': (('foo', 'bar'), ),
                                  })

        self.assertEqual(response.status_code, 200)

        [call] = responses.calls
        self.assertEqual(call.request.url,
                         'https://127.0.0.1:12345/baz?foo=bar#test')
예제 #2
0
    def test_defaults(self):
        """
        When the container client is configured with a host address and port,
        requests are made to that address and port.
        """
        client = ContainerHttpClient('127.0.0.1', '12345')

        responses.add(responses.GET, 'http://127.0.0.1:12345/', status=200)
        response = client.request('GET')

        self.assertEqual(response.status_code, 200)

        [call] = responses.calls
        self.assertEqual(call.request.url, 'http://127.0.0.1:12345/')
예제 #3
0
    def test_for_container_specific_port(self):
        """
        The ``for_container()`` class method returns a container client that
        connects to the container port specified.
        """
        ch = self.make_helper()
        container = ContainerDefinition('first_port',
                                        IMG,
                                        create_kwargs={
                                            'ports': {
                                                '8080/tcp':
                                                ('127.0.0.1', None),
                                                '5353/udp':
                                                ('127.0.0.1', None),
                                            }
                                        },
                                        helper=ch)
        container.setup()
        self.addCleanup(container.teardown)

        client = ContainerHttpClient.for_container(container,
                                                   container_port='8080')
        self.addCleanup(client.close)

        response = client.request('GET', '/foo')

        self.assertEqual(response.status_code, 200)
        response_lines = response.text.splitlines()
        self.assertIn('HTTP/1.1 GET /foo', response_lines)

        addr, port = container.get_host_port('8080')
        self.assertIn('Host: {}:{}'.format(addr, port), response_lines)
예제 #4
0
    def test_session_context_manager(self):
        """
        When a custom session object is given, that object is used to make
        requests and is closed when the context is exited when the container
        client is used as a context manager.
        """
        session = DummySession()
        client = ContainerHttpClient('127.0.0.1', '12345', session=session)

        with client:
            client.request('GET', '/foo')
            self.assertEqual(session.requests, [
                (('GET', 'http://127.0.0.1:12345/foo'), {}),
            ])

        self.assertTrue(session.check_was_closed())
예제 #5
0
 def http_client(self, port=None):
     """
     Construct an HTTP client for this container.
     """
     # Local import to avoid potential circularity.
     from seaworthy.client import ContainerHttpClient
     client = ContainerHttpClient.for_container(self, container_port=port)
     self._http_clients.append(client)
     return client
예제 #6
0
 def test_success(self):
     """
     When a request succeeds before the timeout, all is happy.
     """
     client = ContainerHttpClient('127.0.0.1', '12345')
     responses.add(responses.GET, 'http://127.0.0.1:12345/', status=200)
     # A failure here will raise an exception.
     # 100ms is long enough for a first-time success.
     wait_for_response(client, 0.1)
예제 #7
0
 def test_unexpected_status_code_timeout(self):
     """
     When requests are received without the correct status code before the
     timeout, we time out.
     """
     client = ContainerHttpClient('127.0.0.1', '12345')
     responses.add(responses.GET, 'http://127.0.0.1:12345/', status=503)
     with self.assertRaises(TimeoutError) as cm:
         # 190ms is enough time to fail, wait 100ms, fail again, wait 100ms,
         # then time out.
         wait_for_response(client, 0.19, expected_status_code=200)
     self.assertEqual(str(cm.exception),
                      'Timeout waiting for HTTP response.')
예제 #8
0
 def test_error_then_success(self):
     """
     When an exception is raised before the timeout, we retry and are happy
     with any successful request before the timeout.
     """
     client = ContainerHttpClient('127.0.0.1', '12345')
     responses.add(responses.GET,
                   'http://127.0.0.1:12345/',
                   body=Exception('KABOOM'))
     responses.add(responses.GET, 'http://127.0.0.1:12345/', status=200)
     # A failure here will raise an exception.
     # Because responses is fast 110ms gives us time to fail, wait 100ms,
     # then succeed.
     wait_for_response(client, 0.11)
예제 #9
0
 def test_error_timeout(self):
     """
     When exceptions are raised without a successful request before the
     timeout, we time out.
     """
     client = ContainerHttpClient('127.0.0.1', '12345')
     responses.add(responses.GET,
                   'http://127.0.0.1:12345/',
                   body=Exception('KABOOM'))
     with self.assertRaises(TimeoutError) as cm:
         # 190ms is enough time to fail, wait 100ms, fail again, wait 100ms,
         # then time out.
         wait_for_response(client, 0.19)
     self.assertEqual(str(cm.exception),
                      'Timeout waiting for HTTP response.')
예제 #10
0
    def test_session(self):
        """
        When a custom session object is given, that object is used to make
        requests and is closed when ``close()`` is called.
        """
        session = DummySession()
        client = ContainerHttpClient('127.0.0.1', '12345', session=session)

        client.request('GET', '/foo')
        client.request('POST', '/bar')
        self.assertEqual(session.requests, [
            (('GET', 'http://127.0.0.1:12345/foo'), {}),
            (('POST', 'http://127.0.0.1:12345/bar'), {}),
        ])

        client.close()
        self.assertTrue(session.check_was_closed())
예제 #11
0
    def test_methods(self):
        """
        When the HTTP method-specific methods are called, the correct request
        method is used.
        """
        client = ContainerHttpClient('127.0.0.1', '45678')

        responses.add(responses.GET, 'http://127.0.0.1:45678/', status=200)
        responses.add(responses.OPTIONS,
                      'http://127.0.0.1:45678/foo',
                      status=201)
        responses.add(responses.HEAD, 'http://127.0.0.1:45678/bar', status=403)
        responses.add(responses.POST, 'http://127.0.0.1:45678/baz', status=404)
        responses.add(responses.PUT, 'http://127.0.0.1:45678/test', status=418)
        responses.add(responses.PATCH,
                      'http://127.0.0.1:45678/a/b/c',
                      status=501)
        responses.add(responses.DELETE,
                      'http://127.0.0.1:45678/d/e/f',
                      status=503)

        get_response = client.get()
        options_response = client.options('/foo')
        head_response = client.head('/bar')
        post_response = client.post('/baz')
        put_response = client.put('/test')
        patch_response = client.patch('/a/b/c')
        delete_response = client.delete('/d/e/f')

        self.assertEqual(get_response.status_code, 200)
        self.assertEqual(options_response.status_code, 201)
        self.assertEqual(head_response.status_code, 403)
        self.assertEqual(post_response.status_code, 404)
        self.assertEqual(put_response.status_code, 418)
        self.assertEqual(patch_response.status_code, 501)
        self.assertEqual(delete_response.status_code, 503)

        self.assertEqual(len(responses.calls), 7)
예제 #12
0
    def test_timeout(self):
        """
        When we don't get a response before the timeout, we time out.

        FIXME: Because responses doesn't do timeouts, we fake it by manually
        raising the exception we expect. We really should use requests itself
        for this.
        """
        client = ContainerHttpClient('127.0.0.1', '12345')

        responses.add(responses.GET,
                      'http://127.0.0.1:12345/',
                      body=requests.exceptions.Timeout())
        with self.assertRaises(TimeoutError) as cm:
            # The timeout doesn't actually matter here because we raise the
            # exception ourselves.
            wait_for_response(client, 0.1)
        self.assertEqual(str(cm.exception),
                         'Timeout waiting for HTTP response.')
예제 #13
0
    def test_relative_paths(self):
        """
        The path can be specified as a relative or absolute path.
        """
        client = ContainerHttpClient('127.0.0.1',
                                     '12345',
                                     url_defaults={'path': ['foo']})

        responses.add(responses.GET,
                      'http://127.0.0.1:12345/foo/bar/baz',
                      status=200)
        client.request('GET', 'bar/baz')

        self.assertEqual(responses.calls[0].request.url,
                         'http://127.0.0.1:12345/foo/bar/baz')

        responses.add(responses.GET,
                      'http://127.0.0.1:12345/foobar',
                      status=200)
        client.request('GET', '/foobar')

        self.assertEqual(responses.calls[1].request.url,
                         'http://127.0.0.1:12345/foobar')
예제 #14
0
    def test_paths(self):
        """
        The path is appended to the URL correctly with various leading or
        trailing ``/`` characters.
        """
        client = ContainerHttpClient('127.0.0.1', '12345')

        # Root path
        responses.add(responses.GET, 'http://127.0.0.1:12345/', status=200)
        client.request('GET', '')  # Requests adds a trailing /
        client.request('GET', '/')

        self.assertEqual(responses.calls[0].request.url,
                         'http://127.0.0.1:12345/')
        self.assertEqual(responses.calls[1].request.url,
                         'http://127.0.0.1:12345/')

        # Leading slashes are ignored
        responses.add(responses.GET,
                      'http://127.0.0.1:12345/a/b/c',
                      status=200)
        client.request('GET', '/a/b/c')
        client.request('GET', 'a/b/c')

        self.assertEqual(responses.calls[2].request.url,
                         'http://127.0.0.1:12345/a/b/c')
        self.assertEqual(responses.calls[3].request.url,
                         'http://127.0.0.1:12345/a/b/c')

        # Trailing slashes are respected
        responses.add(responses.GET,
                      'http://127.0.0.1:12345/a/b/c/',
                      status=200)
        client.request('GET', '/a/b/c/')

        self.assertEqual(responses.calls[4].request.url,
                         'http://127.0.0.1:12345/a/b/c/')

        # Double slashes are not ignored
        responses.add(responses.GET,
                      'http://127.0.0.1:12345//a//b',
                      status=200)
        client.request('GET', '//a//b')

        self.assertEqual(responses.calls[5].request.url,
                         'http://127.0.0.1:12345//a//b')