1
from BaseHTTPServer import (
3
BaseHTTPRequestHandler,
7
from signal import SIGKILL
3
from email.message import Message
4
from email.mime.multipart import MIMEMultipart
5
from email.mime.text import MIMEText
8
6
from StringIO import StringIO
9
7
from unittest import TestCase
11
9
from testtools import ExpectedException
13
from grackle import client
18
def __init__(self, func_or_method):
19
self.func_or_method = func_or_method
30
def __exit__(self, exc_type, exc_val, traceback):
31
os.kill(self.pid, SIGKILL)
34
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
37
message = self.rfile.read(int(self.headers['content-length']))
38
if message == 'This is a message':
39
self.send_response(httplib.CREATED)
43
self.send_error(httplib.BAD_REQUEST)
47
service = HTTPServer(('', 8435), FakeGrackleRequestHandler)
48
service.serve_forever()
11
from grackle.client import GrackleClient
12
from grackle.error import (
15
UnsupportedDisplayType,
18
from grackle.service import ForkedFakeService
19
from grackle.store import make_json_message
22
def make_message(message_id, body='body', headers=None, hidden=False):
26
'Message-Id': message_id,
32
message_headers.update(headers.items())
34
message.set_payload(body)
35
for key, value in message_headers.items():
37
return make_json_message(message_id, message.as_string(), hidden)
40
def make_mime_message(message_id, body='body', headers=None, hidden=False,
41
attachment_type=None):
42
parts = MIMEMultipart()
43
parts.attach(MIMEText(body))
44
if attachment_type is not None:
45
attachment = Message()
46
attachment.set_payload('attactment data.')
47
attachment['Content-Type'] = attachment_type
48
attachment['Content-Disposition'] = 'attachment; filename="file.ext"'
49
parts.attach(attachment)
50
return make_message(message_id, parts.as_string(), headers, hidden)
53
class TestPutArchive(TestCase):
55
def test_put_archive(self):
56
client = GrackleClient('localhost', 8410)
58
with ForkedFakeService.from_client(client, message_archives):
59
client.put_archive('arch1')
60
response = client.get_messages('arch1')
61
self.assertEqual(0, len(response['messages']))
63
def test_put_archive_existing_archive(self):
64
client = GrackleClient('localhost', 8411)
65
message_archives = {'arch1': []}
66
with ForkedFakeService.from_client(client, message_archives):
67
with ExpectedException(ArchiveIdExists, ''):
68
client.put_archive('arch1')
52
71
class TestPutMessage(TestCase):
54
73
def test_put_message(self):
55
with Forked(run_service):
56
client.put_message('arch1', StringIO('This is a message'))
74
client = GrackleClient('localhost', 8420)
75
message_archives = {'arch1': []}
76
with ForkedFakeService.from_client(client, message_archives):
77
client.put_message('arch1', 'id1', StringIO('This is a message'))
78
response = client.get_messages('arch1')
79
self.assertEqual(1, len(response['messages']))
80
message = response['messages'][0]
81
self.assertEqual('id1', message['message_id'])
83
def test_put_message_without_archive(self):
84
client = GrackleClient('localhost', 8421)
85
message_archives = {'arch1': []}
86
with ForkedFakeService.from_client(client, message_archives):
57
87
with ExpectedException(Exception, 'wtf'):
58
client.put_message('arch1', StringIO('This is not a message'))
88
client.put_message('no-archive', 'id1', StringIO('message'))
91
class TestGetMessages(TestCase):
93
def assertIDOrder(self, ids, messages):
94
self.assertEqual(ids, [m['message_id'] for m in messages])
96
def assertMessageIDs(self, ids, messages):
98
sorted(ids), sorted(messages, key=lambda m: m['message_id']))
100
def test_get_messages(self):
101
client = GrackleClient('localhost', 8430)
103
'baz': [make_message('foo'), make_message('bar')]}
104
with ForkedFakeService.from_client(client, archive):
105
response = client.get_messages('baz')
106
self.assertEqual(['bar', 'foo'], sorted(m['message_id'] for m in
107
response['messages']))
108
self.assertIs(None, response['next_memo'])
109
self.assertIs(None, response['previous_memo'])
111
def test_get_messages_by_id(self):
112
client = GrackleClient('localhost', 8437)
114
'baz': [make_message('foo'), make_message('bar')]}
115
with ForkedFakeService.from_client(client, archive):
116
response = client.get_messages('baz', message_ids=['foo'])
117
message, = response['messages']
118
self.assertEqual('foo', message['message_id'])
120
def test_get_messages_batching(self):
121
client = GrackleClient('localhost', 8438)
122
archive = {'baz': [make_message('foo'), make_message('bar')]}
123
with ForkedFakeService.from_client(client, archive):
124
response = client.get_messages('baz', limit=1)
125
self.assertEqual(1, len(response['messages']))
126
messages = response['messages']
127
response = client.get_messages(
128
'baz', limit=1, memo=response['next_memo'])
129
self.assertEqual(1, len(response['messages']))
130
messages.extend(response['messages'])
131
self.assertMessageIDs(['foo', 'bar'], messages)
133
def get_messages_member_order_test(self, key):
134
client = GrackleClient('localhost', 8439)
141
make_message('foo', headers={header_name: '2011-03-25'}),
142
make_message('bar', headers={header_name: '2011-03-24'}),
144
with ForkedFakeService.from_client(client, archive):
145
response = client.get_messages('baz')
146
self.assertIDOrder(['foo', 'bar'], response['messages'])
147
response = client.get_messages('baz', order=key)
148
self.assertIDOrder(['bar', 'foo'], response['messages'])
150
def test_get_messages_date_order(self):
151
self.get_messages_member_order_test('date')
153
def test_get_messages_author_order(self):
154
self.get_messages_member_order_test('author')
156
def test_get_messages_subject_order(self):
157
self.get_messages_member_order_test('subject')
159
def test_get_messages_thread_subject_order(self):
162
make_message('bar', headers={'subject': 'y'}),
163
make_message('qux', headers={'subject': 'z'}),
164
make_message('foo', headers={'subject': 'x',
165
'in-reply-to': 'qux'}),
167
client = GrackleClient('localhost', 8439)
168
with ForkedFakeService.from_client(client, archive):
169
response = client.get_messages('baz')
170
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
171
response = client.get_messages('baz', order='subject')
172
self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
173
response = client.get_messages('baz', order='thread_subject')
174
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
176
def test_get_messages_thread_oldest_order(self):
177
client = GrackleClient('localhost', 8439)
180
make_message('bar', headers={'date': 'x'}),
181
make_message('qux', headers={'date': 'z'}),
182
make_message('foo', headers={'date': 'y',
183
'in-reply-to': 'qux'}),
185
with ForkedFakeService.from_client(client, archive):
186
response = client.get_messages('baz')
187
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
188
response = client.get_messages('baz', order='date')
189
self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
190
response = client.get_messages('baz', order='thread_oldest')
191
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
193
def test_get_messages_thread_newest_order(self):
194
client = GrackleClient('localhost', 8439)
197
make_message('bar', headers={'date': 'x'}),
198
make_message('qux', headers={'date': 'w'}),
199
make_message('foo', headers={'date': 'y',
200
'in-reply-to': 'bar'}),
201
make_message('baz', headers={'date': 'z',
202
'in-reply-to': 'qux'}),
204
with ForkedFakeService.from_client(client, archive):
205
response = client.get_messages('baz', order='date')
207
['qux', 'bar', 'foo', 'baz'], response['messages'])
208
response = client.get_messages('baz', order='thread_newest')
210
['bar', 'foo', 'qux', 'baz'], response['messages'])
212
def test_get_messages_unsupported_order(self):
213
client = GrackleClient('localhost', 8439)
216
make_message('foo', headers={'date': '2011-03-25'}),
217
make_message('foo', headers={'date': '2011-03-24'}),
219
with ForkedFakeService.from_client(client, archive):
220
with ExpectedException(UnsupportedOrder, ''):
221
client.get_messages('baz', order='nonsense')
223
def test_get_messages_headers_no_headers(self):
224
client = GrackleClient('localhost', 8440)
225
archive = {'baz': [make_message('foo')]}
226
with ForkedFakeService.from_client(client, archive):
227
response = client.get_messages('baz', headers=[
228
'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
229
first_message = response['messages'][0]
230
self.assertEqual('foo', first_message['message_id'])
231
self.assertEqual({}, first_message['headers'])
233
def test_get_messages_headers_exclude_headers(self):
234
client = GrackleClient('localhost', 8441)
236
'baz': [make_message('foo', headers={'From': 'me'})]}
237
with ForkedFakeService.from_client(client, archive):
238
response = client.get_messages('baz', headers=[
239
'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
240
first_message = response['messages'][0]
241
self.assertEqual('foo', first_message['message_id'])
242
self.assertEqual({}, first_message['headers'])
244
def test_get_messages_headers_include_headers(self):
245
client = GrackleClient('localhost', 8442)
248
make_message('foo', headers={'From': 'me', 'To': 'you'})]}
249
with ForkedFakeService.from_client(client, archive):
250
response = client.get_messages('baz', headers=[
252
first_message = response['messages'][0]
253
self.assertEqual('foo', first_message['message_id'])
254
self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
256
def test_get_messages_max_body_length(self):
257
client = GrackleClient('localhost', 8443)
258
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
259
with ForkedFakeService.from_client(client, archive):
260
response = client.get_messages('baz', max_body_length=3)
261
first_message = response['messages'][0]
262
self.assertEqual('abc', first_message['body'])
264
def test_include_hidden(self):
265
client = GrackleClient('localhost', 8444)
268
make_message('foo', hidden=True),
269
make_message('bar', hidden=False),
271
with ForkedFakeService.from_client(client, archive):
272
response = client.get_messages('baz', include_hidden=True)
273
self.assertMessageIDs(['bar', 'foo'], response['messages'])
274
response = client.get_messages('baz', include_hidden=False)
275
self.assertMessageIDs(['bar'], response['messages'])
277
def test_display_type_unknown_value(self):
278
client = GrackleClient('localhost', 8445)
279
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
280
with ForkedFakeService.from_client(client, archive):
281
with ExpectedException(UnsupportedDisplayType, ''):
282
client.get_messages('baz', display_type='unknown')
284
def test_display_type_headers_only(self):
285
client = GrackleClient('localhost', 8446)
288
make_message('foo', body=u'abcdefghi',
289
headers={'From': 'me', 'To': 'you'})]}
290
with ForkedFakeService.from_client(client, archive):
291
response = client.get_messages('baz', display_type='headers-only')
292
first_message = response['messages'][0]
293
self.assertEqual('foo', first_message['message_id'])
295
archive['baz'][0]['headers'], first_message['headers'])
296
self.assertNotIn('body', first_message)
298
def test_display_type_text_only(self):
299
client = GrackleClient('localhost', 8446)
304
headers={'From': 'me', 'To': 'you'},
305
attachment_type='text/x-diff')]}
306
with ForkedFakeService.from_client(client, archive):
307
response = client.get_messages('baz', display_type='text-only')
308
first_message = response['messages'][0]
309
self.assertEqual('foo', first_message['message_id'])
310
self.assertEqual('me', first_message['headers']['From'])
311
self.assertEqual('you', first_message['headers']['To'])
312
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
314
def test_display_type_all(self):
315
client = GrackleClient('localhost', 8447)
320
headers={'From': 'me', 'To': 'you'},
321
attachment_type='text/x-diff')]}
322
with ForkedFakeService.from_client(client, archive):
323
response = client.get_messages('baz', display_type='all')
324
first_message = response['messages'][0]
325
self.assertEqual('foo', first_message['message_id'])
326
self.assertEqual('me', first_message['headers']['From'])
327
self.assertEqual('you', first_message['headers']['To'])
328
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
330
def test_date_range(self):
331
client = GrackleClient('localhost', 8448)
335
'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
337
'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
339
'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
341
'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
343
'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
345
with ForkedFakeService.from_client(client, archive):
346
response = client.get_messages(
347
'baz', date_range='2012-01-01..2012-01-31')
348
ids = sorted(m['message_id'] for m in response['messages'])
349
self.assertEqual(['bar', 'naf', 'qux'], ids)
351
def test_date_range_unparsabledaterange(self):
352
client = GrackleClient('localhost', 8449)
353
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
354
with ForkedFakeService.from_client(client, archive):
355
with ExpectedException(UnparsableDateRange, ''):
356
client.get_messages('baz', date_range='2012-01-01')
358
def test_date_range_unparsabledaterange_missing_part(self):
359
client = GrackleClient('localhost', 8450)
360
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
361
with ForkedFakeService.from_client(client, archive):
362
with ExpectedException(UnparsableDateRange, ''):
363
client.get_messages('baz', date_range='2012-01-01..')
365
def test_date_range_unparsabledaterange_extra_part(self):
366
client = GrackleClient('localhost', 8451)
367
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
368
with ForkedFakeService.from_client(client, archive):
369
with ExpectedException(UnparsableDateRange, ''):
370
client.get_messages('baz', date_range='2012-01..12-02..12-03')
373
class TestHideMessages(TestCase):
375
def test_hide_message_true(self):
376
client = GrackleClient('localhost', 8470)
379
make_message('foo', hidden=False),
381
with ForkedFakeService.from_client(client, archive):
382
response = client.hide_message('baz', 'foo', hidden=True)
383
self.assertEqual('foo', response['message_id'])
384
self.assertIs(True, response['hidden'])
386
def test_hide_message_false(self):
387
client = GrackleClient('localhost', 8470)
390
make_message('foo', hidden=True),
392
with ForkedFakeService.from_client(client, archive):
393
response = client.hide_message('baz', 'foo', hidden=False)
394
self.assertEqual('foo', response['message_id'])
395
self.assertIs(False, response['hidden'])