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