blob: 768cd050c910a813b475d1d6d778d3e7cdfe32ff [file] [log] [blame]
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -04001# Copyright 2014 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Emilien Macchif61f1fc2016-03-15 21:40:10 -040016import socket
17
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040018import mock
Doug Hellmann583ce2c2015-03-11 14:55:46 +000019from oslotest import mockpatch
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040020import six
Matthew Treinish6421af82015-04-23 09:47:50 -040021from six.moves import http_client as httplib
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040022
23from tempest.common import glance_http
24from tempest import exceptions
Matthew Treinishffad78a2016-04-16 14:39:52 -040025from tempest.tests import base
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040026from tempest.tests import fake_auth_provider
Jordan Pittier00f25962016-03-18 17:10:07 +010027from tempest.tests.lib import fake_http
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040028
29
30class TestGlanceHTTPClient(base.TestCase):
31
32 def setUp(self):
33 super(TestGlanceHTTPClient, self).setUp()
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040034 self.endpoint = 'http://fake_url.com'
35 self.fake_auth = fake_auth_provider.FakeAuthProvider()
36
37 self.fake_auth.base_url = mock.MagicMock(return_value=self.endpoint)
38
Matthew Treinish1d14c542014-06-17 20:25:40 -040039 self.useFixture(mockpatch.PatchObject(
40 httplib.HTTPConnection,
41 'request',
Jordan Pittier00f25962016-03-18 17:10:07 +010042 side_effect=b'fake_body'))
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040043 self.client = glance_http.HTTPClient(self.fake_auth, {})
44
45 def _set_response_fixture(self, header, status, resp_body):
Jordan Pittier00f25962016-03-18 17:10:07 +010046 resp = fake_http.fake_http_response(header, status=status,
47 body=six.StringIO(resp_body))
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040048 self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
Matthew Treinish1d14c542014-06-17 20:25:40 -040049 'getresponse', return_value=resp))
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040050 return resp
51
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040052 def test_raw_request(self):
53 self._set_response_fixture({}, 200, 'fake_response_body')
54 resp, body = self.client.raw_request('GET', '/images')
55 self.assertEqual(200, resp.status)
56 self.assertEqual('fake_response_body', body.read())
57
58 def test_raw_request_with_response_chunked(self):
59 self._set_response_fixture({}, 200, 'fake_response_body')
60 self.useFixture(mockpatch.PatchObject(glance_http,
61 'CHUNKSIZE', 1))
62 resp, body = self.client.raw_request('GET', '/images')
63 self.assertEqual(200, resp.status)
64 self.assertEqual('fake_response_body', body.read())
65
66 def test_raw_request_chunked(self):
67 self.useFixture(mockpatch.PatchObject(glance_http,
68 'CHUNKSIZE', 1))
69 self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
70 'endheaders'))
71 self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
72 'send'))
73
74 self._set_response_fixture({}, 200, 'fake_response_body')
75 req_body = six.StringIO('fake_request_body')
76 resp, body = self.client.raw_request('PUT', '/images', body=req_body)
77 self.assertEqual(200, resp.status)
78 self.assertEqual('fake_response_body', body.read())
Shuquan Huangd9504152015-07-10 09:38:44 +000079 call_count = httplib.HTTPConnection.send.call_count
80 self.assertEqual(call_count - 1, req_body.tell())
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040081
82 def test_get_connection_class_for_https(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +000083 conn_class = self.client._get_connection_class('https')
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040084 self.assertEqual(glance_http.VerifiedHTTPSConnection, conn_class)
85
86 def test_get_connection_class_for_http(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +000087 conn_class = (self.client._get_connection_class('http'))
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040088 self.assertEqual(httplib.HTTPConnection, conn_class)
89
90 def test_get_connection_http(self):
Shuquan Huang29e9cab2015-12-30 22:43:49 +080091 self.assertIsInstance(self.client._get_connection(),
92 httplib.HTTPConnection)
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -040093
94 def test_get_connection_https(self):
95 endpoint = 'https://fake_url.com'
96 self.fake_auth.base_url = mock.MagicMock(return_value=endpoint)
97 self.client = glance_http.HTTPClient(self.fake_auth, {})
Shuquan Huang29e9cab2015-12-30 22:43:49 +080098 self.assertIsInstance(self.client._get_connection(),
99 glance_http.VerifiedHTTPSConnection)
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400100
Emilien Macchif61f1fc2016-03-15 21:40:10 -0400101 def test_get_connection_ipv4_https(self):
102 endpoint = 'https://127.0.0.1'
103 self.fake_auth.base_url = mock.MagicMock(return_value=endpoint)
104 self.client = glance_http.HTTPClient(self.fake_auth, {})
Shuquan Huang29e9cab2015-12-30 22:43:49 +0800105 self.assertIsInstance(self.client._get_connection(),
106 glance_http.VerifiedHTTPSConnection)
Emilien Macchif61f1fc2016-03-15 21:40:10 -0400107
108 def test_get_connection_ipv6_https(self):
109 endpoint = 'https://[::1]'
110 self.fake_auth.base_url = mock.MagicMock(return_value=endpoint)
111 self.client = glance_http.HTTPClient(self.fake_auth, {})
Shuquan Huang29e9cab2015-12-30 22:43:49 +0800112 self.assertIsInstance(self.client._get_connection(),
113 glance_http.VerifiedHTTPSConnection)
Emilien Macchif61f1fc2016-03-15 21:40:10 -0400114
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400115 def test_get_connection_url_not_fount(self):
116 self.useFixture(mockpatch.PatchObject(self.client, 'connection_class',
117 side_effect=httplib.InvalidURL()
118 ))
119 self.assertRaises(exceptions.EndpointNotFound,
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +0000120 self.client._get_connection)
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400121
122 def test_get_connection_kwargs_default_for_http(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +0000123 kwargs = self.client._get_connection_kwargs('http')
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400124 self.assertEqual(600, kwargs['timeout'])
125 self.assertEqual(1, len(kwargs.keys()))
126
127 def test_get_connection_kwargs_set_timeout_for_http(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +0000128 kwargs = self.client._get_connection_kwargs('http', timeout=10,
129 ca_certs='foo')
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400130 self.assertEqual(10, kwargs['timeout'])
131 # nothing more than timeout is evaluated for http connections
132 self.assertEqual(1, len(kwargs.keys()))
133
134 def test_get_connection_kwargs_default_for_https(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +0000135 kwargs = self.client._get_connection_kwargs('https')
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400136 self.assertEqual(600, kwargs['timeout'])
Shuquan Huanga77f7022015-12-14 17:26:38 +0800137 self.assertIsNone(kwargs['ca_certs'])
138 self.assertIsNone(kwargs['cert_file'])
139 self.assertIsNone(kwargs['key_file'])
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400140 self.assertEqual(False, kwargs['insecure'])
141 self.assertEqual(True, kwargs['ssl_compression'])
142 self.assertEqual(6, len(kwargs.keys()))
143
144 def test_get_connection_kwargs_set_params_for_https(self):
Ken'ichi Ohmichi8f6cf5e2015-11-30 12:24:31 +0000145 kwargs = self.client._get_connection_kwargs('https', timeout=10,
146 ca_certs='foo',
147 cert_file='/foo/bar.cert',
148 key_file='/foo/key.pem',
149 insecure=True,
150 ssl_compression=False)
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400151 self.assertEqual(10, kwargs['timeout'])
Joseph Lanouxc9c06be2015-01-21 09:03:30 +0000152 self.assertEqual('foo', kwargs['ca_certs'])
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400153 self.assertEqual('/foo/bar.cert', kwargs['cert_file'])
154 self.assertEqual('/foo/key.pem', kwargs['key_file'])
155 self.assertEqual(True, kwargs['insecure'])
156 self.assertEqual(False, kwargs['ssl_compression'])
157 self.assertEqual(6, len(kwargs.keys()))
158
159
Emilien Macchif61f1fc2016-03-15 21:40:10 -0400160class TestVerifiedHTTPSConnection(base.TestCase):
161
162 @mock.patch('socket.socket')
163 @mock.patch('tempest.common.glance_http.OpenSSLConnectionDelegator')
164 def test_connect_ipv4(self, mock_delegator, mock_socket):
165 connection = glance_http.VerifiedHTTPSConnection('127.0.0.1')
166 connection.connect()
167
168 mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
169 mock_delegator.assert_called_once_with(connection.context,
170 mock_socket.return_value)
171 mock_delegator.return_value.connect.assert_called_once_with(
172 (connection.host, 443))
173
174 @mock.patch('socket.socket')
175 @mock.patch('tempest.common.glance_http.OpenSSLConnectionDelegator')
176 def test_connect_ipv6(self, mock_delegator, mock_socket):
177 connection = glance_http.VerifiedHTTPSConnection('[::1]')
178 connection.connect()
179
180 mock_socket.assert_called_once_with(socket.AF_INET6,
181 socket.SOCK_STREAM)
182 mock_delegator.assert_called_once_with(connection.context,
183 mock_socket.return_value)
184 mock_delegator.return_value.connect.assert_called_once_with(
185 (connection.host, 443, 0, 0))
186
187 @mock.patch('tempest.common.glance_http.OpenSSLConnectionDelegator')
188 @mock.patch('socket.getaddrinfo',
189 side_effect=OSError('Gettaddrinfo failed'))
190 def test_connect_with_address_lookup_failure(self, mock_getaddrinfo,
191 mock_delegator):
192 connection = glance_http.VerifiedHTTPSConnection('127.0.0.1')
193 self.assertRaises(exceptions.RestClientException, connection.connect)
194
195 mock_getaddrinfo.assert_called_once_with(
196 connection.host, connection.port, 0, socket.SOCK_STREAM)
197
198 @mock.patch('socket.socket')
199 @mock.patch('socket.getaddrinfo',
200 return_value=[(2, 1, 6, '', ('127.0.0.1', 443))])
201 @mock.patch('tempest.common.glance_http.OpenSSLConnectionDelegator')
202 def test_connect_with_socket_failure(self, mock_delegator,
203 mock_getaddrinfo,
204 mock_socket):
205 mock_delegator.return_value.connect.side_effect = \
206 OSError('Connect failed')
207
208 connection = glance_http.VerifiedHTTPSConnection('127.0.0.1')
209 self.assertRaises(exceptions.RestClientException, connection.connect)
210
211 mock_getaddrinfo.assert_called_once_with(
212 connection.host, connection.port, 0, socket.SOCK_STREAM)
213 mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
214 mock_delegator.return_value.connect.\
215 assert_called_once_with((connection.host, 443))
216
217
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400218class TestResponseBodyIterator(base.TestCase):
219
220 def test_iter_default_chunk_size_64k(self):
Jordan Pittier00f25962016-03-18 17:10:07 +0100221 resp = fake_http.fake_http_response({}, six.StringIO(
Mauro S. M. Rodrigues790a96d2014-03-30 10:41:30 -0400222 'X' * (glance_http.CHUNKSIZE + 1)))
223 iterator = glance_http.ResponseBodyIterator(resp)
224 chunks = list(iterator)
225 self.assertEqual(chunks, ['X' * glance_http.CHUNKSIZE, 'X'])