~didrocks/unity/altf10

4 by Aaron Bentley
Initial test.
1
from BaseHTTPServer import (
2
    HTTPServer,
3
    BaseHTTPRequestHandler,
4
    )
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
5
from email.message import Message
6
from email.mime.multipart import MIMEMultipart
7
from email.mime.text import MIMEText
6 by Aaron Bentley
Use constants.
8
import httplib
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
9
import logging
4 by Aaron Bentley
Initial test.
10
import os
5 by Aaron Bentley
Actual fake service working.
11
from signal import SIGKILL
13 by Aaron Bentley
Retrieve messages.
12
import simplejson
4 by Aaron Bentley
Initial test.
13
from StringIO import StringIO
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
14
import sys
3 by Aaron Bentley
Add test framework.
15
from unittest import TestCase
13 by Aaron Bentley
Retrieve messages.
16
from urlparse import urlparse
3 by Aaron Bentley
Add test framework.
17
5 by Aaron Bentley
Actual fake service working.
18
from testtools import ExpectedException
19
8 by Aaron Bentley
Test message path.
20
from grackle.client import (
21
    GrackleClient,
38 by Curtis Hovey
Added basic handling of date_range.
22
    UnparsableDateRange,
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
23
    UnsupportedDisplayType,
21 by Aaron Bentley
Test unsupported orders.
24
    UnsupportedOrder,
8 by Aaron Bentley
Test message path.
25
    )
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
26
from grackle.store import (
27
    MemoryStore,
28
    )
4 by Aaron Bentley
Initial test.
29
30
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
31
def make_message(message_id, body='body', headers=None, hidden=False):
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
32
    if headers is None:
33
        headers = {}
34
    headers['Message-Id'] = message_id
35
    message = {
36
        'message_id': message_id,
37
        'headers': headers,
38
        'thread_id': message_id,
39
        'date': headers.get('date', '2005-01-01'),
40
        'subject': headers.get('subject', 'subject'),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
41
        'author': headers.get('author', 'author'),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
42
        'hidden': hidden,
43
        'attachments': [],
35.1.19 by Curtis Hovey
Removed the exceptional rule for replies.
44
        'replies': headers.get('in-reply-to', None),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
45
        'body': body,
46
        }
47
    return message
48
49
35.1.16 by Curtis Hovey
make_mime_message calls to make_message.
50
def make_mime_message(message_id, body='body', headers=None, hidden=False,
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
51
                      attachment_type=None):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
52
    message = MIMEMultipart()
35.1.16 by Curtis Hovey
make_mime_message calls to make_message.
53
    message.attach(MIMEText(body))
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
54
    if attachment_type is not None:
55
        attachment = Message()
56
        attachment.set_payload('attactment data.')
57
        attachment['Content-Type'] = attachment_type
35.1.16 by Curtis Hovey
make_mime_message calls to make_message.
58
        attachment['Content-Disposition'] = 'attachment; filename="file.ext"'
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
59
        message.attach(attachment)
35.1.16 by Curtis Hovey
make_mime_message calls to make_message.
60
    return make_message(message_id, message.get_payload(), headers, hidden)
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
61
62
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
63
class ForkedFakeService:
34 by Aaron Bentley
Cleanup
64
    """A Grackle service fake, as a ContextManager."""
28 by Aaron Bentley
Extract GrackleStore.
65
33 by Aaron Bentley
Cleaner logging switch.
66
    def __init__(self, port, messages=None, write_logs=False):
34 by Aaron Bentley
Cleanup
67
        """Constructor.
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
68
69
        :param port: The tcp port to use.
34 by Aaron Bentley
Cleanup
70
        :param messages: A dict of lists of dicts representing messages.  The
71
            outer dict represents the archive, the list represents the list of
72
            messages for that archive.
73
        :param write_logs: If true, log messages will be written to stdout.
74
        """
28 by Aaron Bentley
Extract GrackleStore.
75
        self.pid = None
