~eday/burrow/prototype-conversion

« back to all changes in this revision

Viewing changes to test/frontend/test_wsgi.py

  • Committer: Eric Day
  • Date: 2011-03-17 23:42:41 UTC
  • Revision ID: eday@oddments.org-20110317234241-ult80xn9d1lon867
First chunk of code from prototype. Beyond the prototype, configuration, module loading, and log handling was added.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
15
import ConfigParser
 
16
import json
 
17
import time
 
18
import unittest
 
19
 
 
20
import eventlet
 
21
import webob
 
22
 
 
23
import burrowd.backend.memory
 
24
import burrowd.backend.sqlite
 
25
import burrowd.frontend.wsgi
 
26
 
 
27
 
 
28
class TestWSGIMemory(unittest.TestCase):
 
29
    '''Unittests for the WSGI frontend to SQLite backend.'''
 
30
    backend_class = burrowd.backend.memory.Backend
 
31
 
 
32
    def setUp(self):
 
33
        config = (ConfigParser.ConfigParser(), 'test')
 
34
        self.backend = self.backend_class(config)
 
35
        self.frontend = burrowd.frontend.wsgi.Frontend(config, self.backend)
 
36
        self.frontend.default_ttl = 0
 
37
        self._get_url('/', status=404)
 
38
        self._get_url('/a', status=404)
 
39
        self._get_url('/a/q', status=404)
 
40
 
 
41
    def tearDown(self):
 
42
        self._get_url('/a/q', status=404)
 
43
        self._get_url('/a', status=404)
 
44
        self._get_url('/', status=404)
 
45
 
 
46
    def test_account(self):
 
47
        self._put_url('/a/q/1')
 
48
        accounts = self._get_url('/')
 
49
        self.assertEquals(accounts, ['a'])
 
50
        self._delete_url('/a')
 
51
 
 
52
    def test_queue(self):
 
53
        self._put_url('/a/q/1')
 
54
        accounts = self._get_url('/a')
 
55
        self.assertEquals(accounts, ['q'])
 
56
        self._delete_url('/a/q')
 
57
 
 
58
    def test_message(self):
 
59
        self._put_url('/a/q/1', body='b')
 
60
        accounts = self._get_url('/a/q')
 
61
        self.assertMessages(accounts, 'a', 'q', [self.message('1', body='b')])
 
62
        self._delete_url('/a/q/1')
 
63
 
 
64
    def test_message_post(self):
 
65
        self._put_url('/a/q/1', body='b')
 
66
        for x in range(0, 3):
 
67
            accounts = self._post_url('/a/q/1?ttl=%d&hide=%d' % (x, x))
 
68
            self.assertEquals(accounts, {'a': {'q': [{'id': '1'}]}})
 
69
            accounts = self._get_url('/a/q?hidden=true')
 
70
            message = self.message('1', x, x, body='b')
 
71
            self.assertMessages(accounts, 'a', 'q', [message])
 
72
        self._delete_url('/a/q/1')
 
73
 
 
74
    def test_message_put(self):
 
75
        for x in range(0, 3):
 
76
            url = '/a/q/1?ttl=%d&hide=%d' % (x, x)
 
77
            status = 201 if x == 0 else 204
 
78
            self._put_url(url, body=str(x), status=status)
 
79
            accounts = self._get_url('/a/q?hidden=true')
 
80
            message = self.message('1', x, x, body=str(x))
 
81
            self.assertMessages(accounts, 'a', 'q', [message])
 
82
        self._delete_url('/a/q/1')
 
83
 
 
84
    def test_message_delete_limit(self):
 
85
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
86
        accounts = self._delete_url('/a/q?limit=3&detail=all', status=200)
 
87
        messages = []
 
88
        messages.append(self.message('1'))
 
89
        messages.append(self.message('2'))
 
90
        messages.append(self.message('3'))
 
91
        self.assertMessages(accounts, 'a', 'q', messages)
 
92
        accounts = self._delete_url('/a/q?limit=3&detail=all', status=200)
 
93
        message = self.message('4')
 
94
        self.assertMessages(accounts, 'a', 'q', [message])
 
95
 
 
96
    def test_message_get_limit(self):
 
97
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
98
        for x in range(0, 4):
 
99
            accounts = self._get_url('/a/q?limit=3')
 
100
            messages = []
 
101
            for y in range(x, 4)[:3]:
 
102
                messages.append(self.message(str(y + 1)))
 
103
            self.assertMessages(accounts, 'a', 'q', messages)
 
104
            self._delete_url('/a/q/%d' % (x + 1))
 
105
 
 
106
    def test_message_post_limit(self):
 
107
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
108
        for x in range(0, 4):
 
109
            accounts = self._post_url('/a/q?limit=3&ttl=%d&detail=all' % x)
 
110
            messages = []
 
111
            for y in range(x, 4)[:3]:
 
112
                messages.append(self.message(str(y + 1), x))
 
113
            self.assertMessages(accounts, 'a', 'q', messages)
 
114
            self._delete_url('/a/q/%d' % (x + 1))
 
