~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 = {}
51 by Curtis Hovey
Always use an rfc822 message in tests.
35
    message_headers = {
36
        'Message-Id': message_id,
37
        'date': '2005-01-01',
38
        'subject': 'subject',
39
        'from': 'author',
40
        'replies': '',
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
41
        }
51 by Curtis Hovey
Always use an rfc822 message in tests.
42
    message_headers.update(headers.items())
43
    message = Message()
44
    message.set_payload(body)
45
    for key, value in message_headers.items():
46
        message[key] = value
47
    return make_json_message(message_id, message.as_string(), hidden)
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
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):
49 by Curtis Hovey
Make an rfc822 message with a mime payload.
52
    parts = MIMEMultipart()
53
    parts.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"'
49 by Curtis Hovey
Make an rfc822 message with a mime payload.
59
        parts.attach(attachment)
51 by Curtis Hovey
Always use an rfc822 message in tests.
60
    return make_message(message_id, parts.as_string(), 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)
51 by Curtis Hovey
Always use an rfc822 message in tests.
240
        if key == 'author':
241
            header_name = 'from'
242
        else:
243
            header_name = key
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
244
        archive = {
245
            'baz': [
51 by Curtis Hovey
Always use an rfc822 message in tests.
246
                make_message('foo', headers={header_name: '2011-03-25'}),
247
                make_message('bar', headers={header_name: '2011-03-24'}),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
248
             ]}
249
        with ForkedFakeService.from_client(client, archive):
20 by Aaron Bentley
Support order by date
250
            response = client.get_messages('baz')
251
            self.assertIDOrder(['foo', 'bar'], response['messages'])
22 by Aaron Bentley
Order by thread subject.
252
            response = client.get_messages('baz', order=key)
20 by Aaron Bentley
Support order by date
253
            self.assertIDOrder(['bar', 'foo'], response['messages'])
21 by Aaron Bentley
Test unsupported orders.
254
22 by Aaron Bentley
Order by thread subject.
255
    def test_get_messages_date_order(self):
256
        self.get_messages_member_order_test('date')
257
258
    def test_get_messages_author_order(self):
259
        self.get_messages_member_order_test('author')
260
261
    def test_get_messages_subject_order(self):
262
        self.get_messages_member_order_test('subject')
263
264
    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.
265
        archive = {
266
            'baz': [
267
                make_message('bar', headers={'subject': 'y'}),
268
                make_message('qux', headers={'subject': 'z'}),
269
                make_message('foo', headers={'subject': 'x',
270
                                             'in-reply-to': 'qux'}),
271
             ]}
22 by Aaron Bentley
Order by thread subject.
272
        client = GrackleClient('localhost', 8439)
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
273
        with ForkedFakeService.from_client(client, archive):
22 by Aaron Bentley
Order by thread subject.
274
            response = client.get_messages('baz')
275
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
276
            response = client.get_messages('baz', order='subject')
277
            self.assertIDOrder(['foo', 'bar', 'qux'], response['messages'])
278
            response = client.get_messages('baz', order='thread_subject')
279
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
280
23 by Aaron Bentley
Support thread_oldest order.
281
    def test_get_messages_thread_oldest_order(self):
282
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
283
        archive = {
284
            'baz': [
285
                make_message('bar', headers={'date': 'x'}),
286
                make_message('qux', headers={'date': 'z'}),
287
                make_message('foo', headers={'date': 'y',
288
                                             'in-reply-to': 'qux'}),
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
289
            ]}
290
        with ForkedFakeService.from_client(client, archive):
23 by Aaron Bentley
Support thread_oldest order.
291
            response = client.get_messages('baz')
292
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
293
            response = client.get_messages('baz', order='date')
294
            self.assertIDOrder(['bar', 'foo', 'qux'], response['messages'])
295
            response = client.get_messages('baz', order='thread_oldest')
296
            self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
297
24 by Aaron Bentley
Support thread_newest threading.
298
    def test_get_messages_thread_newest_order(self):
299
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
300
        archive = {
301
            'baz': [
302
                make_message('bar', headers={'date': 'x'}),
303
                make_message('qux', headers={'date': 'w'}),
304
                make_message('foo', headers={'date': 'y',
305
                                             'in-reply-to': 'bar'}),
306
                make_message('baz', headers={'date': 'z',
307
                                             'in-reply-to': 'qux'}),
308
            ]}
309
        with ForkedFakeService.from_client(client, archive):
24 by Aaron Bentley
Support thread_newest threading.
310
            response = client.get_messages('baz', order='date')
311
            self.assertIDOrder(
312
                ['qux', 'bar', 'foo', 'baz'], response['messages'])
313
            response = client.get_messages('baz', order='thread_newest')
314
            self.assertIDOrder(
315
                ['bar', 'foo', 'qux', 'baz'], response['messages'])
316
21 by Aaron Bentley
Test unsupported orders.
317
    def test_get_messages_unsupported_order(self):
318
        client = GrackleClient('localhost', 8439)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
319
        archive = {
320
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
321
                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.
322
                make_message('foo', headers={'date': '2011-03-24'}),
323
            ]}
324
        with ForkedFakeService.from_client(client, archive):
35 by William Grant
Fix test.
325
            with ExpectedException(UnsupportedOrder, ''):
21 by Aaron Bentley
Test unsupported orders.
326
                client.get_messages('baz', order='nonsense')
27 by Aaron Bentley
get_messages supports header parameter.
327
328
    def test_get_messages_headers_no_headers(self):
329
        client = GrackleClient('localhost', 8440)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
330
        archive = {'baz': [make_message('foo')]}
