Merge lp:~eday/burrow/backend-unittests into lp:burrow

Proposed by Eric Day
Status: Merged
Approved by: Eric Day
Approved revision: 39
Merged at revision: 32
Proposed branch: lp:~eday/burrow/backend-unittests
Merge into: lp:burrow
Diff against target: 425 lines (+170/-63)
6 files modified
.bzrignore (+1/-1)
burrow/backend/__init__.py (+3/-3)
burrow/backend/http.py (+47/-19)
burrow/frontend/wsgi.py (+28/-26)
test/backend/test_http.py (+77/-0)
test/backend/test_memory.py (+14/-14)
To merge this branch: bzr merge lp:~eday/burrow/backend-unittests
Reviewer Review Type Date Requested Status
Burrow Core Team Pending
Review via email: mp+70990@code.launchpad.net

Description of the change

Added HTTP backend unit tests that work against a running server (auto started/killed with test).

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-04-20 18:21:51 +0000
3+++ .bzrignore 2011-08-10 05:42:35 +0000
4@@ -1,4 +1,4 @@
5-.coverage
6+.coverage*
7 burrow.egg-info
8 ChangeLog
9 coverage
10
11=== modified file 'burrow/backend/__init__.py'
12--- burrow/backend/__init__.py 2011-08-09 19:43:03 +0000
13+++ burrow/backend/__init__.py 2011-08-10 05:42:35 +0000
14@@ -112,7 +112,7 @@
15 if detail == 'none':
16 detail = None
17 elif detail is not None and detail not in ['id', 'all']:
18- raise burrow.backend.BadDetail(detail)
19+ raise burrow.backend.InvalidArguments(detail)
20 return detail
21
22 def _get_message_detail(self, filters, default=None):
23@@ -121,7 +121,7 @@
24 if detail == 'none':
25 detail = None
26 elif detail is not None and detail not in options:
27- raise burrow.backend.BadDetail(detail)
28+ raise burrow.backend.InvalidArguments(detail)
29 return detail
30
31
32@@ -129,5 +129,5 @@
33 pass
34
35
36-class BadDetail(Exception):
37+class InvalidArguments(Exception):
38 pass
39
40=== modified file 'burrow/backend/http.py'
41--- burrow/backend/http.py 2011-04-22 02:18:26 +0000
42+++ burrow/backend/http.py 2011-08-10 05:42:35 +0000
43@@ -67,7 +67,7 @@
44 url = self._add_parameters(url, filters=filters)
45 return self._request('GET', url)
46
47- def update_messages(self, account, queue, attributes={}, filters={}):
48+ def update_messages(self, account, queue, attributes, filters={}):
49 url = '/%s/%s' % (account, queue)
50 url = self._add_parameters(url, attributes, filters)
51 return self._request('POST', url)
52@@ -75,20 +75,34 @@
53 def create_message(self, account, queue, message, body, attributes={}):
54 url = '/%s/%s/%s' % (account, queue, message)
55 url = self._add_parameters(url, attributes)
56- return self._request('PUT', url, body=body)
57-
58- def delete_message(self, account, queue, message):
59- url = '/%s/%s/%s' % (account, queue, message)
60- return self._request('DELETE', url)
61-
62- def get_message(self, account, queue, message):
63- url = '/%s/%s/%s' % (account, queue, message)
64- return self._request('GET', url)
65-
66- def update_message(self, account, queue, message, attributes={}):
67- url = '/%s/%s/%s' % (account, queue, message)
68- url = self._add_parameters(url, attributes)
69- return self._request('POST', url)
70+ try:
71+ return self._request('PUT', url, body=body).next()
72+ except StopIteration:
73+ return False
74+
75+ def delete_message(self, account, queue, message, filters={}):
76+ url = '/%s/%s/%s' % (account, queue, message)
77+ url = self._add_parameters(url, filters=filters)
78+ try:
79+ return self._request('DELETE', url).next()
80+ except StopIteration:
81+ return None
82+
83+ def get_message(self, account, queue, message, filters={}):
84+ url = '/%s/%s/%s' % (account, queue, message)
85+ url = self._add_parameters(url, filters=filters)
86+ try:
87+ return self._request('GET', url).next()
88+ except StopIteration:
89+ return None
90+
91+ def update_message(self, account, queue, message, attributes, filters={}):
92+ url = '/%s/%s/%s' % (account, queue, message)
93+ url = self._add_parameters(url, attributes, filters)
94+ try:
95+ return self._request('POST', url).next()
96+ except StopIteration:
97+ return None
98
99 def clean(self):
100 pass
101@@ -111,7 +125,21 @@
102 connection = httplib.HTTPConnection(*self.server)
103 connection.request(method, '/v1.0' + url, *args, **kwargs)
104 response = connection.getresponse()
105- if response.status == 200:
106- return json.loads(response.read())
107- if response.status >= 400:
108- raise Exception(response.reason)
109+ if response.status >= 200 and response.status < 300:
110+ if int(response.getheader('content-length')) == 0:
111+ if response.status == 201:
112+ yield True
113+ return
114+ body = response.read()
115+ if response.getheader('content-type')[:16] == 'application/json':
116+ body = json.loads(body)
117+ if isinstance(body, list):
118+ for item in body:
119+ yield item
120+ return
121+ yield body
122+ if response.status == 400:
123+ raise burrow.backend.InvalidArguments()
124+ if response.status == 404:
125+ raise burrow.backend.NotFound()
126+ raise Exception(response.reason)
127
128=== modified file 'burrow/frontend/wsgi.py'
129--- burrow/frontend/wsgi.py 2011-08-09 17:22:31 +0000
130+++ burrow/frontend/wsgi.py 2011-08-10 05:42:35 +0000
131@@ -173,33 +173,24 @@
132 @webob.dec.wsgify
133 def _delete_message(self, req, account, queue, message):
134 filters = self._parse_filters(req)
135- try:
136- message = self.backend.delete_message(account, queue, message,
137- filters)
138- except burrow.backend.NotFound:
139- return self._response(status=404)
140- return self._response(body=message)
141+ body = lambda: self.backend.delete_message(account, queue, message,
142+ filters)
143+ return self._response(body=body)
144
145 @webob.dec.wsgify
146 def _get_message(self, req, account, queue, message):
147 filters = self._parse_filters(req)
148- try:
149- message = self.backend.get_message(account, queue, message,
150- filters)
151- except burrow.backend.NotFound:
152- return self._response(status=404)
153- return self._response(body=message)
154+ body = lambda: self.backend.get_message(account, queue, message,
155+ filters)
156+ return self._response(body=body)
157
158 @webob.dec.wsgify
159 def _post_message(self, req, account, queue, message):
160 attributes = self._parse_attributes(req)
161 filters = self._parse_filters(req)
162- try:
163- message = self.backend.update_message(account, queue, message,
164- attributes, filters)
165- except burrow.backend.NotFound:
166- return self._response(status=404)
167- return self._response(body=message)
168+ body = lambda: self.backend.update_message(account, queue, message,
169+ attributes, filters)
170+ return self._response(body=body)
171
172 @webob.dec.wsgify
173 def _put_message(self, req, account, queue, message):
174@@ -241,12 +232,17 @@
175 return attributes
176
177 def _response(self, status=200, body=None, content_type=None):
178- if isinstance(body, types.GeneratorType):
179- try:
180+ try:
181+ if isinstance(body, types.GeneratorType):
182 body = list(body)
183- except burrow.backend.NotFound:
184- body = None
185- status = 404
186+ if isinstance(body, types.FunctionType):
187+ body = body()
188+ except burrow.backend.InvalidArguments:
189+ status = 400
190+ body = None
191+ except burrow.backend.NotFound:
192+ status = 404
193+ body = None
194 if body == []:
195 body = None
196 if body is None:
197@@ -258,11 +254,17 @@
198 if isinstance(body, list) or isinstance(body, dict):
199 content_type = 'application/json'
200 else:
201- content_type = "application/octet-stream"
202+ content_type = 'application/octet-stream'
203 if content_type == 'application/json':
204 body = json.dumps(body, indent=2)
205- return webob.Response(status=status, body=body,
206- content_type=content_type)
207+ response = webob.Response(status=status)
208+ if body is not None:
209+ response.content_type = content_type
210+ if isinstance(body, unicode):
211+ response.unicode_body = body
212+ else:
213+ response.body = body
214+ return response
215
216
217 class WSGILog(object):
218
219=== added file 'test/backend/test_http.py'
220--- test/backend/test_http.py 1970-01-01 00:00:00 +0000
221+++ test/backend/test_http.py 2011-08-10 05:42:35 +0000
222@@ -0,0 +1,77 @@
223+# Copyright (C) 2011 OpenStack LLC.
224+#
225+# Licensed under the Apache License, Version 2.0 (the "License");
226+# you may not use this file except in compliance with the License.
227+# You may obtain a copy of the License at
228+#
229+# http://www.apache.org/licenses/LICENSE-2.0
230+#
231+# Unless required by applicable law or agreed to in writing, software
232+# distributed under the License is distributed on an "AS IS" BASIS,
233+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
234+# See the License for the specific language governing permissions and
235+# limitations under the License.
236+
237+import atexit
238+import ConfigParser
239+import os
240+import signal
241+import time
242+
243+import burrow.server
244+import burrow.backend.http
245+import test.backend.test_memory
246+
247+
248+class TestHTTP(test.backend.test_memory.TestMemory):
249+ '''Unittests for the HTTP backend.'''
250+
251+ def setUp(self):
252+ config = (ConfigParser.ConfigParser(), 'test')
253+ self.backend = burrow.backend.http.Backend(config)
254+ self.check_empty()
255+
256+
257+def kill_server():
258+ try:
259+ pid_file = open('server.pid', 'r')
260+ pid = pid_file.read()
261+ pid_file.close()
262+ try:
263+ os.kill(int(pid), signal.SIGUSR1)
264+ time.sleep(1)
265+ os.kill(int(pid), signal.SIGTERM)
266+ except OSError:
267+ pass
268+ os.unlink('server.pid')
269+ except IOError:
270+ pass
271+
272+
273+def start_server():
274+ pid = os.fork()
275+ if pid == 0:
276+ try:
277+ import coverage
278+ cov = coverage.coverage(data_suffix=True)
279+ cov.start()
280+
281+ def save_coverage(signum, frame):
282+ cov.save()
283+
284+ signal.signal(signal.SIGUSR1, save_coverage)
285+ except:
286+ pass
287+ server = burrow.server.Server(add_default_log_handler=False)
288+ server.frontends[0].default_ttl = 0
289+ server.run()
290+ os.exit(0)
291+ pid_file = open('server.pid', 'w')
292+ pid_file.write(str(pid))
293+ pid_file.close()
294+ time.sleep(1)
295+
296+
297+kill_server()
298+start_server()
299+atexit.register(kill_server)
300
301=== modified file 'test/backend/test_memory.py'
302--- test/backend/test_memory.py 2011-08-09 22:53:44 +0000
303+++ test/backend/test_memory.py 2011-08-10 05:42:35 +0000
304@@ -75,7 +75,7 @@
305 self.backend.create_message('a', 'q', 'm', 'test')
306 filters = dict(detail='bad')
307 accounts = self.backend.delete_accounts(filters)
308- self.assertRaises(burrow.backend.BadDetail, list, accounts)
309+ self.assertRaises(burrow.backend.InvalidArguments, list, accounts)
310 self.assertEquals([], list(self.backend.delete_accounts()))
311
312 def test_accounts_delete_marker(self):
313@@ -145,7 +145,7 @@
314 self.backend.create_message('a', 'q', 'm', 'test')
315 filters = dict(detail='bad')
316 accounts = self.backend.get_accounts(filters)
317- self.assertRaises(burrow.backend.BadDetail, list, accounts)
318+ self.assertRaises(burrow.backend.InvalidArguments, list, accounts)
319 self.assertEquals([], list(self.backend.delete_accounts()))
320
321 def test_accounts_get_marker(self):
322@@ -237,7 +237,7 @@
323 self.backend.create_message('a', 'q', 'm', 'test')
324 filters = dict(detail='bad')
325 queues = self.backend.delete_queues('a', filters)
326- self.assertRaises(burrow.backend.BadDetail, list, queues)
327+ self.assertRaises(burrow.backend.InvalidArguments, list, queues)
328 self.assertEquals([], list(self.backend.delete_queues('a')))
329
330 def test_queues_delete_marker(self):
331@@ -307,7 +307,7 @@
332 self.backend.create_message('a', 'q', 'm', 'test')
333 filters = dict(detail='bad')
334 queues = self.backend.get_queues('a', filters)
335- self.assertRaises(burrow.backend.BadDetail, list, queues)
336+ self.assertRaises(burrow.backend.InvalidArguments, list, queues)
337 self.assertEquals([], list(self.backend.delete_queues('a')))
338
339 def test_queues_get_marker(self):
340@@ -428,7 +428,7 @@
341 self.backend.create_message('a', 'q', 'm', 'test')
342 filters = dict(detail='bad')
343 messages = self.backend.delete_messages('a', 'q', filters)
344- self.assertRaises(burrow.backend.BadDetail, list, messages)
345+ self.assertRaises(burrow.backend.InvalidArguments, list, messages)
346 self.assertEquals([], list(self.backend.delete_messages('a', 'q')))
347
348 def test_messages_delete_marker(self):
349@@ -514,7 +514,7 @@
350 self.backend.create_message('a', 'q', 'm', 'test')
351 filters = dict(detail='bad')
352 messages = self.backend.get_messages('a', 'q', filters)
353- self.assertRaises(burrow.backend.BadDetail, list, messages)
354+ self.assertRaises(burrow.backend.InvalidArguments, list, messages)
355 self.delete_messages()
356
357 def test_messages_get_marker(self):
358@@ -618,7 +618,7 @@
359 attributes = dict(ttl=100, hide=200)
360 filters = dict(detail='bad')
361 messages = self.backend.update_messages('a', 'q', attributes, filters)
362- self.assertRaises(burrow.backend.BadDetail, list, messages)
363+ self.assertRaises(burrow.backend.InvalidArguments, list, messages)
364 self.delete_messages()
365
366 def test_messages_update_marker(self):
367@@ -752,7 +752,7 @@
368 def test_message_delete_detail_bad(self):
369 self.backend.create_message('a', 'q', 'm', 'test')
370 filters = dict(detail='bad')
371- self.assertRaises(burrow.backend.BadDetail,
372+ self.assertRaises(burrow.backend.InvalidArguments,
373 self.backend.delete_message, 'a', 'q', 'm', filters)
374 self.delete_messages()
375
376@@ -794,7 +794,7 @@
377 def test_message_get_detail_bad(self):
378 self.backend.create_message('a', 'q', 'm', 'test')
379 filters = dict(detail='bad')
380- self.assertRaises(burrow.backend.BadDetail,
381+ self.assertRaises(burrow.backend.InvalidArguments,
382 self.backend.get_message, 'a', 'q', 'm', filters)
383 self.delete_messages()
384
385@@ -848,27 +848,27 @@
386 self.backend.create_message('a', 'q', 'm', 'test')
387 attributes = dict(ttl=100, hide=200)
388 filters = dict(detail='bad')
389- self.assertRaises(burrow.backend.BadDetail,
390+ self.assertRaises(burrow.backend.InvalidArguments,
391 self.backend.update_message, 'a', 'q', 'm', attributes, filters)
392 self.delete_messages()
393
394 def test_message_ttl(self):
395 attributes = dict(ttl=1)
396 self.backend.create_message('a', 'q', 'm', 'test', attributes)
397- time.sleep(1)
398+ time.sleep(2)
399 self.backend.clean()
400
401 def test_message_ttl_large(self):
402 attributes = dict(ttl=1)
403 for x in xrange(0, 1000):
404 self.backend.create_message('a', 'q', str(x), str(x), attributes)
405- time.sleep(1)
406+ time.sleep(2)
407 self.backend.clean()
408
409 def test_message_hide(self):
410 attributes = dict(hide=1)
411 self.backend.create_message('a', 'q', 'm', 'test', attributes)
412- time.sleep(1)
413+ time.sleep(2)
414 self.backend.clean()
415 message = self.backend.get_message('a', 'q', 'm')
416 self.assertEquals(dict(id='m', ttl=0, hide=0, body='test'), message)
417@@ -878,7 +878,7 @@
418 attributes = dict(hide=1)
419 for x in xrange(0, 1000):
420 self.backend.create_message('a', 'q', str(x), str(x), attributes)
421- time.sleep(1)
422+ time.sleep(2)
423 self.backend.clean()
424 message = self.backend.get_message('a', 'q', '0')
425 self.assertEquals(dict(id='0', ttl=0, hide=0, body='0'), message)

Subscribers

People subscribed via source and target branches