18
18
from testtools import ExpectedException
20
from grackle.client import (
20
from grackle.client import GrackleClient
21
from grackle.error import (
22
23
UnparsableDateRange,
23
24
UnsupportedDisplayType,
26
27
from grackle.store import (
31
33
def make_message(message_id, body='body', headers=None, hidden=False):
32
34
if headers is None:
34
headers['Message-Id'] = message_id
36
'message_id': message_id,
38
'thread_id': message_id,
39
'date': headers.get('date', '2005-01-01'),
40
'subject': headers.get('subject', 'subject'),
41
'author': headers.get('author', 'author'),
44
'replies': headers.get('in-reply-to', None),
37
'Message-Id': message_id,
43
message_headers.update(headers.items())
45
message.set_payload(body)
46
for key, value in message_headers.items():
48
return make_json_message(message_id, message.as_string(), hidden)
50
51
def make_mime_message(message_id, body='body', headers=None, hidden=False,
51
52
attachment_type=None):
52
message = MIMEMultipart()
53
message.attach(MIMEText(body))
53
parts = MIMEMultipart()
54
parts.attach(MIMEText(body))
54
55
if attachment_type is not None:
55
56
attachment = Message()
56
57
attachment.set_payload('attactment data.')
57
58
attachment['Content-Type'] = attachment_type
58
59
attachment['Content-Disposition'] = 'attachment; filename="file.ext"'
59
message.attach(attachment)
60
return make_message(message_id, message.get_payload(), headers, hidden)
60
parts.attach(attachment)
61
return make_message(message_id, parts.as_string(), headers, hidden)
63
64
class ForkedFakeService:
112
113
"""Start the HTTP server."""
113
114
service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
114
115
service.store = MemoryStore(self.message_archives)
115
for archive_id, messages in service.store.message_archives.iteritems():
116
for message in messages:
117
message.setdefault('headers', {})
119
117
if self.write_logs:
120
118
logging.basicConfig(
133
131
self.logger = logging.getLogger('http')
134
132
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
135
"""Create an archive or message on PUT."""
136
scheme, netloc, path, params, query_string, fragments = (
138
parts = path.split('/')
139
if parts[1] != 'archive':
140
# This is an unknonwn operation?
143
# This expected path is /archive/archive_id.
145
self.server.store.put_archive(parts[2])
146
self.send_response(httplib.CREATED)
149
except Exception, error:
151
httplib.BAD_REQUEST, error.__doc__)
153
# This expected path is /archive/archive_id/message_id.
155
message = self.rfile.read(int(self.headers['content-length']))
156
self.server.store.put_message(parts[2], parts[3], message)
157
self.send_response(httplib.CREATED)
161
self.send_error(httplib.BAD_REQUEST)
136
163
def do_POST(self):
137
"""Create a message on POST."""
138
message = self.rfile.read(int(self.headers['content-length']))
164
"""Change a message on POST."""
139
165
scheme, netloc, path, params, query_string, fragments = (
140
166
urlparse(self.path))
141
167
parts = path.split('/')
142
if parts[1] == 'archive' and len(parts) == 4:
168
if parts[1] != 'archive':
169
# This is an unknonwn operation?
172
# This expected path is /archive/archive_id/message_id.
144
174
# 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)
175
response = self.server.store.hide_message(
176
parts[2], parts[3], query_string)
177
self.send_response(httplib.OK)
147
178
self.end_headers()
179
self.wfile.write(simplejson.dumps(response))
150
181
self.send_error(httplib.BAD_REQUEST)
173
204
self.logger.info(message)
207
class TestPutArchive(TestCase):
209
def test_put_archive(self):
210
client = GrackleClient('localhost', 8410)
211
message_archives = {}
212
with ForkedFakeService.from_client(client, message_archives):
213
client.put_archive('arch1')
214
response = client.get_messages('arch1')
215
self.assertEqual(0, len(response['messages']))
217
def test_put_archive_existing_archive(self):
218
client = GrackleClient('localhost', 8411)
219
message_archives = {'arch1': []}
220
with ForkedFakeService.from_client(client, message_archives):
221
with ExpectedException(ArchiveIdExists, ''):
222
client.put_archive('arch1')
176
225
class TestPutMessage(TestCase):
178
227
def test_put_message(self):
238
287
def get_messages_member_order_test(self, key):
239
288
client = GrackleClient('localhost', 8439)
242
make_message('foo', headers={key: '2011-03-25'}),
243
make_message('bar', headers={key: '2011-03-24'}),
295
make_message('foo', headers={header_name: '2011-03-25'}),
296
make_message('bar', headers={header_name: '2011-03-24'}),
245
298
with ForkedFakeService.from_client(client, archive):
246
299
response = client.get_messages('baz')
393
446
first_message = response['messages'][0]
394
447
self.assertEqual('foo', first_message['message_id'])
395
448
self.assertEqual(
396
{'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
397
first_message['headers'])
449
archive['baz'][0]['headers'], first_message['headers'])
398
450
self.assertNotIn('body', first_message)
400
452
def test_display_type_text_only(self):
411
463
self.assertEqual('foo', first_message['message_id'])
412
464
self.assertEqual('me', first_message['headers']['From'])
413
465
self.assertEqual('you', first_message['headers']['To'])
414
self.assertEqual('abcdefghi', first_message['body'])
466
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
416
468
def test_display_type_all(self):
417
469
client = GrackleClient('localhost', 8447)
427
479
self.assertEqual('foo', first_message['message_id'])
428
480
self.assertEqual('me', first_message['headers']['From'])
429
481
self.assertEqual('you', first_message['headers']['To'])
431
'abcdefghi\n\nattactment data.', first_message['body'])
482
self.assertEqual(archive['baz'][0]['body'], first_message['body'])
433
484
def test_date_range(self):
434
485
client = GrackleClient('localhost', 8448)
471
522
with ForkedFakeService.from_client(client, archive):
472
523
with ExpectedException(UnparsableDateRange, ''):
473
524
client.get_messages('baz', date_range='2012-01..12-02..12-03')
527
class TestHideMessages(TestCase):
529
def test_hide_message_true(self):
530
client = GrackleClient('localhost', 8470)
533
make_message('foo', hidden=False),
535
with ForkedFakeService.from_client(client, archive):
536
response = client.hide_message('baz', 'foo', hidden=True)
537
self.assertEqual('foo', response['message_id'])
538
self.assertIs(True, response['hidden'])
540
def test_hide_message_false(self):
541
client = GrackleClient('localhost', 8470)
544
make_message('foo', hidden=True),
546
with ForkedFakeService.from_client(client, archive):
547
response = client.hide_message('baz', 'foo', hidden=False)
548
self.assertEqual('foo', response['message_id'])
549
self.assertIs(False, response['hidden'])