~didrocks/unity/altf10

« back to all changes in this revision

Viewing changes to grackle/tests/test_client.py

  • Committer: Curtis Hovey
  • Date: 2012-03-16 16:12:13 UTC
  • Revision ID: curtis.hovey@canonical.com-20120316161213-htrw58db1ojtl8d9
Always use an rfc822 message in tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
    UnsupportedOrder,
25
25
    )
26
26
from grackle.store import (
 
27
    make_json_message,
27
28
    MemoryStore,
28
29
    )
29
30
 
31
32
def make_message(message_id, body='body', headers=None, hidden=False):
32
33
    if headers is None:
33
34
        headers = {}
34
 
    headers['Message-Id'] = message_id
35
 
    message = {
36
 
        'message_id': message_id,
37
 
        'headers': headers,
38
 
        'thread_id': message_id,
39
 
        'date': headers.get('date', '2005-01-01'),
40
 
        'subject': headers.get('subject', 'subject'),
41
 
        'author': headers.get('author', 'author'),
42
 
        'hidden': hidden,
43
 
        'attachments': [],
44
 
        'replies': headers.get('in-reply-to', None),
45
 
        'body': body,
 
35
    message_headers = {
 
36
        'Message-Id': message_id,
 
37
        'date': '2005-01-01',
 
38
        'subject': 'subject',
 
39
        'from': 'author',
 
40
        'replies': '',
46
41
        }
47
 
    return message
 
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)
48
48
 
49
49
 
50
50
def make_mime_message(message_id, body='body', headers=None, hidden=False,
51
51
                      attachment_type=None):
52
 
    message = MIMEMultipart()
53
 
    message.attach(MIMEText(body))
 
52
    parts = MIMEMultipart()
 
53
    parts.attach(MIMEText(body))
54
54
    if attachment_type is not None:
55
55
        attachment = Message()
56
56
        attachment.set_payload('attactment data.')
57
57
        attachment['Content-Type'] = attachment_type
58
58
        attachment['Content-Disposition'] = 'attachment; filename="file.ext"'
59
 
        message.attach(attachment)
60
 
    return make_message(message_id, message.get_payload(), headers, hidden)
 
59
        parts.attach(attachment)
 
60
    return make_message(message_id, parts.as_string(), headers, hidden)
61
61
 
62
62
 
63
63
class ForkedFakeService:
64
64
    """A Grackle service fake, as a ContextManager."""
65
65
 
66
 
    def __init__(self, port, messages=None, write_logs=False):
 
66
    def __init__(self, port, message_archives=None, write_logs=False):
67
67
        """Constructor.
68
68
 
69
69
        :param port: The tcp port to use.
70
 
        :param messages: A dict of lists of dicts representing messages.  The
71
 
            outer dict represents the archive, the list represents the list of
72
 
            messages for that archive.
 
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.
73
73
        :param write_logs: If true, log messages will be written to stdout.
74
74
        """
75
75
        self.pid = None
76
76
        self.port = port
77
 
        if messages is None:
78
 
            self.messages = {}
 
77
        if message_archives is None:
 
78
            self.message_archives = {}
79
79
        else:
80
 
            self.messages = messages
 
80
            self.message_archives = message_archives
81
81
        self.read_end, self.write_end = os.pipe()
82
82
        self.write_logs = write_logs
83
83
 
84
84
    @staticmethod
85
 
    def from_client(client, messages=None):
 
85
    def from_client(client, message_archives=None):
86
86
        """Instantiate a ForkedFakeService from the client.
87
87
 
88
88
        :param port: The client to provide service for.
89
 
        :param messages: A dict of lists of dicts representing messages.  The
90
 
            outer dict represents the archive, the list represents the list of
91
 
            messages for that archive.
 
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.
92
92
        """
93
 
        return ForkedFakeService(client.port, messages)
 
93
        return ForkedFakeService(client.port, message_archives)
94
94
 
95
95
    def is_ready(self):
96
96
        """Tell the parent process that the server is ready for writes."""
111
111
    def start_server(self):
112
112
        """Start the HTTP server."""
113
113
        service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
114
 
        service.store = MemoryStore(self.messages)
115
 
        for archive_id, messages in service.store.messages.iteritems():
 