331
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
332
            response = client.get_messages('baz', headers=[
333
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
334
        first_message = response['messages'][0]
335
        self.assertEqual('foo', first_message['message_id'])
336
        self.assertEqual({}, first_message['headers'])
337
338
    def test_get_messages_headers_exclude_headers(self):
29 by Aaron Bentley
implement include_hidden.
339
        client = GrackleClient('localhost', 8441)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
340
        archive = {
341
            'baz': [make_message('foo', headers={'From': 'me'})]}
342
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
343
            response = client.get_messages('baz', headers=[
344
                'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
345
        first_message = response['messages'][0]
346
        self.assertEqual('foo', first_message['message_id'])
347
        self.assertEqual({}, first_message['headers'])
348
349
    def test_get_messages_headers_include_headers(self):
29 by Aaron Bentley
implement include_hidden.
350
        client = GrackleClient('localhost', 8442)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
351
        archive = {
352
            'baz': [
353
                make_message('foo', headers={'From': 'me', 'To': 'you'})]}
354
        with ForkedFakeService.from_client(client, archive):
27 by Aaron Bentley
get_messages supports header parameter.
355
            response = client.get_messages('baz', headers=[
356
                'From', 'To'])
357
        first_message = response['messages'][0]
358
        self.assertEqual('foo', first_message['message_id'])
359
        self.assertEqual({'From': 'me', 'To': 'you'}, first_message['headers'])
28 by Aaron Bentley
Extract GrackleStore.
360
361
    def test_get_messages_max_body_length(self):
29 by Aaron Bentley
implement include_hidden.
362
        client = GrackleClient('localhost', 8443)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
363
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
364
        with ForkedFakeService.from_client(client, archive):
28 by Aaron Bentley
Extract GrackleStore.
365
            response = client.get_messages('baz', max_body_length=3)
366
        first_message = response['messages'][0]
367
        self.assertEqual('abc', first_message['body'])
368
29 by Aaron Bentley
implement include_hidden.
369
    def test_include_hidden(self):
370
        client = GrackleClient('localhost', 8444)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
371
        archive = {
372
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
373
                make_message('foo', hidden=True),
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
374
                make_message('bar', hidden=False),
375
            ]}
376
        with ForkedFakeService.from_client(client, archive):
29 by Aaron Bentley
implement include_hidden.
377
            response = client.get_messages('baz', include_hidden=True)
378
            self.assertMessageIDs(['bar', 'foo'], response['messages'])
379
            response = client.get_messages('baz', include_hidden=False)
380
            self.assertMessageIDs(['bar'], response['messages'])
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
381
382
    def test_display_type_unknown_value(self):
35.1.5 by Curtis Hovey
Moved the display_type arg.
383
        client = GrackleClient('localhost', 8445)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
384
        archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
385
        with ForkedFakeService.from_client(client, archive):
35.1.4 by Curtis Hovey
Added SUPPORTED_DISPLAY_TYPES.
386
            with ExpectedException(UnsupportedDisplayType, ''):
387
                client.get_messages('baz', display_type='unknown')
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
388
389
    def test_display_type_headers_only(self):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
390
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
391
        archive = {
392
            'baz': [
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
393
                make_message('foo', body=u'abcdefghi',
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
394
                             headers={'From': 'me', 'To': 'you'})]}
395
        with ForkedFakeService.from_client(client, archive):
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
396
            response = client.get_messages('baz', display_type='headers-only')
397
        first_message = response['messages'][0]
398
        self.assertEqual('foo', first_message['message_id'])
35.1.13 by Curtis Hovey
Use make_message() to make test data consistent.
399
        self.assertEqual(
51 by Curtis Hovey
Always use an rfc822 message in tests.
400
            archive['baz'][0]['headers'], first_message['headers'])
35.1.6 by Curtis Hovey
Added display_type == 'headers-only' support.
401
        self.assertNotIn('body', first_message)
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
402
403
    def test_display_type_text_only(self):
404
        client = GrackleClient('localhost', 8446)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
405
        archive = {
406
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
407
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
408
                    'foo', 'abcdefghi',
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
409
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
410
                    attachment_type='text/x-diff')]}
411
        with ForkedFakeService.from_client(client, archive):
35.1.9 by Curtis Hovey
Added support for display_type == 'text-only'.
412
            response = client.get_messages('baz', display_type='text-only')
413
        first_message = response['messages'][0]
414
        self.assertEqual('foo', first_message['message_id'])
415
        self.assertEqual('me', first_message['headers']['From'])
416
        self.assertEqual('you', first_message['headers']['To'])
48 by Curtis Hovey
Use a real rfc822 message for mime testing.
417
        self.assertEqual(archive['baz'][0]['body'], first_message['body'])
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
418
419
    def test_display_type_all(self):
420
        client = GrackleClient('localhost', 8447)
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
421
        archive = {
422
            'baz': [
35.1.12 by Curtis Hovey
Renamed make_message => make_mime_message.
423
                make_mime_message(
35.1.11 by Curtis Hovey
Reanme make_json_message => make_message.
424
                    'foo', 'abcdefghi',
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
425
                    headers={'From': 'me', 'To': 'you'},
35.1.14 by Curtis Hovey
Create the archive outside of the call to create the server.
426
                    attachment_type='text/x-diff')]}
427
        with ForkedFakeService.from_client(client, archive):
35.1.10 by Curtis Hovey
Added support for display_type == 'all'.
428
            response = client.get_messages('baz', display_type='all')
429
        first_message = response['messages'][0]
430
        self.assertEqual('foo', first_message['message_id'])
431
        self.assertEqual('me', first_message['headers']['From'])
432
        self.assertEqual('you', first_message['headers']['To'])
48 by Curtis Hovey
Use a real rfc822 message for mime testing.
433
        self.assertEqual(archive['baz'][0]['body'], 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')