76
        self.port = port
31 by Aaron Bentley
Switch fake_grackle_service to ForkedFake.from_client.
77
        if messages is None:
78
            self.messages = {}
79
        else:
80
            self.messages = messages
28 by Aaron Bentley
Extract GrackleStore.
81
        self.read_end, self.write_end = os.pipe()
33 by Aaron Bentley
Cleaner logging switch.
82
        self.write_logs = write_logs
28 by Aaron Bentley
Extract GrackleStore.
83
31 by Aaron Bentley
Switch fake_grackle_service to ForkedFake.from_client.
84
    @staticmethod
85
    def from_client(client, messages=None):
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
86
        """Instantiate a ForkedFakeService from the client.
34 by Aaron Bentley
Cleanup
87
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
88
        :param port: The client to provide service for.
34 by Aaron Bentley
Cleanup
89
        :param messages: A dict of lists of dicts representing messages.  The
90
            outer dict represents the archive, the list represents the list of
91
            messages for that archive.
92
        """
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
93
        return ForkedFakeService(client.port, messages)
31 by Aaron Bentley
Switch fake_grackle_service to ForkedFake.from_client.
94
28 by Aaron Bentley
Extract GrackleStore.
95
    def is_ready(self):
34 by Aaron Bentley
Cleanup
96
        """Tell the parent process that the server is ready for writes."""
28 by Aaron Bentley
Extract GrackleStore.
97
        os.write(self.write_end, 'asdf')
98
99
    def __enter__(self):
34 by Aaron Bentley
Cleanup
100
        """Run the service.
101
102
        Fork and start a server in the child.  Return when the server is ready
103
        for use."""
28 by Aaron Bentley
Extract GrackleStore.
104
        pid = os.fork()
105
        if pid == 0:
106
            self.start_server()
107
        self.pid = pid
108
        os.read(self.read_end, 1)
109
        return
110
111
    def start_server(self):
34 by Aaron Bentley
Cleanup
112
        """Start the HTTP server."""
28 by Aaron Bentley
Extract GrackleStore.
113
        service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
114
        service.store = MemoryStore(self.messages)
28 by Aaron Bentley
Extract GrackleStore.
115
        for archive_id, messages in service.store.messages.iteritems():
116
            for message in messages:
117
                message.setdefault('headers', {})
118
        self.is_ready()
33 by Aaron Bentley
Cleaner logging switch.
119
        if self.write_logs:
120
            logging.basicConfig(
121
                stream=sys.stderr, level=logging.INFO)
28 by Aaron Bentley
Extract GrackleStore.
122
        service.serve_forever()
123
124
    def __exit__(self, exc_type, exc_val, traceback):
125
        os.kill(self.pid, SIGKILL)
126
127
128
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
34 by Aaron Bentley
Cleanup
129
    """A request handler that forwards to server.store."""
28 by Aaron Bentley
Extract GrackleStore.
130
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
131
    def __init__(self, *args, **kwargs):
34 by Aaron Bentley
Cleanup
132
        """Constructor.  Sets up logging."""
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
133
        self.logger = logging.getLogger('http')
134
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
135
28 by Aaron Bentley
Extract GrackleStore.
136
    def do_POST(self):
34 by Aaron Bentley
Cleanup
137
        """Create a message on POST."""
28 by Aaron Bentley
Extract GrackleStore.
138
        message = self.rfile.read(int(self.headers['content-length']))
139
        if message == 'This is a message':
140
            self.send_response(httplib.CREATED)
141
            self.end_headers()
142
            self.wfile.close()
143
        else:
144
            self.send_error(httplib.BAD_REQUEST)
145
146
    def do_GET(self):
34 by Aaron Bentley
Cleanup
147
        """Retrieve a list of messages on GET."""
28 by Aaron Bentley
Extract GrackleStore.
148
        scheme, netloc, path, params, query_string, fragments = (
149
            urlparse(self.path))
