~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('/')
47 by Curtis Hovey
Raise ArchiveIdNotFound if the client puts a message into an unknown archive.
142
        if parts[1] == 'archive' and len(parts) == 4:
143
            try:
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)
147
                self.end_headers()
148
                self.wfile.close()
149
            except:
150
                self.send_error(httplib.BAD_REQUEST)
28 by Aaron Bentley
Extract GrackleStore.
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': []}
47 by Curtis Hovey
Raise ArchiveIdNotFound if the client puts a message into an unknown archive.
181
        with ForkedFakeService.from_client(client, message_archives):
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
182
            client.put_message('arch1', 'id1', StringIO('This is a message'))
183
            response = client.get_messages('arch1')
47 by Curtis Hovey
Raise ArchiveIdNotFound if the client puts a message into an unknown archive.
184
        self.assertEqual(1, len(response['messages']))
185
        message = response['messages'][0]
186
        self.assertEqual('id1', message['message_id'])
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
187
47 by Curtis Hovey
Raise ArchiveIdNotFound if the client puts a message into an unknown archive.
188
    def test_put_message_without_archive(self):
46 by Curtis Hovey
Implemented a partial put into the MemoryStore.
189
        client = GrackleClient('localhost', 8421)
190
        message_archives = {'arch1': []}
191
        with ForkedFakeService.from_client(client, message_archives):
5 by Aaron Bentley
Actual fake service working.
192
            with ExpectedException(Exception, 'wtf'):
47 by Curtis Hovey
Raise ArchiveIdNotFound if the client puts a message into an unknown archive.
193
                client.put_message('no-archive', 'id1', StringIO('message'))
11 by Aaron Bentley
Start working on GET.
194
195
196
class TestGetMessages(TestCase):
197
20 by Aaron Bentley
Support order by date
198
    def assertIDOrder(self, ids, messages):
199
        self.assertEqual(ids, [m['message_id'] for m in messages])
200
19 by Aaron Bentley
Implement memo/limit support.
201
    def assertMessageIDs(self, ids, messages):
20 by Aaron Bentley
Support order by date
202
        self.assertIDOrder(
35.1.1 by Curtis Hovey
Hush lint.
203
            sorted(ids), sorted(messages, key=lambda m: m['message_id']))
19 by Aaron Bentley
Implement memo/limit support.
204
11 by Aaron Bentley
Start working on GET.
205
    def test_get_messages(self):
42 by Curtis Hovey
Separate gracle MemoryStore to its own module.
206
        client = GrackleClient('localhost', 8430)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
207
        archive = {
208
            'baz': [make_message('foo'), make_message('bar')]}
209
        with ForkedFakeService.from_client(client, archive):
15 by Aaron Bentley
Test filtering by message-id.
210
            response = client.get_messages('baz')
17 by Aaron Bentley
Switch hyphens to underscores.
211
        self.assertEqual(['bar', 'foo'], sorted(m['message_id'] for m in
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
212
            response['messages']))
213
        self.assertIs(None, response['next_memo'])
214
        self.assertIs(None, response['previous_memo'])
15 by Aaron Bentley
Test filtering by message-id.
215
216
    def test_get_messages_by_id(self):
217
        client = GrackleClient('localhost', 8437)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
218
        archive = {
219
            'baz': [make_message('foo'), make_message('bar')]}
220
        with ForkedFakeService.from_client(client, archive):
16 by Aaron Bentley
Include next_memo, previous_memo in get_messages response.
221
            response = client.get_messages('baz', message_ids=['foo'])
222
        message, = response['messages']
17 by Aaron Bentley
Switch hyphens to underscores.
223
        self.assertEqual('foo', message['message_id'])
19 by Aaron Bentley
Implement memo/limit support.
224
225
    def test_get_messages_batching(self):
20 by Aaron Bentley
Support order by date
226
        client = GrackleClient('localhost', 8438)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
227
        archive = {'baz': [make_message('foo'), make_message('bar')]}
228
        with ForkedFakeService.from_client(client, archive):
19 by Aaron Bentley
Implement memo/limit support.
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)
20 by Aaron Bentley
Support order by date
237
22 by Aaron Bentley
Order by thread subject.
238
    def get_messages_member_order_test(self, key):
20 by Aaron Bentley
Support order by date
239
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
240
        archive = {
241
            'baz': [
242
                make_message('foo', headers={key: '2011-03-25'}),
243
                make_message('bar', headers={key: '2011-03-24'}),
244
             ]}
245
        with ForkedFakeService.from_client(client, archive):
20 by Aaron Bentley
Support order by date
246
            response = client.get_messages('baz')
247
            self.assertIDOrder(['foo', 'bar'], response['messages'])
22 by Aaron Bentley
Order by thread subject.
248
            response = client.get_messages('baz', order=key)
20 by Aaron Bentley
Support order by date
249
            self.assertIDOrder(['bar', 'foo'], response['messages'])
21 by Aaron Bentley
Test unsupported orders.
250
22 by Aaron Bentley
Order by thread subject.
251
    def test_get_messages_date_order(self):
