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
=== modified file '.bzrignore'
--- .bzrignore 2011-04-20 18:21:51 +0000
+++ .bzrignore 2011-08-10 05:42:35 +0000
@@ -1,4 +1,4 @@
1.coverage1.coverage*
2burrow.egg-info2burrow.egg-info
3ChangeLog3ChangeLog
4coverage4coverage
55
=== modified file 'burrow/backend/__init__.py'
--- burrow/backend/__init__.py 2011-08-09 19:43:03 +0000
+++ burrow/backend/__init__.py 2011-08-10 05:42:35 +0000
@@ -112,7 +112,7 @@
112 if detail == 'none':112 if detail == 'none':
113 detail = None113 detail = None
114 elif detail is not None and detail not in ['id', 'all']:114 elif detail is not None and detail not in ['id', 'all']:
115 raise burrow.backend.BadDetail(detail)115 raise burrow.backend.InvalidArguments(detail)
116 return detail116 return detail
117117
118 def _get_message_detail(self, filters, default=None):118 def _get_message_detail(self, filters, default=None):
@@ -121,7 +121,7 @@
121 if detail == 'none':121 if detail == 'none':
122 detail = None122 detail = None
123 elif detail is not None and detail not in options:123 elif detail is not None and detail not in options:
124 raise burrow.backend.BadDetail(detail)124 raise burrow.backend.InvalidArguments(detail)
125 return detail125 return detail
126126
127127
@@ -129,5 +129,5 @@
129 pass129 pass
130130
131131
132class BadDetail(Exception):132class InvalidArguments(Exception):
133 pass133 pass
134134
=== modified file 'burrow/backend/http.py'
--- burrow/backend/http.py 2011-04-22 02:18:26 +0000
+++ burrow/backend/http.py 2011-08-10 05:42:35 +0000
@@ -67,7 +67,7 @@
67 url = self._add_parameters(url, filters=filters)67 url = self._add_parameters(url, filters=filters)
68 return self._request('GET', url)68 return self._request('GET', url)
6969
70 def update_messages(self, account, queue, attributes={}, filters={}):70 def update_messages(self, account, queue, attributes, filters={}):
71 url = '/%s/%s' % (account, queue)71 url = '/%s/%s' % (account, queue)
72 url = self._add_parameters(url, attributes, filters)72 url = self._add_parameters(url, attributes, filters)
73 return self._request('POST', url)73 return self._request('POST', url)
@@ -75,20 +75,34 @@
75 def create_message(self, account, queue, message, body, attributes={}):75 def create_message(self, account, queue, message, body, attributes={}):
76 url = '/%s/%s/%s' % (account, queue, message)76 url = '/%s/%s/%s' % (account, queue, message)
77 url = self._add_parameters(url, attributes)77 url = self._add_parameters(url, attributes)
78 return self._request('PUT', url, body=body)78 try:
7979 return self._request('PUT', url, body=body).next()
80 def delete_message(self, account, queue, message):80 except StopIteration:
81 url = '/%s/%s/%s' % (account, queue, message)81 return False
82 return self._request('DELETE', url)82
8383 def delete_message(self, account, queue, message, filters={}):
84 def get_message(self, account, queue, message):84 url = '/%s/%s/%s' % (account, queue, message)
85 url = '/%s/%s/%s' % (account, queue, message)85 url = self._add_parameters(url, filters=filters)
86 return self._request('GET', url)86 try:
8787 return self._request('DELETE', url).next()
88 def update_message(self, account, queue, message, attributes={}):88 except StopIteration:
89 url = '/%s/%s/%s' % (account, queue, message)89 return None
90 url = self._add_parameters(url, attributes)90
91 return self._request('POST', url)91 def get_message(self, account, queue, message, filters={}):
92 url = '/%s/%s/%s' % (account, queue, message)
93 url = self._add_parameters(url, filters=filters)
94 try:
95 return self._request('GET', url).next()
96 except StopIteration:
97 return None
98
99 def update_message(self, account, queue, message, attributes, filters={}):
100 url = '/%s/%s/%s' % (account, queue, message)
101 url = self._add_parameters(url, attributes, filters)
102 try:
103 return self._request('POST', url).next()
104 except StopIteration:
105 return None
92106
93 def clean(self):107 def clean(self):
94 pass108 pass
@@ -111,7 +125,21 @@
111 connection = httplib.HTTPConnection(*self.server)125 connection = httplib.HTTPConnection(*self.server)
112 connection.request(method, '/v1.0' + url, *args, **kwargs)126 connection.request(method, '/v1.0' + url, *args, **kwargs)
113 response = connection.getresponse()127 response = connection.getresponse()
114 if response.status == 200:128 if response.status >= 200 and response.status < 300:
115 return json.loads(response.read())129 if int(response.getheader('content-length')) == 0:
116 if response.status >= 400:130 if response.status == 201:
117 raise Exception(response.reason)131 yield True
132 return
133 body = response.read()
134 if response.getheader('content-type')[:16] == 'application/json':
135 body = json.loads(body)
136 if isinstance(body, list):
137 for item in body:
138 yield item
139 return
140 yield body
141 if response.status == 400:
142 raise burrow.backend.InvalidArguments()
143 if response.status == 404:
144 raise burrow.backend.NotFound()
145 raise Exception(response.reason)
118146
=== modified file 'burrow/frontend/wsgi.py'
--- burrow/frontend/wsgi.py 2011-08-09 17:22:31 +0000
+++ burrow/frontend/wsgi.py 2011-08-10 05:42:35 +0000
@@ -173,33 +173,24 @@
173 @webob.dec.wsgify173 @webob.dec.wsgify
174 def _delete_message(self, req, account, queue, message):174 def _delete_message(self, req, account, queue, message):
175 filters = self._parse_filters(req)175 filters = self._parse_filters(req)
176 try:176 body = lambda: self.backend.delete_message(account, queue, message,
177 message = self.backend.delete_message(account, queue, message,177 filters)
178 filters)178 return self._response(body=body)
179 except burrow.backend.NotFound:
180 return self._response(status=404)
181 return self._response(body=message)
182179
183 @webob.dec.wsgify180 @webob.dec.wsgify
184 def _get_message(self, req, account, queue, message):181 def _get_message(self, req, account, queue, message):
185 filters = self._parse_filters(req)182 filters = self._parse_filters(req)
186 try:183 body = lambda: self.backend.get_message(account, queue, message,
187 message = self.backend.get_message(account, queue, message,184 filters)
188 filters)185 return self._response(body=body)
189 except burrow.backend.NotFound:
190 return self._response(status=404)
191 return self._response(body=message)
192186
193 @webob.dec.wsgify187 @webob.dec.wsgify
194 def _post_message(self, req, account, queue, message):188 def _post_message(self, req, account, queue, message):
195 attributes = self._parse_attributes(req)189 attributes = self._parse_attributes(req)
196 filters = self._parse_filters(req)190 filters = self._parse_filters(req)
197 try:191 body = lambda: self.backend.update_message(account, queue, message,
198 message = self.backend.update_message(account, queue, message,192 attributes, filters)
199 attributes, filters)193 return self._response(body=body)
200 except burrow.backend.NotFound:
201 return self._response(status=404)
202 return self._response(body=message)
203194
204 @webob.dec.wsgify195 @webob.dec.wsgify
205 def _put_message(self, req, account, queue, message):196 def _put_message(self, req, account, queue, message):
@@ -241,12 +232,17 @@
241 return attributes232 return attributes
242233
243 def _response(self, status=200, body=None, content_type=None):234 def _response(self, status=200, body=None, content_type=None):
244 if isinstance(body, types.GeneratorType):235 try:
245 try:236 if isinstance(body, types.GeneratorType):
246 body = list(body)237 body = list(body)
247 except burrow.backend.NotFound:238 if isinstance(body, types.FunctionType):
248 body = None239 body = body()
249 status = 404240 except burrow.backend.InvalidArguments:
241 status = 400
242 body = None
243 except burrow.backend.NotFound:
244 status = 404
245 body = None
250 if body == []:246 if body == []:
251 body = None247 body = None
252 if body is None:248 if body is None:
@@ -258,11 +254,17 @@
258 if isinstance(body, list) or isinstance(body, dict):254 if isinstance(body, list) or isinstance(body, dict):
259 content_type = 'application/json'255 content_type = 'application/json'
260 else:256 else:
261 content_type = "application/octet-stream"257 content_type = 'application/octet-stream'
262 if content_type == 'application/json':258 if content_type == 'application/json':
263 body = json.dumps(body, indent=2)259 body = json.dumps(body, indent=2)
264 return webob.Response(status=status, body=body,260 response = webob.Response(status=status)
265 content_type=content_type)261 if body is not None:
262 response.content_type = content_type
263 if isinstance(body, unicode):
264 response.unicode_body = body
265 else:
266 response.body = body
267 return response
266268
267269
268class WSGILog(object):270class WSGILog(object):
269271
=== added file 'test/backend/test_http.py'
--- test/backend/test_http.py 1970-01-01 00:00:00 +0000
+++ test/backend/test_http.py 2011-08-10 05:42:35 +0000
@@ -0,0 +1,77 @@
1# Copyright (C) 2011 OpenStack LLC.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain 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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import atexit
16import ConfigParser
17import os
18import signal
19import time
20
21import burrow.server
22import burrow.backend.http
23import test.backend.test_memory
24
25
26class TestHTTP(test.backend.test_memory.TestMemory):
27 '''Unittests for the HTTP backend.'''
28
29 def setUp(self):
30 config = (ConfigParser.ConfigParser(), 'test')
31 self.backend = burrow.backend.http.Backend(config)
32 self.check_empty()
33
34
35def kill_server():
36 try:
37 pid_file = open('server.pid', 'r')
38 pid = pid_file.read()
39 pid_file.close()
40 try:
41 os.kill(int(pid), signal.SIGUSR1)
42 time.sleep(1)
43 os.kill(int(pid), signal.SIGTERM)
44 except OSError:
45 pass
46 os.unlink('server.pid')
47 except IOError:
48 pass
49
50
51def start_server():
52 pid = os.fork()
53 if pid == 0:
54 try:
55 import coverage
56 cov = coverage.coverage(data_suffix=True)
57 cov.start()
58
59 def save_coverage(signum, frame):
60 cov.save()
61
62 signal.signal(signal.SIGUSR1, save_coverage)
63 except:
64 pass
65 server = burrow.server.Server(add_default_log_handler=False)
66 server.frontends[0].default_ttl = 0
67 server.run()
68 os.exit(0)
69 pid_file = open('server.pid', 'w')
70 pid_file.write(str(pid))
71 pid_file.close()
72 time.sleep(1)
73
74
75kill_server()
76start_server()
77atexit.register(kill_server)
078
=== modified file 'test/backend/test_memory.py'
--- test/backend/test_memory.py 2011-08-09 22:53:44 +0000
+++ test/backend/test_memory.py 2011-08-10 05:42:35 +0000
@@ -75,7 +75,7 @@
75 self.backend.create_message('a', 'q', 'm', 'test')75 self.backend.create_message('a', 'q', 'm', 'test')
76 filters = dict(detail='bad')76 filters = dict(detail='bad')
77 accounts = self.backend.delete_accounts(filters)77 accounts = self.backend.delete_accounts(filters)
78 self.assertRaises(burrow.backend.BadDetail, list, accounts)78 self.assertRaises(burrow.backend.InvalidArguments, list, accounts)
79 self.assertEquals([], list(self.backend.delete_accounts()))79 self.assertEquals([], list(self.backend.delete_accounts()))
8080
81 def test_accounts_delete_marker(self):81 def test_accounts_delete_marker(self):
@@ -145,7 +145,7 @@
145 self.backend.create_message('a', 'q', 'm', 'test')145 self.backend.create_message('a', 'q', 'm', 'test')
146 filters = dict(detail='bad')146 filters = dict(detail='bad')
147 accounts = self.backend.get_accounts(filters)147 accounts = self.backend.get_accounts(filters)
148 self.assertRaises(burrow.backend.BadDetail, list, accounts)148 self.assertRaises(burrow.backend.InvalidArguments, list, accounts)
149 self.assertEquals([], list(self.backend.delete_accounts()))149 self.assertEquals([], list(self.backend.delete_accounts()))
150150
151 def test_accounts_get_marker(self):151 def test_accounts_get_marker(self):
@@ -237,7 +237,7 @@
237 self.backend.create_message('a', 'q', 'm', 'test')237 self.backend.create_message('a', 'q', 'm', 'test')
238 filters = dict(detail='bad')238 filters = dict(detail='bad')
239 queues = self.backend.delete_queues('a', filters)239 queues = self.backend.delete_queues('a', filters)
240 self.assertRaises(burrow.backend.BadDetail, list, queues)240 self.assertRaises(burrow.backend.InvalidArguments, list, queues)
241 self.assertEquals([], list(self.backend.delete_queues('a')))241 self.assertEquals([], list(self.backend.delete_queues('a')))
242242
243 def test_queues_delete_marker(self):243 def test_queues_delete_marker(self):
@@ -307,7 +307,7 @@
307 self.backend.create_message('a', 'q', 'm', 'test')307 self.backend.create_message('a', 'q', 'm', 'test')
308 filters = dict(detail='bad')308 filters = dict(detail='bad')
309 queues = self.backend.get_queues('a', filters)309 queues = self.backend.get_queues('a', filters)
310 self.assertRaises(burrow.backend.BadDetail, list, queues)310 self.assertRaises(burrow.backend.InvalidArguments, list, queues)
311 self.assertEquals([], list(self.backend.delete_queues('a')))311 self.assertEquals([], list(self.backend.delete_queues('a')))
312312
313 def test_queues_get_marker(self):313 def test_queues_get_marker(self):
@@ -428,7 +428,7 @@
428 self.backend.create_message('a', 'q', 'm', 'test')428 self.backend.create_message('a', 'q', 'm', 'test')
429 filters = dict(detail='bad')429 filters = dict(detail='bad')
430 messages = self.backend.delete_messages('a', 'q', filters)430 messages = self.backend.delete_messages('a', 'q', filters)
431 self.assertRaises(burrow.backend.BadDetail, list, messages)431 self.assertRaises(burrow.backend.InvalidArguments, list, messages)
432 self.assertEquals([], list(self.backend.delete_messages('a', 'q')))432 self.assertEquals([], list(self.backend.delete_messages('a', 'q')))
433433
434 def test_messages_delete_marker(self):434 def test_messages_delete_marker(self):
@@ -514,7 +514,7 @@
514 self.backend.create_message('a', 'q', 'm', 'test')514 self.backend.create_message('a', 'q', 'm', 'test')
515 filters = dict(detail='bad')515 filters = dict(detail='bad')
516 messages = self.backend.get_messages('a', 'q', filters)516 messages = self.backend.get_messages('a', 'q', filters)
517 self.assertRaises(burrow.backend.BadDetail, list, messages)517 self.assertRaises(burrow.backend.InvalidArguments, list, messages)
518 self.delete_messages()518 self.delete_messages()
519519
520 def test_messages_get_marker(self):520 def test_messages_get_marker(self):
@@ -618,7 +618,7 @@
618 attributes = dict(ttl=100, hide=200)618 attributes = dict(ttl=100, hide=200)
619 filters = dict(detail='bad')619 filters = dict(detail='bad')
620 messages = self.backend.update_messages('a', 'q', attributes, filters)620 messages = self.backend.update_messages('a', 'q', attributes, filters)
621 self.assertRaises(burrow.backend.BadDetail, list, messages)621 self.assertRaises(burrow.backend.InvalidArguments, list, messages)
622 self.delete_messages()622 self.delete_messages()
623623
624 def test_messages_update_marker(self):624 def test_messages_update_marker(self):
@@ -752,7 +752,7 @@
752 def test_message_delete_detail_bad(self):752 def test_message_delete_detail_bad(self):
753 self.backend.create_message('a', 'q', 'm', 'test')753 self.backend.create_message('a', 'q', 'm', 'test')
754 filters = dict(detail='bad')754 filters = dict(detail='bad')
755 self.assertRaises(burrow.backend.BadDetail,755 self.assertRaises(burrow.backend.InvalidArguments,
756 self.backend.delete_message, 'a', 'q', 'm', filters)756 self.backend.delete_message, 'a', 'q', 'm', filters)
757 self.delete_messages()757 self.delete_messages()
758758
@@ -794,7 +794,7 @@
794 def test_message_get_detail_bad(self):794 def test_message_get_detail_bad(self):
795 self.backend.create_message('a', 'q', 'm', 'test')795 self.backend.create_message('a', 'q', 'm', 'test')
796 filters = dict(detail='bad')796 filters = dict(detail='bad')
797 self.assertRaises(burrow.backend.BadDetail,797 self.assertRaises(burrow.backend.InvalidArguments,
798 self.backend.get_message, 'a', 'q', 'm', filters)798 self.backend.get_message, 'a', 'q', 'm', filters)
799 self.delete_messages()799 self.delete_messages()
800800
@@ -848,27 +848,27 @@
848 self.backend.create_message('a', 'q', 'm', 'test')848 self.backend.create_message('a', 'q', 'm', 'test')
849 attributes = dict(ttl=100, hide=200)849 attributes = dict(ttl=100, hide=200)
850 filters = dict(detail='bad')850 filters = dict(detail='bad')
851 self.assertRaises(burrow.backend.BadDetail,851 self.assertRaises(burrow.backend.InvalidArguments,
852 self.backend.update_message, 'a', 'q', 'm', attributes, filters)852 self.backend.update_message, 'a', 'q', 'm', attributes, filters)
853 self.delete_messages()853 self.delete_messages()
854854
855 def test_message_ttl(self):855 def test_message_ttl(self):
856 attributes = dict(ttl=1)856 attributes = dict(ttl=1)
857 self.backend.create_message('a', 'q', 'm', 'test', attributes)857 self.backend.create_message('a', 'q', 'm', 'test', attributes)
858 time.sleep(1)858 time.sleep(2)
859 self.backend.clean()859 self.backend.clean()
860860
861 def test_message_ttl_large(self):861 def test_message_ttl_large(self):
862 attributes = dict(ttl=1)862 attributes = dict(ttl=1)
863 for x in xrange(0, 1000):863 for x in xrange(0, 1000):
864 self.backend.create_message('a', 'q', str(x), str(x), attributes)864 self.backend.create_message('a', 'q', str(x), str(x), attributes)
865 time.sleep(1)865 time.sleep(2)
866 self.backend.clean()866 self.backend.clean()
867867
868 def test_message_hide(self):868 def test_message_hide(self):
869 attributes = dict(hide=1)869 attributes = dict(hide=1)
870 self.backend.create_message('a', 'q', 'm', 'test', attributes)870 self.backend.create_message('a', 'q', 'm', 'test', attributes)
871 time.sleep(1)871 time.sleep(2)
872 self.backend.clean()872 self.backend.clean()
873 message = self.backend.get_message('a', 'q', 'm')873 message = self.backend.get_message('a', 'q', 'm')
874 self.assertEquals(dict(id='m', ttl=0, hide=0, body='test'), message)874 self.assertEquals(dict(id='m', ttl=0, hide=0, body='test'), message)
@@ -878,7 +878,7 @@
878 attributes = dict(hide=1)878 attributes = dict(hide=1)
879 for x in xrange(0, 1000):879 for x in xrange(0, 1000):
880 self.backend.create_message('a', 'q', str(x), str(x), attributes)880 self.backend.create_message('a', 'q', str(x), str(x), attributes)
881 time.sleep(1)881 time.sleep(2)
882 self.backend.clean()882 self.backend.clean()
883 message = self.backend.get_message('a', 'q', '0')883 message = self.backend.get_message('a', 'q', '0')
884 self.assertEquals(dict(id='0', ttl=0, hide=0, body='0'), message)884 self.assertEquals(dict(id='0', ttl=0, hide=0, body='0'), message)

Subscribers

People subscribed via source and target branches