150
        parts = path.split('/')
151
        if parts[1] == 'archive':
152
            try:
153
                response = self.server.store.get_messages(
154
                    parts[2], query_string)
155
                self.send_response(httplib.OK)
156
                self.end_headers()
157
                self.wfile.write(simplejson.dumps(response))
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
158
            except Exception, error:
159
                self.send_response(
160
                    httplib.BAD_REQUEST, error.__doc__)
28 by Aaron Bentley
Extract GrackleStore.
161
                return
13 by Aaron Bentley
Retrieve messages.
162
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
163
    def log_message(self, format, *args):
34 by Aaron Bentley
Cleanup
164
        """Override log_message to use standard Python logging."""
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
165
        message = "%s - - [%s] %s\n" % (
35.1.1 by Curtis Hovey
Hush lint.
166
            self.address_string(), self.log_date_time_string(), format % args)
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
167
        self.logger.info(message)
168
5 by Aaron Bentley
Actual fake service working.
169
3 by Aaron Bentley
Add test framework.
170
class TestPutMessage(TestCase):
171
172
    def test_put_message(self):
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
173
        client = GrackleClient('localhost', 8420)
35.1.3 by Curtis Hovey
Renamed ForkedFake => ForkedFakeService.
174
        with ForkedFakeService.from_client(client):
7 by Aaron Bentley
Fix URLs etc.
175
            client.put_message('arch1', 'asdf', StringIO('This is a message'))
5 by Aaron Bentley
Actual fake service working.
176
            with ExpectedException(Exception, 'wtf'):
7 by Aaron Bentley
Fix URLs etc.
177
                client.put_message('arch1', 'asdf',
178
                    StringIO('This is not a message'))
11 by Aaron Bentley
Start working on GET.
179
180
181
class TestGetMessages(TestCase):
182
20 by Aaron Bentley
Support order by date
183
    def assertIDOrder(self, ids, messages):
184
        self.assertEqual(ids, [m['message_id'] for m in messages])
185
19 by Aaron Bentley
Implement memo/limit support.
186
    def assertMessageIDs(self, ids, messages):
20 by Aaron Bentley
Support order by date
187
        self.assertIDOrder(
35.1.1 by Curtis Hovey
Hush lint.
188
            sorted(ids), sorted(messages, key=lambda m: m['message_id']))
19 by Aaron Bentley
Implement memo/limit support.
189
11 by Aaron Bentley
Start working on GET.
190
    def test_get_messages(self):
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
191
        client = GrackleClient('localhost', 8430)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
192
        archive = {
193
            'baz': [make_message('foo'), make_message('bar')]}
194
        with ForkedFakeService.from_client(client, archive):
15 by Aaron Bentley
Test filtering by message-id.
195
            response = client.get_messages('baz')
17 by Aaron Bentley
Switch hyphens to underscores.
196
        self.assertEqual(['bar', 'foo'], sorted(m['message_id'] for m in
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
197
            response['messages']))
198
        self.assertIs(None, response['next_memo'])
199
        self.assertIs(None, response['previous_memo'])
15 by Aaron Bentley
Test filtering by message-id.
200
201
    def test_get_messages_by_id(self):
202
        client = GrackleClient('localhost', 8437)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
203
        archive = {
204
            'baz': [make_message('foo'), make_message('bar')]}
205
        with ForkedFakeService.from_client(client, archive):
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
206
            response = client.get_messages('baz', message_ids=['foo'])
207
        message, = response['messages']
17 by Aaron Bentley
Switch hyphens to underscores.
208
        self.assertEqual('foo', message['message_id'])
19 by Aaron Bentley
Implement memo/limit support.
209
210
    def test_get_messages_batching(self):
20 by Aaron Bentley
Support order by date
211
        client = GrackleClient('localhost', 8438)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
212
        archive = {'baz': [make_message('foo'), make_message('bar')]}