252
        self.get_messages_member_order_test('date')
253
254
    def test_get_messages_author_order(self):
255
        self.get_messages_member_order_test('author')
256
257
    def test_get_messages_subject_order(self):
258
        self.get_messages_member_order_test('subject')
259
260
    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.
261
        archive = {
262
            'baz': [
263
                make_message('bar', headers={'subject': 'y'}),
264
                make_message('qux', headers={'subject': 'z'}),
265
                make_message('foo', headers={'subject': 'x',
266
                                             'in-reply-to': 'qux'}),
267
             ]}
22 by Aaron Bentley
Order by thread subject.
268
        client = GrackleClient('localhost', 8439)
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
269
        with ForkedFakeService.from_client(client, archive):
22 by Aaron Bentley
Order by thread subject.
270
            response = client.get_messages('baz')
271
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
272
            response = client.get_messages('baz', order='subject')
273
            self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
274
            response = client.get_messages('baz', order='thread_subject')
275
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
276
23 by Aaron Bentley
Support thread_oldest order.
277
    def test_get_messages_thread_oldest_order(self):
278
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
279
        archive = {
280
            'baz': [
281
                make_message('bar', headers={'date': 'x'}),
282
                make_message('qux', headers={'date': 'z'}),
283
                make_message('foo', headers={'date': 'y',
284
                                             'in-reply-to': 'qux'}),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
285
            ]}
286
        with ForkedFakeService.from_client(client, archive):
23 by Aaron Bentley
Support thread_oldest order.
287
            response = client.get_messages('baz')
288
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
289
            response = client.get_messages('baz', order='date')
290
            self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
291
            response = client.get_messages('baz', order='thread_oldest')
292
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
293
24 by Aaron Bentley
Support thread_newest threading.
294
    def test_get_messages_thread_newest_order(self):
295
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
296
        archive = {
297
            'baz': [
298
                make_message('bar', headers={'date': 'x'}),
299
                make_message('qux', headers={'date': 'w'}),
300
                make_message('foo', headers={'date': 'y',
301
                                             'in-reply-to': 'bar'}),
302
                make_message('baz', headers={'date': 'z',
303
                                             'in-reply-to': 'qux'}),
304
            ]}
305
        with ForkedFakeService.from_client(client, archive):
24 by Aaron Bentley
Support thread_newest threading.
306
            response = client.get_messages('baz', order='date')
307
            self.assertIDOrder(
308
                ['qux', 'bar', 'foo', 'baz'], response['messages'])
309
            response = client.get_messages('baz', order='thread_newest')
310
            self.assertIDOrder(
311
                ['bar', 'foo', 'qux', 'baz'], response['messages'])
312
21 by Aaron Bentley
Test unsupported orders.
313
    def test_get_messages_unsupported_order(self):
314
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
315
        archive = {
316
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
317
                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.
318
                make_message('foo', headers={'date': '2011-03-24'}),
319
            ]}
320
        with ForkedFakeService.from_client(client, archive):
35 by William Grant
Fix test.
321
            with ExpectedException(UnsupportedOrder, ''):
21 by Aaron Bentley
Test unsupported orders.
322
                client.get_messages('baz', order='nonsense')
27 by Aaron Bentley
get_messages supports header parameter.
323
324
    def test_get_messages_headers_no_headers(self):
325
        client = GrackleClient('localhost', 8440)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
326
        archive = {'baz': [make_message('foo')]}
