~didrocks/unity/altf10

« back to all changes in this revision

Viewing changes to grackle/tests/test_client.py

  • Committer: Aaron Bentley
  • Date: 2012-01-11 08:06:03 UTC
  • Revision ID: aaron@canonical.com-20120111080603-fxgo006hthzc89kq
check is PHONY

Show diffs side-by-side

added added

removed removed

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