115
 
 
116
    def test_message_delete_marker(self):
 
117
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
118
        accounts = self._delete_url('/a/q?marker=2&detail=all', status=200)
 
119
        messages = []
 
120
        messages.append(self.message('3'))
 
121
        messages.append(self.message('4'))
 
122
        self.assertMessages(accounts, 'a', 'q', messages)
 
123
        accounts = self._delete_url('/a/q?marker=5&detail=all', status=200)
 
124
        messages = []
 
125
        messages.append(self.message('1'))
 
126
        messages.append(self.message('2'))
 
127
        self.assertMessages(accounts, 'a', 'q', messages)
 
128
 
 
129
    def test_message_get_marker(self):
 
130
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
131
        for x in range(0, 4):
 
132
            accounts = self._get_url('/a/q?marker=%d' % x)
 
133
            messages = []
 
134
            for y in range(x, 4):
 
135
                messages.append(self.message(str(y + 1)))
 
136
            self.assertMessages(accounts, 'a', 'q', messages)
 
137
            self._delete_url('/a/q/%d' % (x + 1))
 
138
 
 
139
    def test_message_post_marker(self):
 
140
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
141
        for x in range(0, 4):
 
142
            url = '/a/q?marker=%d&ttl=%d&detail=all' % (x, x)
 
143
            accounts = self._post_url(url)
 
144
            messages = []
 
145
            for y in range(x, 4):
 
146
                messages.append(self.message(str(y + 1), x))
 
147
            self.assertMessages(accounts, 'a', 'q', messages)
 
148
            self._delete_url('/a/q/%d' % (x + 1))
 
149
 
 
150
    def test_message_delete_limit_marker(self):
 
151
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
152
        url = '/a/q?limit=2&marker=1&detail=all'
 
153
        accounts = self._delete_url(url, status=200)
 
154
        messages = []
 
155
        messages.append(self.message('2'))
 
156
        messages.append(self.message('3'))
 
157
        self.assertMessages(accounts, 'a', 'q', messages)
 
158
        url = '/a/q?limit=2&marker=5&detail=all'
 
159
        accounts = self._delete_url(url, status=200)
 
160
        messages = []
 
161
        messages.append(self.message('1'))
 
162
        messages.append(self.message('4'))
 
163
        self.assertMessages(accounts, 'a', 'q', messages)
 
164
 
 
165
    def test_message_get_limit_marker(self):
 
166
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
167
        for x in range(0, 4):
 
168
            accounts = self._get_url('/a/q?limit=2&marker=%d' % x)
 
169
            messages = []
 
170
            for y in range(x, 4)[:2]:
 
171
                messages.append(self.message(str(y + 1)))
 
172
            self.assertMessages(accounts, 'a', 'q', messages)
 
173
            self._delete_url('/a/q/%d' % (x + 1))
 
174
 
 
175
    def test_message_post_limit_marker(self):
 
176
        [self._put_url('/a/q/%d' % x) for x in range(1, 5)]
 
177
        for x in range(0, 4):
 
178
            url = '/a/q?limit=2&marker=%d&ttl=%d&detail=all' % (x, x)
 
179
            accounts = self._post_url(url)
 
180
            messages = []
 
181
            for y in range(x, 4)[:2]:
 
182
                messages.append(self.message(str(y + 1), x))
 
183
            self.assertMessages(accounts, 'a', 'q', messages)
 
184
            self._delete_url('/a/q/%d' % (x + 1))
 
185
 
 
186
    def test_message_ttl(self):
 
187
        self._put_url('/a/q/1?ttl=1')
 
188
        accounts = self._get_url('/a/q/1')
 
189
        message = self.message('1', 1)
 
190
        self.assertMessages(accounts, 'a', 'q', [self.message('1', 1)])
 
191
        time.sleep(1)
 
192
        self.backend.clean()
 
193
        self._get_url('/a/q/1', status=404)
 
194
        self._put_url('/a/q/1')
 
195
        accounts = self._get_url('/a/q/1')
 
196
        self.assertMessages(accounts, 'a', 'q', [self.message('1')])
 
197
        self._post_url('/a/q/1?ttl=1')
 
198
        accounts = self._get_url('/a/q/1')
 
199
        self.assertMessages(accounts, 'a', 'q', [self.message('1', 1)])
 
200
        time.sleep(1)
 
201
        self.backend.clean()
 
202
        self._get_url('/a/q/1', status=404)
 
203
 
 
204
    def test_message_hide(self):
 
205
        self._put_url('/a/q/1?hide=1')
 
206
        accounts = self._get_url('/a/q/1')
 
207
        self.assertMessages(accounts, 'a', 'q', [self.message('1', hide=1)])
 
208
        time.sleep(1)
 
209
        self.backend.clean()
 
210
        accounts = self._get_url('/a/q/1')
 
211
        self.assertMessages(accounts, 'a', 'q', [self.message('1')])
 
212
        self._post_url('/a/q/1?hide=1')
 
213
        accounts = self._get_url('/a/q/1')
 
