blob: da9ab720fd458e9993176cf170253d7f58a5aa1d [file] [log] [blame]
Matthew Treinisha33037e2013-12-05 23:16:39 +00001# Copyright 2013 IBM Corp.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import httplib2
vponomaryov67b58fe2014-02-06 19:05:41 +020016import json
Matthew Treinisha33037e2013-12-05 23:16:39 +000017
18from tempest.common import rest_client
Matthew Treinish684d8992014-01-30 16:27:40 +000019from tempest import config
Matthew Treinisha33037e2013-12-05 23:16:39 +000020from tempest import exceptions
21from tempest.openstack.common.fixture import mockpatch
vponomaryov67b58fe2014-02-06 19:05:41 +020022from tempest.services.compute.xml import common as xml
Matthew Treinisha33037e2013-12-05 23:16:39 +000023from tempest.tests import base
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000024from tempest.tests import fake_auth_provider
Matthew Treinisha33037e2013-12-05 23:16:39 +000025from tempest.tests import fake_config
26from tempest.tests import fake_http
27
28
29class BaseRestClientTestClass(base.TestCase):
30
vponomaryov67b58fe2014-02-06 19:05:41 +020031 url = 'fake_endpoint'
32
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000033 def _get_region(self):
34 return 'fake region'
Matthew Treinisha33037e2013-12-05 23:16:39 +000035
36 def setUp(self):
37 super(BaseRestClientTestClass, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -050038 self.useFixture(fake_config.ConfigFixture())
39 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000040 self.rest_client = rest_client.RestClient(
41 fake_auth_provider.FakeAuthProvider())
Matthew Treinisha33037e2013-12-05 23:16:39 +000042 self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000043 self.useFixture(mockpatch.PatchObject(self.rest_client, '_get_region',
44 side_effect=self._get_region()))
Matthew Treinisha33037e2013-12-05 23:16:39 +000045 self.useFixture(mockpatch.PatchObject(self.rest_client,
46 '_log_response'))
47
48
49class TestRestClientHTTPMethods(BaseRestClientTestClass):
50 def setUp(self):
51 self.fake_http = fake_http.fake_httplib2()
52 super(TestRestClientHTTPMethods, self).setUp()
53 self.useFixture(mockpatch.PatchObject(self.rest_client,
54 '_error_checker'))
55
56 def test_post(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020057 __, return_dict = self.rest_client.post(self.url, {}, {})
Matthew Treinisha33037e2013-12-05 23:16:39 +000058 self.assertEqual('POST', return_dict['method'])
59
60 def test_get(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020061 __, return_dict = self.rest_client.get(self.url)
Matthew Treinisha33037e2013-12-05 23:16:39 +000062 self.assertEqual('GET', return_dict['method'])
63
64 def test_delete(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020065 __, return_dict = self.rest_client.delete(self.url)
Matthew Treinisha33037e2013-12-05 23:16:39 +000066 self.assertEqual('DELETE', return_dict['method'])
67
68 def test_patch(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020069 __, return_dict = self.rest_client.patch(self.url, {}, {})
Matthew Treinisha33037e2013-12-05 23:16:39 +000070 self.assertEqual('PATCH', return_dict['method'])
71
72 def test_put(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020073 __, return_dict = self.rest_client.put(self.url, {}, {})
Matthew Treinisha33037e2013-12-05 23:16:39 +000074 self.assertEqual('PUT', return_dict['method'])
75
76 def test_head(self):
77 self.useFixture(mockpatch.PatchObject(self.rest_client,
78 'response_checker'))
vponomaryov67b58fe2014-02-06 19:05:41 +020079 __, return_dict = self.rest_client.head(self.url)
Matthew Treinisha33037e2013-12-05 23:16:39 +000080 self.assertEqual('HEAD', return_dict['method'])
81
82 def test_copy(self):
vponomaryov67b58fe2014-02-06 19:05:41 +020083 __, return_dict = self.rest_client.copy(self.url)
Matthew Treinisha33037e2013-12-05 23:16:39 +000084 self.assertEqual('COPY', return_dict['method'])
85
86
87class TestRestClientNotFoundHandling(BaseRestClientTestClass):
88 def setUp(self):
89 self.fake_http = fake_http.fake_httplib2(404)
90 super(TestRestClientNotFoundHandling, self).setUp()
91
92 def test_post(self):
93 self.assertRaises(exceptions.NotFound, self.rest_client.post,
vponomaryov67b58fe2014-02-06 19:05:41 +020094 self.url, {}, {})
95
96
97class TestRestClientHeadersJSON(TestRestClientHTTPMethods):
98 TYPE = "json"
99
100 def _verify_headers(self, resp):
101 self.assertEqual(self.rest_client._get_type(), self.TYPE)
102 resp = dict((k.lower(), v) for k, v in resp.iteritems())
103 self.assertEqual(self.header_value, resp['accept'])
104 self.assertEqual(self.header_value, resp['content-type'])
105
106 def setUp(self):
107 super(TestRestClientHeadersJSON, self).setUp()
108 self.rest_client.TYPE = self.TYPE
109 self.header_value = 'application/%s' % self.rest_client._get_type()
110
111 def test_post(self):
112 resp, __ = self.rest_client.post(self.url, {})
113 self._verify_headers(resp)
114
115 def test_get(self):
116 resp, __ = self.rest_client.get(self.url)
117 self._verify_headers(resp)
118
119 def test_delete(self):
120 resp, __ = self.rest_client.delete(self.url)
121 self._verify_headers(resp)
122
123 def test_patch(self):
124 resp, __ = self.rest_client.patch(self.url, {})
125 self._verify_headers(resp)
126
127 def test_put(self):
128 resp, __ = self.rest_client.put(self.url, {})
129 self._verify_headers(resp)
130
131 def test_head(self):
132 self.useFixture(mockpatch.PatchObject(self.rest_client,
133 'response_checker'))
134 resp, __ = self.rest_client.head(self.url)
135 self._verify_headers(resp)
136
137 def test_copy(self):
138 resp, __ = self.rest_client.copy(self.url)
139 self._verify_headers(resp)
140
141
142class TestRestClientHeadersXML(TestRestClientHeadersJSON):
143 TYPE = "xml"
144
145 # These two tests are needed in one exemplar
146 def test_send_json_accept_xml(self):
147 resp, __ = self.rest_client.get(self.url,
148 self.rest_client.get_headers("xml",
149 "json"))
150 resp = dict((k.lower(), v) for k, v in resp.iteritems())
151 self.assertEqual("application/json", resp["content-type"])
152 self.assertEqual("application/xml", resp["accept"])
153
154 def test_send_xml_accept_json(self):
155 resp, __ = self.rest_client.get(self.url,
156 self.rest_client.get_headers("json",
157 "xml"))
158 resp = dict((k.lower(), v) for k, v in resp.iteritems())
159 self.assertEqual("application/json", resp["accept"])
160 self.assertEqual("application/xml", resp["content-type"])
161
162
163class TestRestClientParseRespXML(BaseRestClientTestClass):
164 TYPE = "xml"
165
166 keys = ["fake_key1", "fake_key2"]
167 values = ["fake_value1", "fake_value2"]
Dirk Muellerb9a57152014-02-21 15:48:32 +0100168 item_expected = dict((key, value) for (key, value) in zip(keys, values))
vponomaryov67b58fe2014-02-06 19:05:41 +0200169 list_expected = {"body_list": [
170 {keys[0]: values[0]},
171 {keys[1]: values[1]},
172 ]}
173 dict_expected = {"body_dict": {
174 keys[0]: values[0],
175 keys[1]: values[1],
176 }}
177
178 def setUp(self):
179 self.fake_http = fake_http.fake_httplib2()
180 super(TestRestClientParseRespXML, self).setUp()
181 self.rest_client.TYPE = self.TYPE
182
183 def test_parse_resp_body_item(self):
184 body_item = xml.Element("item", **self.item_expected)
185 body = self.rest_client._parse_resp(str(xml.Document(body_item)))
186 self.assertEqual(self.item_expected, body)
187
188 def test_parse_resp_body_list(self):
189 self.rest_client.list_tags = ["fake_list", ]
190 body_list = xml.Element(self.rest_client.list_tags[0])
191 for i in range(2):
192 body_list.append(xml.Element("fake_item",
193 **self.list_expected["body_list"][i]))
194 body = self.rest_client._parse_resp(str(xml.Document(body_list)))
195 self.assertEqual(self.list_expected["body_list"], body)
196
197 def test_parse_resp_body_dict(self):
198 self.rest_client.dict_tags = ["fake_dict", ]
199 body_dict = xml.Element(self.rest_client.dict_tags[0])
200
201 for i in range(2):
202 body_dict.append(xml.Element("fake_item", xml.Text(self.values[i]),
203 key=self.keys[i]))
204
205 body = self.rest_client._parse_resp(str(xml.Document(body_dict)))
206 self.assertEqual(self.dict_expected["body_dict"], body)
207
208
209class TestRestClientParseRespJSON(TestRestClientParseRespXML):
210 TYPE = "json"
211
212 def test_parse_resp_body_item(self):
213 body = self.rest_client._parse_resp(json.dumps(self.item_expected))
214 self.assertEqual(self.item_expected, body)
215
216 def test_parse_resp_body_list(self):
217 body = self.rest_client._parse_resp(json.dumps(self.list_expected))
218 self.assertEqual(self.list_expected["body_list"], body)
219
220 def test_parse_resp_body_dict(self):
221 body = self.rest_client._parse_resp(json.dumps(self.dict_expected))
222 self.assertEqual(self.dict_expected["body_dict"], body)
223
224 def test_parse_resp_two_top_keys(self):
225 dict_two_keys = self.dict_expected.copy()
226 dict_two_keys.update({"second_key": ""})
227 body = self.rest_client._parse_resp(json.dumps(dict_two_keys))
228 self.assertEqual(dict_two_keys, body)
229
230 def test_parse_resp_one_top_key_without_list_or_dict(self):
231 data = {"one_top_key": "not_list_or_dict_value"}
232 body = self.rest_client._parse_resp(json.dumps(data))
233 self.assertEqual(data, body)
vponomaryov6cb6d192014-03-07 09:39:05 +0200234
235
236class TestRestClientErrorCheckerJSON(base.TestCase):
237 c_type = "application/json"
238
239 def set_data(self, r_code, enc=None, r_body=None):
240 if enc is None:
241 enc = self.c_type
242 resp_dict = {'status': r_code, 'content-type': enc}
243 resp = httplib2.Response(resp_dict)
244 data = {
245 "method": "fake_method",
246 "url": "fake_url",
247 "headers": "fake_headers",
248 "body": "fake_body",
249 "resp": resp,
250 "resp_body": '{"resp_body": "fake_resp_body"}',
251 }
252 if r_body is not None:
253 data.update({"resp_body": r_body})
254 return data
255
256 def setUp(self):
257 super(TestRestClientErrorCheckerJSON, self).setUp()
Matthew Treinishff598482014-02-28 16:13:58 -0500258 self.useFixture(fake_config.ConfigFixture())
259 self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
vponomaryov6cb6d192014-03-07 09:39:05 +0200260 self.rest_client = rest_client.RestClient(
261 fake_auth_provider.FakeAuthProvider())
262
263 def test_response_less_than_400(self):
264 self.rest_client._error_checker(**self.set_data("399"))
265
266 def test_response_400(self):
267 self.assertRaises(exceptions.BadRequest,
268 self.rest_client._error_checker,
269 **self.set_data("400"))
270
271 def test_response_401(self):
272 self.assertRaises(exceptions.Unauthorized,
273 self.rest_client._error_checker,
274 **self.set_data("401"))
275
276 def test_response_403(self):
277 self.assertRaises(exceptions.Unauthorized,
278 self.rest_client._error_checker,
279 **self.set_data("403"))
280
281 def test_response_404(self):
282 self.assertRaises(exceptions.NotFound,
283 self.rest_client._error_checker,
284 **self.set_data("404"))
285
286 def test_response_409(self):
287 self.assertRaises(exceptions.Conflict,
288 self.rest_client._error_checker,
289 **self.set_data("409"))
290
291 def test_response_413(self):
292 self.assertRaises(exceptions.OverLimit,
293 self.rest_client._error_checker,
294 **self.set_data("413"))
295
296 def test_response_422(self):
297 self.assertRaises(exceptions.UnprocessableEntity,
298 self.rest_client._error_checker,
299 **self.set_data("422"))
300
301 def test_response_500_with_text(self):
302 # _parse_resp is expected to return 'str'
303 self.assertRaises(exceptions.ServerFault,
304 self.rest_client._error_checker,
305 **self.set_data("500"))
306
307 def test_response_501_with_text(self):
308 self.assertRaises(exceptions.ServerFault,
309 self.rest_client._error_checker,
310 **self.set_data("501"))
311
312 def test_response_500_with_dict(self):
313 r_body = '{"resp_body": {"err": "fake_resp_body"}}'
314 self.assertRaises(exceptions.ServerFault,
315 self.rest_client._error_checker,
316 **self.set_data("500", r_body=r_body))
317
318 def test_response_501_with_dict(self):
319 r_body = '{"resp_body": {"err": "fake_resp_body"}}'
320 self.assertRaises(exceptions.ServerFault,
321 self.rest_client._error_checker,
322 **self.set_data("501", r_body=r_body))
323
324 def test_response_bigger_than_400(self):
325 # Any response code, that bigger than 400, and not in
326 # (401, 403, 404, 409, 413, 422, 500, 501)
327 self.assertRaises(exceptions.UnexpectedResponseCode,
328 self.rest_client._error_checker,
329 **self.set_data("402"))
330
331
332class TestRestClientErrorCheckerXML(TestRestClientErrorCheckerJSON):
333 c_type = "application/xml"
334
335
336class TestRestClientErrorCheckerTEXT(TestRestClientErrorCheckerJSON):
337 c_type = "text/plain"
338
339 def test_fake_content_type(self):
340 # This test is required only in one exemplar
341 # Any response code, that bigger than 400, and not in
342 # (401, 403, 404, 409, 413, 422, 500, 501)
343 self.assertRaises(exceptions.InvalidContentType,
344 self.rest_client._error_checker,
345 **self.set_data("405", enc="fake_enc"))
Matthew Treinishead51df2014-03-15 18:56:43 +0000346
347
348class TestRestClientUtils(BaseRestClientTestClass):
349
350 def _is_resource_deleted(self, resource_id):
351 if not isinstance(self.retry_pass, int):
352 return False
353 if self.retry_count >= self.retry_pass:
354 return True
355 self.retry_count = self.retry_count + 1
356 return False
357
358 def setUp(self):
359 self.fake_http = fake_http.fake_httplib2()
360 super(TestRestClientUtils, self).setUp()
361 self.retry_count = 0
362 self.retry_pass = None
363 self.original_deleted_method = self.rest_client.is_resource_deleted
364 self.rest_client.is_resource_deleted = self._is_resource_deleted
365
366 def test_wait_for_resource_deletion(self):
367 self.retry_pass = 2
368 # Ensure timeout long enough for loop execution to hit retry count
369 self.rest_client.build_timeout = 500
370 sleep_mock = self.patch('time.sleep')
371 self.rest_client.wait_for_resource_deletion('1234')
372 self.assertEqual(len(sleep_mock.mock_calls), 2)
373
374 def test_wait_for_resource_deletion_not_deleted(self):
375 self.patch('time.sleep')
376 # Set timeout to be very quick to force exception faster
377 self.rest_client.build_timeout = 1
378 self.assertRaises(exceptions.TimeoutException,
379 self.rest_client.wait_for_resource_deletion,
380 '1234')
381
382 def test_wait_for_deletion_with_unimplemented_deleted_method(self):
383 self.rest_client.is_resource_deleted = self.original_deleted_method
384 self.assertRaises(NotImplementedError,
385 self.rest_client.wait_for_resource_deletion,
386 '1234')