213
        with ForkedFakeService.from_client(client, archive):
19 by Aaron Bentley
Implement memo/limit support.
214
            response = client.get_messages('baz', limit=1)
215
            self.assertEqual(1, len(response['messages']))
216
            messages = response['messages']
217
            response = client.get_messages(
218
                'baz', limit=1, memo=response['next_memo'])
219
            self.assertEqual(1, len(response['messages']))
220
            messages.extend(response['messages'])
221
            self.assertMessageIDs(['foo', 'bar'], messages)
20 by Aaron Bentley
Support order by date
222
22 by Aaron Bentley
Order by thread subject.
223
    def get_messages_member_order_test(self, key):
20 by Aaron Bentley
Support order by date
224
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
225
        archive = {
226
            'baz': [
227
                make_message('foo', headers={key: '2011-03-25'}),
228
                make_message('bar', headers={key: '2011-03-24'}),
229
             ]}
230
        with ForkedFakeService.from_client(client, archive):
20 by Aaron Bentley
Support order by date
231
            response = client.get_messages('baz')
232
            self.assertIDOrder(['foo', 'bar'], response['messages'])
22 by Aaron Bentley
Order by thread subject.
233
            response = client.get_messages('baz', order=key)
20 by Aaron Bentley
Support order by date
234
            self.assertIDOrder(['bar', 'foo'], response['messages'])
21 by Aaron Bentley
Test unsupported orders.
235
22 by Aaron Bentley
Order by thread subject.
236
    def test_get_messages_date_order(self):
237
        self.get_messages_member_order_test('date')
238
239
    def test_get_messages_author_order(self):
240
        self.get_messages_member_order_test('author')
241
242
    def test_get_messages_subject_order(self):
243
        self.get_messages_member_order_test('subject')
244
245
    def test_get_messages_thread_subject_order(self):
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
246
        archive = {
247
            'baz': [
248
                make_message('bar', headers={'subject': 'y'}),
249
                make_message('qux', headers={'subject': 'z'}),
250
                make_message('foo', headers={'subject': 'x',
251
                                             'in-reply-to': 'qux'}),
252
             ]}
22 by Aaron Bentley
Order by thread subject.
253
        client = GrackleClient('localhost', 8439)
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
254
        with ForkedFakeService.from_client(client, archive):
22 by Aaron Bentley
Order by thread subject.
255
            response = client.get_messages('baz')
256
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
257
            response = client.get_messages('baz', order='subject')
258
            self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
259
            response = client.get_messages('baz', order='thread_subject')
260
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
261
23 by Aaron Bentley
Support thread_oldest order.
262
    def test_get_messages_thread_oldest_order(self):
263
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
264
        archive = {
265
            'baz': [
266
                make_message('bar', headers={'date': 'x'}),
267
                make_message('qux', headers={'date': 'z'}),
268
                make_message('foo', headers={'date': 'y',
269
                                             'in-reply-to': 'qux'}),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
270
            ]}
271
        with ForkedFakeService.from_client(client, archive):
23 by Aaron Bentley
Support thread_oldest order.
272
            response = client.get_messages('baz')
273
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
274
            response = client.get_messages('baz', order='date')
275
            self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
276
            response = client.get_messages('baz', order='thread_oldest')
277
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
278
24 by Aaron Bentley
Support thread_newest threading.
279
    def test_get_messages_thread_newest_order(self):
280
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
281
        archive = {
282
            'baz': [
283
                make_message('bar', headers={'date': 'x'}),
284
                make_message('qux', headers={'date': 'w'}),
285
                make_message('foo', headers={'date': 'y',
286
                                             'in-reply-to': 'bar'}),
287
                make_message('baz', headers={'date': 'z',
288
                                             'in-reply-to': 'qux'}),
289
            ]}
290
        with ForkedFakeService.from_client(client, archive):
24 by Aaron Bentley
Support thread_newest threading.
291
            response = client.get_messages('baz', order='date')
