128
50
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
129
"""A request handler that forwards to server.store."""
131
def __init__(self, *args, **kwargs):
132
"""Constructor. Sets up logging."""
133
self.logger = logging.getLogger('http')
134
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
136
52
def do_POST(self):
137
"""Create a message on POST."""
138
53
message = self.rfile.read(int(self.headers['content-length']))
139
scheme, netloc, path, params, query_string, fragments = (
141
parts = path.split('/')
142
if parts[1] == 'archive' and len(parts) == 4:
144
# This expected path is /archive/archive_id/message_id.
145
self.server.store.put_message(parts[2], parts[3], message)
146
self.send_response(httplib.CREATED)
150
self.send_error(httplib.BAD_REQUEST)
54
if message == 'This is a message':
55
self.send_response(httplib.CREATED)
59
self.send_error(httplib.BAD_REQUEST)
153
"""Retrieve a list of messages on GET."""
154
62
scheme, netloc, path, params, query_string, fragments = (
155
63
urlparse(self.path))
156
parts = path.split('/')
157
if parts[1] == 'archive':
159
response = self.server.store.get_messages(
160
parts[2], query_string)
161
self.send_response(httplib.OK)
163
self.wfile.write(simplejson.dumps(response))
164
except Exception, error:
166
httplib.BAD_REQUEST, error.__doc__)
169
def log_message(self, format, *args):
170
"""Override log_message to use standard Python logging."""
171
message = "%s - - [%s] %s\n" % (
172
self.address_string(), self.log_date_time_string(), format % args)
173
self.logger.info(message)
64
archive = os.path.split(path)[1]
65
query = parse_qs(query_string)
66
parameters = simplejson.loads(query['parameters'][0])
67
self.send_response(httplib.OK)
69
messages = [m for m in self.server.messages[archive] if 'message_ids'
70
not in parameters or m['message-id'] in
71
parameters['message_ids']]
72
self.wfile.write(simplejson.dumps(messages))
75
def fake_grackle_service(client, messages=None):
78
return ForkedFake(client.port, messages)
176
81
class TestPutMessage(TestCase):
178
83
def test_put_message(self):
179
client = GrackleClient('localhost', 8420)
180
message_archives = {'arch1': []}
181
with ForkedFakeService.from_client(client, message_archives):
182
client.put_message('arch1', 'id1', StringIO('This is a message'))
183
response = client.get_messages('arch1')
184
self.assertEqual(1, len(response['messages']))
185
message = response['messages'][0]
186
self.assertEqual('id1', message['message_id'])
188
def test_put_message_without_archive(self):
189
client = GrackleClient('localhost', 8421)
190
message_archives = {'arch1': []}
191
with ForkedFakeService.from_client(client, message_archives):
84
client = GrackleClient('localhost', 8436)
85
with fake_grackle_service(client):
86
client.put_message('arch1', 'asdf', StringIO('This is a message'))
192
87
with ExpectedException(Exception, 'wtf'):
193
client.put_message('no-archive', 'id1', StringIO('message'))
88
client.put_message('arch1', 'asdf',
89
StringIO('This is not a message'))
196
92
class TestGetMessages(TestCase):
198
def assertIDOrder(self, ids, messages):
199
self.assertEqual(ids, [m['message_id'] for m in messages])
201
def assertMessageIDs(self, ids, messages):
203
sorted(ids), sorted(messages, key=lambda m: m['message_id']))
205
94
def test_get_messages(self):
206
client = GrackleClient('localhost', 8430)
208
'baz': [make_message('foo'), make_message('bar')]}
209
with ForkedFakeService.from_client(client, archive):
95
client = GrackleClient('localhost', 8435)
96
with fake_grackle_service(client,
98
[{'message-id': 'foo'},
99
{'message-id': 'bar'}]}):
210
100
response = client.get_messages('baz')
211
self.assertEqual(['bar', 'foo'], sorted(m['message_id'] for m in
212
response['messages']))
213
self.assertIs(None, response['next_memo'])
214
self.assertIs(None, response['previous_memo'])
101
self.assertEqual(['bar', 'foo'], sorted(m['message-id'] for m in
216
104
def test_get_messages_by_id(self):
217
105
client = GrackleClient('localhost', 8437)
219
'baz': [make_message('foo'), make_message('bar')]}
220
with ForkedFakeService.from_client(client, archive):
221
response = client.get_messages('baz', message_ids=['foo'])
222
message, = response['messages']
223
self.assertEqual('foo', message['message_id'])
225
def test_get_messages_batching(self):
226
client = GrackleClient('localhost', 8438)
227
archive = {'baz': [make_message('foo'), make_message('bar')]}
228
with ForkedFakeService.from_client(client, archive):
229
response = client.get_messages('baz', limit=1)
230
self.assertEqual(1, len(response['messages']))
231
messages = response['messages']
232
response = client.get_messages(
233
'baz', limit=1, memo=response['next_memo'])
234
self.assertEqual(1, len(response['messages']))
235
messages.extend(response['messages'])
236
self.assertMessageIDs(['foo', 'bar'], messages)
238
def get_messages_member_order_test(self, key):
239
client = GrackleClient('localhost', 8439)
246
make_message('foo', headers={header_name: '2011-03-25'}),
247
make_message('bar', headers={header_name: '2011-03-24'}),
249
with ForkedFakeService.from_client(client, archive):
250
response = client.get_messages('baz')
251
self.assertIDOrder(['foo', 'bar'], response['messages'])
252
response = client.get_messages('baz', order=key)
253
self.assertIDOrder(['bar', 'foo'], response['messages'])
255
def test_get_messages_date_order(self):
256
self.get_messages_member_order_test('date')
258
def test_get_messages_author_order(self):
259
self.get_messages_member_order_test('author')
261
def test_get_messages_subject_order(self):
262
self.get_messages_member_order_test('subject')
264
def test_get_messages_thread_subject_order(self):
267
make_message('bar', headers={'subject': 'y'}),
268
make_message('qux', headers={'subject': 'z'}),
269
make_message('foo', headers={'subject': 'x',
270
'in-reply-to': 'qux'}),
272
client = GrackleClient('localhost', 8439)
273
with ForkedFakeService.from_client(client, archive):
274
response = client.get_messages('baz')
275
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
276
response = client.get_messages('baz', order='subject')
277
self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
278
response = client.get_messages('baz', order='thread_subject')
279
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
281
def test_get_messages_thread_oldest_order(self):
282
client = GrackleClient('localhost', 8439)
285
make_message('bar', headers={'date': 'x'}),
286
make_message('qux', headers={'date': 'z'}),
287
make_message('foo', headers={'date': 'y',
288
'in-reply-to': 'qux'}),
290
with ForkedFakeService.from_client(client, archive):
291
response = client.get_messages('baz')
292
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
293
response = client.get_messages('baz', order='date')
294
self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
295
response = client.get_messages('baz', order='thread_oldest')
296
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
298
def test_get_messages_thread_newest_order(self):
299
client = GrackleClient('localhost', 8439)
302
make_message('bar', headers={'date': 'x'}),
303
make_message('qux', headers={'date': 'w'}),
304
make_message('foo', headers={'date': 'y',
305
'in-reply-to': 'bar'}),
306
make_message('baz', headers={'date': 'z',
307
'in-reply-to': 'qux'}),
309
with ForkedFakeService.from_client(client, archive):
310
response = client.get_messages('baz', order='date')
312
['qux', 'bar', 'foo', 'baz'], response['messages'])
313
response = client.get_messages('baz', order='thread_newest')
315
['bar', 'foo', 'qux', 'baz'], response['messages'])
317
def test_get_messages_unsupported_order(self):
318
client = GrackleClient('localhost', 8439)
321
make_message('foo', headers={'date': '2011-03-25'}),
322
make_message('foo', headers={'date': '2011-03-24'}),
324
with ForkedFakeService.from_client(client, archive):
325
with ExpectedException(UnsupportedOrder, ''):
326
client.get_messages('baz', order='nonsense')
328
def test_get_messages_headers_no_headers(self):
329
client = GrackleClient('localhost', 8440)
330
archive = {'baz': [make_message('foo')]}
331
with ForkedFakeService.from_client(client, archive):
332
response = client.get_messages('baz', headers=[
333
'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
334
first_message = response['messages'][0]
335
self.assertEqual('foo', first_message['message_id'])
336
self.assertEqual({}, first_message['headers'])
338
def test_get_messages_headers_exclude_headers(self):
339
client = GrackleClient('localhost', 8441)
341
'baz': [make_message('foo', headers={'From': 'me'})]}
342
with ForkedFakeService.from_client(client, archive):
343
response = client.get_messages('baz', headers=[
344
'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
345
first_message = response['messages'][0]
346
self.assertEqual('foo', first_message['message_id'])
347
self.assertEqual({}, first_message['headers'])
349
def test_get_messages_headers_include_headers(self):
350
client = GrackleClient('localhost', 8442)
353
make_message('foo', headers={'From': 'me', 'To': 'you'})]}
354
with ForkedFakeService.from_client(client, archive):
355
response = client.get_messages('baz', headers=[
357
first_message = response['messages'][0]
358
self.assertEqual('foo', first_message['message_id'])
359
self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
361
def test_get_messages_max_body_length(self):
362
client = GrackleClient('localhost', 8443)
363
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
364
with ForkedFakeService.from_client(client, archive):
365
response = client.get_messages('baz', max_body_length=3)
366
first_message = response['messages'][0]
367
self.assertEqual('abc', first_message['body'])
369
def test_include_hidden(self):
370
client = GrackleClient('localhost', 8444)
373
make_message('foo', hidden=True),
374
make_message('bar', hidden=False),
376
with ForkedFakeService.from_client(client, archive):
377
response = client.get_messages('baz', include_hidden=True)
378
self.assertMessageIDs(['bar', 'foo'], response['messages'])
379
response = client.get_messages('baz', include_hidden=False)
380
self.assertMessageIDs(['bar'], response['messages'])
382
def test_display_type_unknown_value(self):
383
client = GrackleClient('localhost', 8445)
384
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
385
with ForkedFakeService.from_client(client, archive):
386
with ExpectedException(UnsupportedDisplayType, ''):
387
client.get_messages('baz', display_type='unknown')
389
def test_display_type_headers_only(self):
390
client = GrackleClient('localhost', 8446)
393
make_message('foo', body=u'abcdefghi',
394
headers={'From': 'me', 'To': 'you'})]}
395
with ForkedFakeService.from_client(client, archive):
396
response = client.get_messages('baz', display_type='headers-only')
397
first_message = response['messages'][0]
398
self.assertEqual('foo', first_message['message_id'])
400
archive['baz'][0]['headers'], first_message['headers'])
401
self.assertNotIn('body', first_message)
403
def test_display_type_text_only(self):
404
client = GrackleClient('localhost', 8446)
409
headers={'From': 'me', 'To': 'you'},
410
attachment_type='text/x-diff')]}
411
with ForkedFakeService.from_client(client, archive):
412
response = client.get_messages('baz', display_type='text-only')
413
first_message = response['messages'][0]
414
self.assertEqual('foo', first_message['message_id'])
415
self.assertEqual('me', first_message['headers']['From'])
416
self.assertEqual('you', first_message['headers']['To'])
417
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
419
def test_display_type_all(self):
420
client = GrackleClient('localhost', 8447)
425
headers={'From': 'me', 'To': 'you'},
426
attachment_type='text/x-diff')]}
427
with ForkedFakeService.from_client(client, archive):
428
response = client.get_messages('baz', display_type='all')
429
first_message = response['messages'][0]
430
self.assertEqual('foo', first_message['message_id'])
431
self.assertEqual('me', first_message['headers']['From'])
432
self.assertEqual('you', first_message['headers']['To'])
433
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
435
def test_date_range(self):
436
client = GrackleClient('localhost', 8448)
440
'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
442
'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
444
'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
446
'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
448
'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
450
with ForkedFakeService.from_client(client, archive):
451
response = client.get_messages(
452
'baz', date_range='2012-01-01..2012-01-31')
453
ids = sorted(m['message_id'] for m in response['messages'])
454
self.assertEqual(['bar', 'naf', 'qux'], ids)
456
def test_date_range_unparsabledaterange(self):
457
client = GrackleClient('localhost', 8449)
458
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
459
with ForkedFakeService.from_client(client, archive):
460
with ExpectedException(UnparsableDateRange, ''):
461
client.get_messages('baz', date_range='2012-01-01')
463
def test_date_range_unparsabledaterange_missing_part(self):
464
client = GrackleClient('localhost', 8450)
465
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
466
with ForkedFakeService.from_client(client, archive):
467
with ExpectedException(UnparsableDateRange, ''):
468
client.get_messages('baz', date_range='2012-01-01..')
470
def test_date_range_unparsabledaterange_extra_part(self):
471
client = GrackleClient('localhost', 8451)
472
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
473
with ForkedFakeService.from_client(client, archive):
474
with ExpectedException(UnparsableDateRange, ''):
475
client.get_messages('baz', date_range='2012-01..12-02..12-03')
106
with fake_grackle_service(client,
108
[{'message-id': 'foo'},
109
{'message-id': 'bar'}]}):
110
message, = client.get_messages('baz', message_ids=['foo'])
111
self.assertEqual('foo', message['message-id'])