114
        service.store = MemoryStore(self.message_archives)
 
115
        for archive_id, messages in service.store.message_archives.iteritems():
116
116
            for message in messages:
117
117
                message.setdefault('headers', {})
118
118
        self.is_ready()
136
136
    def do_POST(self):
137
137
        """Create a message on POST."""
138
138
        message = self.rfile.read(int(self.headers['content-length']))
139
 
        if message == 'This is a message':
140
 
            self.send_response(httplib.CREATED)
141
 
            self.end_headers()
142
 
            self.wfile.close()
143
 
        else:
144
 
            self.send_error(httplib.BAD_REQUEST)
 
139
        scheme, netloc, path, params, query_string, fragments = (
 
140
            urlparse(self.path))
 
141
        parts = path.split('/')
 
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)
145
151
 
146
152
    def do_GET(self):
147
153
        """Retrieve a list of messages on GET."""
171
177
 
172
178
    def test_put_message(self):
173
179
        client = GrackleClient('localhost', 8420)
174
 
        with ForkedFakeService.from_client(client):
175
 
            client.put_message('arch1', 'asdf', StringIO('This is a message'))
 
180
        message_archives = {'arch1': []}
 
181
        with ForkedFakeService.from_client(client, message_archives):
 
182
            client.put_message('arch1', 'id1', StringIO('This is a message'))
 
183
            response = client.get_messages('arch1')
 
184
        self.assertEqual(1, len(response['messages']))
 
185
        message = response['messages'][0]
 
186
        self.assertEqual('id1', message['message_id'])
 
187
 
 
188
    def test_put_message_without_archive(self):
 
189
        client = GrackleClient('localhost', 8421)
 
190
        message_archives = {'arch1': []}
 
191
        with ForkedFakeService.from_client(client, message_archives):
176
192
            with ExpectedException(Exception, 'wtf'):
177
 
                client.put_message('arch1', 'asdf',
178
 
                    StringIO('This is not a message'))
 
193
                client.put_message('no-archive', 'id1', StringIO('message'))
179
194
 
180
195
 
181
196
class TestGetMessages(TestCase):
222
237
 
223
238
    def get_messages_member_order_test(self, key):
224
239
        client = GrackleClient('localhost', 8439)
 
240
        if key == 'author':
 
241
            header_name = 'from'
 
242
        else:
 
243
            header_name = key
225
244
        archive = {
226
245
            'baz': [
227
 
                make_message('foo', headers={key: '2011-03-25'}),
228
 
                make_message('bar', headers={key: '2011-03-24'}),
 
246
                make_message('foo', headers={header_name: '2011-03-25'}),
 
247
                make_message('bar', headers={header_name: '2011-03-24'}),
229
248
             ]}
230
249
        with ForkedFakeService.from_client(client, archive):
231
250
            response = client.get_messages('baz')
378
397
        first_message = response['messages'][0]
379
398
        self.assertEqual('foo', first_message['message_id'])
380
399
        self.assertEqual(
381
 
            {'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
382
 
            first_message['headers'])
 
400
            archive['baz'][0]['headers'], first_message['headers'])
383
401
        self.assertNotIn('body', first_message)
384
402
 
385
403
    def test_display_type_text_only(self):
396
414
        self.assertEqual('foo', first_message['message_id'])
397
415
        self.assertEqual('me', first_message['headers']['From'])
398
416
        self.assertEqual('you', first_message['headers']['To'])
399
 
        self.assertEqual('abcdefghi', first_message['body'])
 
417
        self.assertEqual(archive['baz'][0]['body'], first_message['body'])
400
418
 
401
419
    def test_display_type_all(self):
402
420
        client = GrackleClient('localhost', 8447)
412
430
        self.assertEqual('foo', first_message['message_id'])
413
431
        self.assertEqual('me', first_message['headers']['From'])
414
432
        self.assertEqual('you', first_message['headers']['To'])
415
 
        self.assertEqual(
416
 
            'abcdefghi\n\nattactment data.', first_message['body'])
 
433
        self.assertEqual(archive['baz'][0]['body'], first_message['body'])
417
434
 
418
435
    def test_date_range(self):
419
436
        client = GrackleClient('localhost', 8448)