292
            self.assertIDOrder(
293
                ['qux', 'bar', 'foo', 'baz'], response['messages'])
294
            response = client.get_messages('baz', order='thread_newest')
295
            self.assertIDOrder(
296
                ['bar', 'foo', 'qux', 'baz'], response['messages'])
297
21 by Aaron Bentley
Test unsupported orders.
298
    def test_get_messages_unsupported_order(self):
299
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
300
        archive = {
301
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
302
                make_message('foo', headers={'date': '2011-03-25'}),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
303
                make_message('foo', headers={'date': '2011-03-24'}),
304
            ]}
305
        with ForkedFakeService.from_client(client, archive):
35 by William Grant
Fix test.
306
            with ExpectedException(UnsupportedOrder, ''):
21 by Aaron Bentley
Test unsupported orders.
307
                client.get_messages('baz', order='nonsense')
27 by Aaron Bentley
get_messages supports header parameter.
308
309
    def test_get_messages_headers_no_headers(self):
310
        client = GrackleClient('localhost', 8440)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
311
        archive = {'baz': [make_message('foo')]}
312
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
313
            response = client.get_messages('baz', headers=[
314
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
315
        first_message = response['messages'][0]
316
        self.assertEqual('foo', first_message['message_id'])
317
        self.assertEqual({}, first_message['headers'])
318
319
    def test_get_messages_headers_exclude_headers(self):
29 by Aaron Bentley
implement include_hidden.
320
        client = GrackleClient('localhost', 8441)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
321
        archive = {
322
            'baz': [make_message('foo', headers={'From': 'me'})]}
323
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
324
            response = client.get_messages('baz', headers=[
325
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
326
        first_message = response['messages'][0]
327
        self.assertEqual('foo', first_message['message_id'])
328
        self.assertEqual({}, first_message['headers'])
329
330
    def test_get_messages_headers_include_headers(self):
29 by Aaron Bentley
implement include_hidden.
331
        client = GrackleClient('localhost', 8442)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
332
        archive = {
333
            'baz': [
334
                make_message('foo', headers={'From': 'me', 'To': 'you'})]}
335
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
336
            response = client.get_messages('baz', headers=[
337
                'From', 'To'])
338
        first_message = response['messages'][0]
339
        self.assertEqual('foo', first_message['message_id'])
340
        self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
28 by Aaron Bentley
Extract GrackleStore.
341
342
    def test_get_messages_max_body_length(self):
29 by Aaron Bentley
implement include_hidden.
343
        client = GrackleClient('localhost', 8443)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
344
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
345
        with ForkedFakeService.from_client(client, archive):
28 by Aaron Bentley
Extract GrackleStore.
346
            response = client.get_messages('baz', max_body_length=3)
347
        first_message = response['messages'][0]
348
        self.assertEqual('abc', first_message['body'])
349
29 by Aaron Bentley
implement include_hidden.
350
    def test_include_hidden(self):
351
        client = GrackleClient('localhost', 8444)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
352
        archive = {
353
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
354
                make_message('foo', hidden=True),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
355
                make_message('bar', hidden=False),
356
            ]}
357
        with ForkedFakeService.from_client(client, archive):
29 by Aaron Bentley
implement include_hidden.
358
            response = client.get_messages('baz', include_hidden=True)
359
            self.assertMessageIDs(['bar', 'foo'], response['messages'])
360
            response = client.get_messages('baz', include_hidden=False)
361
            self.assertMessageIDs(['bar'], response['messages'])
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
362
363
    def test_display_type_unknown_value(self):
35.1.5 by Curtis Hovey
Moved the display_type arg.
364
        client = GrackleClient('localhost', 8445)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
365
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
366
        with ForkedFakeService.from_client(client, archive):
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
367
            with ExpectedException(UnsupportedDisplayType, ''):
368
                client.get_messages('baz', display_type='unknown')
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
369
370
    def test_display_type_headers_only(self):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
371
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
372
        archive = {
373
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
374
                make_message('foo', body=u'abcdefghi',
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
375
                             headers={'From': 'me', 'To': 'you'})]}
376
        with ForkedFakeService.from_client(client, archive):
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
377
            response = client.get_messages('baz', display_type='headers-only')
378
        first_message = response['messages'][0]
379
        self.assertEqual('foo', first_message['message_id'])
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
380
        self.assertEqual(
381
            {'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
382
            first_message['headers'])
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
383
        self.assertNotIn('body', first_message)
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
384
385
    def test_display_type_text_only(self):
386
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
387
        archive = {
388
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
389
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
390
                    'foo', 'abcdefghi',
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
391
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
392
                    attachment_type='text/x-diff')]}
393
        with ForkedFakeService.from_client(client, archive):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
394
            response = client.get_messages('baz', display_type='text-only')
395
        first_message = response['messages'][0]
396
        self.assertEqual('foo', first_message['message_id'])
397
        self.assertEqual('me', first_message['headers']['From'])
398
        self.assertEqual('you', first_message['headers']['To'])
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
399
        self.assertEqual('abcdefghi', first_message['body'])
400
401
    def test_display_type_all(self):
402
        client = GrackleClient('localhost', 8447)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
403
        archive = {
404
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
405
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
406
                    'foo', 'abcdefghi',
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
407
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
408
                    attachment_type='text/x-diff')]}