214
        self.assertMessages(accounts, 'a', 'q', [self.message('1', hide=1)])
 
215
        time.sleep(1)
 
216
        self.backend.clean()
 
217
        accounts = self._get_url('/a/q/1')
 
218
        self.assertMessages(accounts, 'a', 'q', [self.message('1')])
 
219
        self._delete_url('/a/q/1')
 
220
 
 
221
    def _message_wait(self):
 
222
        accounts = self._get_url('/a/q?wait=2')
 
223
        self.assertMessages(accounts, 'a', 'q', [self.message('1')])
 
224
        self.success = True
 
225
 
 
226
    def test_message_put_wait(self):
 
227
        self.success = False
 
228
        thread = eventlet.spawn(self._message_wait)
 
229
        eventlet.spawn_after(0.2, self._put_url, '/a/q/1')
 
230
        thread.wait()
 
231
        self.assertTrue(self.success)
 
232
        self._delete_url('/a/q/1')
 
233
 
 
234
    def test_message_put_wait_overwrite(self):
 
235
        self.success = False
 
236
        self._put_url('/a/q/1?hide=10')
 
237
        thread = eventlet.spawn(self._message_wait)
 
238
        eventlet.spawn_after(0.2, self._put_url, '/a/q/1?hide=0', status=204)
 
239
        thread.wait()
 
240
        self.assertTrue(self.success)
 
241
        self._delete_url('/a/q/1')
 
242
 
 
243
    def test_message_put_wait_cleanup(self):
 
244
        self.success = False
 
245
        self._put_url('/a/q/1?hide=1')
 
246
        thread = eventlet.spawn(self._message_wait)
 
247
        eventlet.spawn_after(1, self.backend.clean)
 
248
        thread.wait()
 
249
        self.assertTrue(self.success)
 
250
        self._delete_url('/a/q/1')
 
251
 
 
252
    def test_message_post_wait(self):
 
253
        self.success = False
 
254
        self._put_url('/a/q/1?hide=10')
 
255
        thread = eventlet.spawn(self._message_wait)
 
256
        eventlet.spawn_after(0.2, self._post_url, '/a/q/1?hide=0')
 
257
        thread.wait()
 
258
        self.assertTrue(self.success)
 
259
        self._delete_url('/a/q/1')
 
260
 
 
261
    def test_message_post_wait_queue(self):
 
262
        self.success = False
 
263
        self._put_url('/a/q/1?hide=10')
 
264
        thread = eventlet.spawn(self._message_wait)
 
265
        eventlet.spawn_after(0.2, self._post_url, '/a/q?hide=0&hidden=true')
 
266
        thread.wait()
 
267
        self.assertTrue(self.success)
 
268
        self._delete_url('/a/q/1')
 
269
 
 
270
    def message(self, id, ttl=0, hide=0, body=''):
 
271
        return dict(id=id, ttl=ttl, hide=hide, body=body)
 
272
 
 
273
    def assertMessages(self, accounts, account, queue, messages):
 
274
        self.assertEquals(len(accounts), 1)
 
275
        self.assertEquals(len(accounts['a']), 1)
 
276
        self.assertEquals(len(accounts['a']['q']), len(messages))
 
277
        for x in range(0, len(messages)):
 
278
            self.assertEquals(accounts['a']['q'][x]['id'], messages[x]['id'])
 
279
            ttl = messages[x]['ttl']
 
280
            if ttl > 0:
 
281
                ttl += int(time.time())
 
282
            self.assertAlmostEquals(accounts['a']['q'][0]['ttl'], ttl)
 
283
            hide = messages[x]['hide']
 
284
            if hide > 0:
 
285
                hide += int(time.time())
 
286
            self.assertAlmostEquals(accounts['a']['q'][0]['hide'], hide)
 
287
            body = messages[x]['body']
 
288
            self.assertEquals(accounts['a']['q'][x]['body'], body)
 
289
 
 
290
    def _delete_url(self, url, status=204, **kwargs):
 
291
        return self._url('DELETE', url, status=status, **kwargs)
 
292
 
 
293
    def _get_url(self, url, **kwargs):
 
294
        return self._url('GET', url, **kwargs)
 
295
 
 
296
    def _post_url(self, url, **kwargs):
 
297
        return self._url('POST', url, **kwargs)
 
298
 
 
299
    def _put_url(self, url, status=201, **kwargs):
 
300
        return self._url('PUT', url, status=status, **kwargs)
 
301
 
 
302
    def _url(self, method, url, body='', status=200):
 
303
        req = webob.Request.blank(url, method=method, body=body)
 
304
        res = req.get_response(self.frontend)
 
305
        self.assertEquals(res.status_int, status)
 
306
        if status == 200:
 
307
            return json.loads(res.body)
 
308
        return None
 
309
 
 
310
 
 
311
class TestWSGISQLite(TestWSGIMemory):
 
312
    '''Unittests for the WSGI frontend to SQLite backend.'''
 
313
    backend_class = burrowd.backend.sqlite.Backend