~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
45 by Curtis Hovey
Rename variable for clarity.
66
    def __init__(self, port, message_archives=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.
45 by Curtis Hovey
Rename variable for clarity.
70
        :param message_archives: A dict of lists of dicts representing
71
            archives of messages. The outer dict represents the archive,
72
            the list represents the list of messages for that archive.
34 by Aaron Bentley
Cleanup
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
45 by Curtis Hovey
Rename variable for clarity.
77
        if message_archives is None:
78
            self.message_archives = {}
31 by Aaron Bentley
Switch fake_grackle_service to ForkedFake.from_client.
79
        else:
45 by Curtis Hovey
Rename variable for clarity.
80
            self.message_archives = message_archives
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
45 by Curtis Hovey
Rename variable for clarity.
85
    def from_client(client, message_archives=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.
45 by Curtis Hovey
Rename variable for clarity.
89
        :param message_archives: A dict of lists of dicts representing
90
            archives of messages. The outer dict represents the archive,
91
            the list represents the list of messages for that archive.
34 by Aaron Bentley
Cleanup
92
        """
45 by Curtis Hovey
Rename variable for clarity.
93
        return ForkedFakeService(client.port, message_archives)
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)
45 by Curtis Hovey
Rename variable for clarity.
114
        service.store = MemoryStore(self.message_archives)
115
        for archive_id, messages in service.store.message_archives.iteritems():
28 by Aaron Bentley
Extract GrackleStore.
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']))
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
139
        scheme, netloc, path, params, query_string, fragments = (
140
            urlparse(self.path))
141
        parts = path.split('/')
142
        if parts[1] == 'archive':
143
            # This expected path is /archive/archive_id/message_id.
144
            self.server.store.put_message(parts[2], parts[3], message)
28 by Aaron Bentley
Extract GrackleStore.
145
        if message == 'This is a message':
146
            self.send_response(httplib.CREATED)
147
            self.end_headers()
148
            self.wfile.close()
149
        else:
150
            self.send_error(httplib.BAD_REQUEST)
151
152
    def do_GET(self):
34 by Aaron Bentley
Cleanup
153
        """Retrieve a list of messages on GET."""
28 by Aaron Bentley
Extract GrackleStore.
154
        scheme, netloc, path, params, query_string, fragments = (
155
            urlparse(self.path))
156
        parts = path.split('/')
157
        if parts[1] == 'archive':
158
            try:
159
                response = self.server.store.get_messages(
160
                    parts[2], query_string)
161
                self.send_response(httplib.OK)
162
                self.end_headers()
163
                self.wfile.write(simplejson.dumps(response))
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
164
            except Exception, error:
165
                self.send_response(
166
                    httplib.BAD_REQUEST, error.__doc__)
28 by Aaron Bentley
Extract GrackleStore.
167
                return
13 by Aaron Bentley
Retrieve messages.
168
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
169
    def log_message(self, format, *args):
34 by Aaron Bentley
Cleanup
170
        """Override log_message to use standard Python logging."""
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
171
        message = "%s - - [%s] %s\n" % (
35.1.1 by Curtis Hovey
Hush lint.
172
            self.address_string(), self.log_date_time_string(), format % args)
32 by Aaron Bentley
Switch test HTTP server to standard Python logging.
173
        self.logger.info(message)
174
5 by Aaron Bentley
Actual fake service working.
175
3 by Aaron Bentley
Add test framework.
176
class TestPutMessage(TestCase):
177
178
    def test_put_message(self):
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
179
        client = GrackleClient('localhost', 8420)
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
180
        message_archives = {'arch1': []}
181
        service = ForkedFakeService.from_client(client, message_archives)
182
        with service:
183
            client.put_message('arch1', 'id1', StringIO('This is a message'))
184
            response = client.get_messages('arch1')
185
            self.assertEqual(1, len(response['messages']))
186
            message = response['messages'][0]
187
            self.assertEqual('id1', message['message_id'])
188
189
    def test_put_message_without_message(self):
190
        client = GrackleClient('localhost', 8421)
191
        message_archives = {'arch1': []}
192
        with ForkedFakeService.from_client(client, message_archives):
5 by Aaron Bentley
Actual fake service working.
193
            with ExpectedException(Exception, 'wtf'):
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
194
                client.put_message('arch1', 'id1',
7 by Aaron Bentley
Fix URLs etc.
195
                    StringIO('This is not a message'))
11 by Aaron Bentley
Start working on GET.
196
197
198
class TestGetMessages(TestCase):
199
20 by Aaron Bentley
Support order by date
200
    def assertIDOrder(self, ids, messages):
201
        self.assertEqual(ids, [m['message_id'] for m in messages])
202
19 by Aaron Bentley
Implement memo/limit support.
203
    def assertMessageIDs(self, ids, messages):
20 by Aaron Bentley
Support order by date
204
        self.assertIDOrder(
35.1.1 by Curtis Hovey
Hush lint.
205
            sorted(ids), sorted(messages, key=lambda m: m['message_id']))
19 by Aaron Bentley
Implement memo/limit support.
206
11 by Aaron Bentley
Start working on GET.
207
    def test_get_messages(self):
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
208
        client = GrackleClient('localhost', 8430)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
209
        archive = {
210
            'baz': [make_message('foo'), make_message('bar')]}
211
        with ForkedFakeService.from_client(client, archive):
15 by Aaron Bentley
Test filtering by message-id.
212
            response = client.get_messages('baz')
17 by Aaron Bentley
Switch hyphens to underscores.
213
        self.assertEqual(['bar', 'foo'], sorted(m['message_id'] for m in
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
214
            response['messages']))
215
        self.assertIs(None, response['next_memo'])
216
        self.assertIs(None, response['previous_memo'])
15 by Aaron Bentley
Test filtering by message-id.
217
218
    def test_get_messages_by_id(self):
219
        client = GrackleClient('localhost', 8437)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
220
        archive = {
221
            'baz': [make_message('foo'), make_message('bar')]}
222
        with ForkedFakeService.from_client(client, archive):
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
223
            response = client.get_messages('baz', message_ids=['foo'])
224
        message, = response['messages']
17 by Aaron Bentley
Switch hyphens to underscores.
225
        self.assertEqual('foo', message['message_id'])
19 by Aaron Bentley
Implement memo/limit support.
226
227
    def test_get_messages_batching(self):
20 by Aaron Bentley
Support order by date
228
        client = GrackleClient('localhost', 8438)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
229
        archive = {'baz': [make_message('foo'), make_message('bar')]}
230
        with ForkedFakeService.from_client(client, archive):
19 by Aaron Bentley
Implement memo/limit support.
231
            response = client.get_messages('baz', limit=1)
232
            self.assertEqual(1, len(response['messages']))
233
            messages = response['messages']
234
            response = client.get_messages(
235
                'baz', limit=1, memo=response['next_memo'])
236
            self.assertEqual(1, len(response['messages']))
237
            messages.extend(response['messages'])
238
            self.assertMessageIDs(['foo', 'bar'], messages)
20 by Aaron Bentley
Support order by date
239
22 by Aaron Bentley
Order by thread subject.
240
    def get_messages_member_order_test(self, key):
20 by Aaron Bentley
Support order by date
241
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
242
        archive = {
243
            'baz': [
244
                make_message('foo', headers={key: '2011-03-25'}),
245
                make_message('bar', headers={key: '2011-03-24'}),
246
             ]}
247
        with ForkedFakeService.from_client(client, archive):
20 by Aaron Bentley
Support order by date
248
            response = client.get_messages('baz')
249
            self.assertIDOrder(['foo', 'bar'], response['messages'])
22 by Aaron Bentley
Order by thread subject.
250
            response = client.get_messages('baz', order=key)
20 by Aaron Bentley
Support order by date
251
            self.assertIDOrder(['bar', 'foo'], response['messages'])
21 by Aaron Bentley
Test unsupported orders.
252
22 by Aaron Bentley
Order by thread subject.
253
    def test_get_messages_date_order(self):
254
        self.get_messages_member_order_test('date')
255
256
    def test_get_messages_author_order(self):
257
        self.get_messages_member_order_test('author')
258
259
    def test_get_messages_subject_order(self):
260
        self.get_messages_member_order_test('subject')
261
262
    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.
263
        archive = {
264
            'baz': [
265
                make_message('bar', headers={'subject': 'y'}),
266
                make_message('qux', headers={'subject': 'z'}),
267
                make_message('foo', headers={'subject': 'x',
268
                                             'in-reply-to': 'qux'}),
269
             ]}
22 by Aaron Bentley
Order by thread subject.
270
        client = GrackleClient('localhost', 8439)
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
271
        with ForkedFakeService.from_client(client, archive):
22 by Aaron Bentley
Order by thread subject.
272
            response = client.get_messages('baz')
273
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
274
            response = client.get_messages('baz', order='subject')
275
            self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
276
            response = client.get_messages('baz', order='thread_subject')
277
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
278
23 by Aaron Bentley
Support thread_oldest order.
279
    def test_get_messages_thread_oldest_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': 'z'}),
285
                make_message('foo', headers={'date': 'y',
286
                                             'in-reply-to': 'qux'}),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
287
            ]}
288
        with ForkedFakeService.from_client(client, archive):
23 by Aaron Bentley
Support thread_oldest order.
289
            response = client.get_messages('baz')
290
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
291
            response = client.get_messages('baz', order='date')
292
            self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
293
            response = client.get_messages('baz', order='thread_oldest')
294
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
295
24 by Aaron Bentley
Support thread_newest threading.
296
    def test_get_messages_thread_newest_order(self):
297
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
298
        archive = {
299
            'baz': [
300
                make_message('bar', headers={'date': 'x'}),
301
                make_message('qux', headers={'date': 'w'}),
302
                make_message('foo', headers={'date': 'y',
303
                                             'in-reply-to': 'bar'}),
304
                make_message('baz', headers={'date': 'z',
305
                                             'in-reply-to': 'qux'}),
306
            ]}
307
        with ForkedFakeService.from_client(client, archive):
24 by Aaron Bentley
Support thread_newest threading.
308
            response = client.get_messages('baz', order='date')
309
            self.assertIDOrder(
310
                ['qux', 'bar', 'foo', 'baz'], response['messages'])
311
            response = client.get_messages('baz', order='thread_newest')
312
            self.assertIDOrder(
313
                ['bar', 'foo', 'qux', 'baz'], response['messages'])
314
21 by Aaron Bentley
Test unsupported orders.
315
    def test_get_messages_unsupported_order(self):
316
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
317
        archive = {
318
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
319
                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.
320
                make_message('foo', headers={'date': '2011-03-24'}),
321
            ]}
322
        with ForkedFakeService.from_client(client, archive):
35 by William Grant
Fix test.
323
            with ExpectedException(UnsupportedOrder, ''):
21 by Aaron Bentley
Test unsupported orders.
324
                client.get_messages('baz', order='nonsense')
27 by Aaron Bentley
get_messages supports header parameter.
325
326
    def test_get_messages_headers_no_headers(self):
327
        client = GrackleClient('localhost', 8440)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
328
        archive = {'baz': [make_message('foo')]}
329
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
330
            response = client.get_messages('baz', headers=[
331
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
332
        first_message = response['messages'][0]
333
        self.assertEqual('foo', first_message['message_id'])
334
        self.assertEqual({}, first_message['headers'])
335
336
    def test_get_messages_headers_exclude_headers(self):
29 by Aaron Bentley
implement include_hidden.
337
        client = GrackleClient('localhost', 8441)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
338
        archive = {
339
            'baz': [make_message('foo', headers={'From': 'me'})]}
340
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
341
            response = client.get_messages('baz', headers=[
342
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
343
        first_message = response['messages'][0]
344
        self.assertEqual('foo', first_message['message_id'])
345
        self.assertEqual({}, first_message['headers'])
346
347
    def test_get_messages_headers_include_headers(self):
29 by Aaron Bentley
implement include_hidden.
348
        client = GrackleClient('localhost', 8442)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
349
        archive = {
350
            'baz': [
351
                make_message('foo', headers={'From': 'me', 'To': 'you'})]}
352
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
353
            response = client.get_messages('baz', headers=[
354
                'From', 'To'])
355
        first_message = response['messages'][0]
356
        self.assertEqual('foo', first_message['message_id'])
357
        self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
28 by Aaron Bentley
Extract GrackleStore.
358
359
    def test_get_messages_max_body_length(self):
29 by Aaron Bentley
implement include_hidden.
360
        client = GrackleClient('localhost', 8443)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
361
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
362
        with ForkedFakeService.from_client(client, archive):
28 by Aaron Bentley
Extract GrackleStore.
363
            response = client.get_messages('baz', max_body_length=3)
364
        first_message = response['messages'][0]
365
        self.assertEqual('abc', first_message['body'])
366
29 by Aaron Bentley
implement include_hidden.
367
    def test_include_hidden(self):
368
        client = GrackleClient('localhost', 8444)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
369
        archive = {
370
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
371
                make_message('foo', hidden=True),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
372
                make_message('bar', hidden=False),
373
            ]}
374
        with ForkedFakeService.from_client(client, archive):
29 by Aaron Bentley
implement include_hidden.
375
            response = client.get_messages('baz', include_hidden=True)
376
            self.assertMessageIDs(['bar', 'foo'], response['messages'])
377
            response = client.get_messages('baz', include_hidden=False)
378
            self.assertMessageIDs(['bar'], response['messages'])
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
379
380
    def test_display_type_unknown_value(self):
35.1.5 by Curtis Hovey
Moved the display_type arg.
381
        client = GrackleClient('localhost', 8445)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
382
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
383
        with ForkedFakeService.from_client(client, archive):
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
384
            with ExpectedException(UnsupportedDisplayType, ''):
385
                client.get_messages('baz', display_type='unknown')
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
386
387
    def test_display_type_headers_only(self):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
388
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
389
        archive = {
390
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
391
                make_message('foo', body=u'abcdefghi',
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
392
                             headers={'From': 'me', 'To': 'you'})]}
393
        with ForkedFakeService.from_client(client, archive):
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
394
            response = client.get_messages('baz', display_type='headers-only')
395
        first_message = response['messages'][0]
396
        self.assertEqual('foo', first_message['message_id'])
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
397
        self.assertEqual(
398
            {'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
399
            first_message['headers'])
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
400
        self.assertNotIn('body', first_message)
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
401
402
    def test_display_type_text_only(self):
403
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
404
        archive = {
405
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
406
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
407
                    'foo', 'abcdefghi',
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
408
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
409
                    attachment_type='text/x-diff')]}
410
        with ForkedFakeService.from_client(client, archive):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
411
            response = client.get_messages('baz', display_type='text-only')
412
        first_message = response['messages'][0]
413
        self.assertEqual('foo', first_message['message_id'])
414
        self.assertEqual('me', first_message['headers']['From'])
415
        self.assertEqual('you', first_message['headers']['To'])
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
416
        self.assertEqual('abcdefghi', first_message['body'])
417
418
    def test_display_type_all(self):
419
        client = GrackleClient('localhost', 8447)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
420
        archive = {
421
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
422
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
423
                    'foo', 'abcdefghi',
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
424
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
425
                    attachment_type='text/x-diff')]}
426
        with ForkedFakeService.from_client(client, archive):
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
427
            response = client.get_messages('baz', display_type='all')
428
        first_message = response['messages'][0]
429
        self.assertEqual('foo', first_message['message_id'])
430
        self.assertEqual('me', first_message['headers']['From'])
431
        self.assertEqual('you', first_message['headers']['To'])
432
        self.assertEqual(
433
            'abcdefghi\n\nattactment data.', first_message['body'])
38 by Curtis Hovey
Added basic handling of date_range.
434
435
    def test_date_range(self):
436
        client = GrackleClient('localhost', 8448)
437
        archive = {
438
            'baz': [
439
                make_mime_message(
440
                    'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
441
                make_mime_message(
442
                    'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
443
                make_mime_message(
444
                    'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
445
                make_mime_message(
446
                    'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
447
                make_mime_message(
448
                    'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
449
                    ]}
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)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
455
456
    def test_date_range_unparsabledaterange(self):
41 by Curtis Hovey
Added test for extra data argument.
457
        client = GrackleClient('localhost', 8449)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
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')
40 by Curtis Hovey
Dates must be a value.
462
463
    def test_date_range_unparsabledaterange_missing_part(self):
41 by Curtis Hovey
Added test for extra data argument.
464
        client = GrackleClient('localhost', 8450)
40 by Curtis Hovey
Dates must be a value.
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..')
41 by Curtis Hovey
Added test for extra data argument.
469
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')