409
        with ForkedFakeService.from_client(client, archive):
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
410
            response = client.get_messages('baz', display_type='all')
411
        first_message = response['messages'][0]
412
        self.assertEqual('foo', first_message['message_id'])
413
        self.assertEqual('me', first_message['headers']['From'])
414
        self.assertEqual('you', first_message['headers']['To'])
415
        self.assertEqual(
416
            'abcdefghi\n\nattactment data.', first_message['body'])
38 by Curtis Hovey
Added basic handling of date_range.
417
418
    def test_date_range(self):
419
        client = GrackleClient('localhost', 8448)
420
        archive = {
421
            'baz': [
422
                make_mime_message(
423
                    'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
424
                make_mime_message(
425
                    'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
426
                make_mime_message(
427
                    'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
428
                make_mime_message(
429
                    'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
430
                make_mime_message(
431
                    'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
432
                    ]}
433
        with ForkedFakeService.from_client(client, archive):
434
            response = client.get_messages(
435
                'baz', date_range='2012-01-01..2012-01-31')
436
        ids = sorted(m['message_id'] for m in response['messages'])
437
        self.assertEqual(['bar', 'naf', 'qux'], ids)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
438
439
    def test_date_range_unparsabledaterange(self):
41 by Curtis Hovey
Added test for extra data argument.
440
        client = GrackleClient('localhost', 8449)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
441
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
442
        with ForkedFakeService.from_client(client, archive):
443
            with ExpectedException(UnparsableDateRange, ''):
444
                client.get_messages('baz', date_range='2012-01-01')
40 by Curtis Hovey
Dates must be a value.
445
446
    def test_date_range_unparsabledaterange_missing_part(self):
41 by Curtis Hovey
Added test for extra data argument.
447
        client = GrackleClient('localhost', 8450)
40 by Curtis Hovey
Dates must be a value.
448
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
449
        with ForkedFakeService.from_client(client, archive):
450
            with ExpectedException(UnparsableDateRange, ''):
451
                client.get_messages('baz', date_range='2012-01-01..')
41 by Curtis Hovey
Added test for extra data argument.
452
453
    def test_date_range_unparsabledaterange_extra_part(self):
454
        client = GrackleClient('localhost', 8451)
455
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
456
        with ForkedFakeService.from_client(client, archive):
457
            with ExpectedException(UnparsableDateRange, ''):
458
                client.get_messages('baz', date_range='2012-01..12-02..12-03')