327
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
328
            response = client.get_messages('baz', headers=[
329
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
330
        first_message = response['messages'][0]
331
        self.assertEqual('foo', first_message['message_id'])
332
        self.assertEqual({}, first_message['headers'])
333
334
    def test_get_messages_headers_exclude_headers(self):
29 by Aaron Bentley
implement include_hidden.
335
        client = GrackleClient('localhost', 8441)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
336
        archive = {
337
            'baz': [make_message('foo', headers={'From': 'me'})]}
338
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
339
            response = client.get_messages('baz', headers=[
340
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
341
        first_message = response['messages'][0]
342
        self.assertEqual('foo', first_message['message_id'])
343
        self.assertEqual({}, first_message['headers'])
344
345
    def test_get_messages_headers_include_headers(self):
29 by Aaron Bentley
implement include_hidden.
346
        client = GrackleClient('localhost', 8442)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
347
        archive = {
348
            'baz': [
349
                make_message('foo', headers={'From': 'me', 'To': 'you'})]}
350
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
351
            response = client.get_messages('baz', headers=[
352
                'From', 'To'])
353
        first_message = response['messages'][0]
354
        self.assertEqual('foo', first_message['message_id'])
355
        self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
28 by Aaron Bentley
Extract GrackleStore.
356
357
    def test_get_messages_max_body_length(self):
29 by Aaron Bentley
implement include_hidden.
358
        client = GrackleClient('localhost', 8443)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
359
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
360
        with ForkedFakeService.from_client(client, archive):
28 by Aaron Bentley
Extract GrackleStore.
361
            response = client.get_messages('baz', max_body_length=3)
362
        first_message = response['messages'][0]
363
        self.assertEqual('abc', first_message['body'])
364
29 by Aaron Bentley
implement include_hidden.
365
    def test_include_hidden(self):
366
        client = GrackleClient('localhost', 8444)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
367
        archive = {
368
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
369
                make_message('foo', hidden=True),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
370
                make_message('bar', hidden=False),
371
            ]}
372
        with ForkedFakeService.from_client(client, archive):
29 by Aaron Bentley
implement include_hidden.
373
            response = client.get_messages('baz', include_hidden=True)
374
            self.assertMessageIDs(['bar', 'foo'], response['messages'])
375
            response = client.get_messages('baz', include_hidden=False)
376
            self.assertMessageIDs(['bar'], response['messages'])
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
377
378
    def test_display_type_unknown_value(self):
35.1.5 by Curtis Hovey
Moved the display_type arg.
379
        client = GrackleClient('localhost', 8445)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
380
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
381
        with ForkedFakeService.from_client(client, archive):
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
382
            with ExpectedException(UnsupportedDisplayType, ''):
383
                client.get_messages('baz', display_type='unknown')
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
384
385
    def test_display_type_headers_only(self):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
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.13 by Curtis Hovey
Use make_message() to make test data consistent.
389
                make_message('foo', body=u'abcdefghi',
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
390
                             headers={'From': 'me', 'To': 'you'})]}
391
        with ForkedFakeService.from_client(client, archive):
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
392
            response = client.get_messages('baz', display_type='headers-only')
393
        first_message = response['messages'][0]
394
        self.assertEqual('foo', first_message['message_id'])
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
395
        self.assertEqual(
396
            {'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
397
            first_message['headers'])
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
398
        self.assertNotIn('body', first_message)
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
399
400
    def test_display_type_text_only(self):
401
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
402
        archive = {
403
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
404
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
405
                    'foo', 'abcdefghi',
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
406
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
407
                    attachment_type='text/x-diff')]}
408
        with ForkedFakeService.from_client(client, archive):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
409
            response = client.get_messages('baz', display_type='text-only')
410
        first_message = response['messages'][0]
411
        self.assertEqual('foo', first_message['message_id'])
412
        self.assertEqual('me', first_message['headers']['From'])
413
        self.assertEqual('you', first_message['headers']['To'])
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
414
        self.assertEqual('abcdefghi', first_message['body'])
415
416
    def test_display_type_all(self):
417
        client = GrackleClient('localhost', 8447)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
418
        archive = {
419
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
420
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
421
                    'foo', 'abcdefghi',
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
422
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
423
                    attachment_type='text/x-diff')]}
424
        with ForkedFakeService.from_client(client, archive):
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
425
            response = client.get_messages('baz', display_type='all')
426
        first_message = response['messages'][0]
427
        self.assertEqual('foo', first_message['message_id'])
428
        self.assertEqual('me', first_message['headers']['From'])
429
        self.assertEqual('you', first_message['headers']['To'])
430
        self.assertEqual(
431
            'abcdefghi\n\nattactment data.', first_message['body'])
38 by Curtis Hovey
Added basic handling of date_range.
432
433
    def test_date_range(self):
434
        client = GrackleClient('localhost', 8448)
435
        archive = {
436
            'baz': [
437
                make_mime_message(
438
                    'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
439
                make_mime_message(
440
                    'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
441
                make_mime_message(
442
                    'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
443
                make_mime_message(
444
                    'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
445
                make_mime_message(
446
                    'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
447
                    ]}
448
        with ForkedFakeService.from_client(client, archive):
449
            response = client.get_messages(
450
                'baz', date_range='2012-01-01..2012-01-31')
451
        ids = sorted(m['message_id'] for m in response['messages'])
452
        self.assertEqual(['bar', 'naf', 'qux'], ids)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
453
454
    def test_date_range_unparsabledaterange(self):
41 by Curtis Hovey
Added test for extra data argument.
455
        client = GrackleClient('localhost', 8449)
39 by Curtis Hovey
Raise UnparsableDateRange when the date cannot be parsed.
456
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
457
        with ForkedFakeService.from_client(client, archive):
458
            with ExpectedException(UnparsableDateRange, ''):
459
                client.get_messages('baz', date_range='2012-01-01')
40 by Curtis Hovey
Dates must be a value.
460
461
    def test_date_range_unparsabledaterange_missing_part(self):
41 by Curtis Hovey
Added test for extra data argument.
462
        client = GrackleClient('localhost', 8450)
40 by Curtis Hovey
Dates must be a value.
463
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
464
        with ForkedFakeService.from_client(client, archive):
465
            with ExpectedException(UnparsableDateRange, ''):
466
                client.get_messages('baz', date_range='2012-01-01..')
41 by Curtis Hovey
Added test for extra data argument.
467
468
    def test_date_range_unparsabledaterange_extra_part(self):
469
        client = GrackleClient('localhost', 8451)
470
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
471
        with ForkedFakeService.from_client(client, archive):
472
            with ExpectedException(UnparsableDateRange, ''):
473
                client.get_messages('baz', date_range='2012-01..12-02..12-03')