~unity-2d-team/unity-2d/Shell-MultiMonitor

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