~didrocks/unity/altf10

« back to all changes in this revision

Viewing changes to grackle/tests/test_client.py

  • Committer: Curtis Hovey
  • Date: 2012-01-30 18:30:54 UTC
  • mto: This revision was merged to the branch mainline in revision 36.
  • Revision ID: curtis.hovey@canonical.com-20120130183054-lyjgaxcekr8efuou
Hush lint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
 
39
39
class GrackleStore:
 
40
    """A memory-backed message store."""
40
41
 
41
42
    def __init__(self, messages):
 
43
        """Constructor."""
42
44
        self.messages = messages
43
45
 
44
46
    def get_messages(self, archive_id, query_string):
 
47
        """Return matching messages.
 
48
 
 
49
        :param archive_id: The archive to retrieve from.
 
50
        :param query_string: Contains 'parameters', which is a JSON-format
 
51
            string describing parameters.
 
52
        """
45
53
        query = parse_qs(query_string)
46
54
        parameters = simplejson.loads(query['parameters'][0])
47
55
        order = parameters.get('order')
48
56
        messages = self.messages[archive_id]
49
 
        if order is not None :
 
57
        if order is not None:
50
58
            if order not in SUPPORTED_ORDERS:
51
59
                raise UnsupportedOrder
52
60
            elif order.startswith('thread_'):
64
72
                messages.sort(key=lambda m: m[order])
65
73
        new_messages = []
66
74
        for message in messages:
67
 
            if (
68
 
                not parameters['include_hidden']
 
75
            if (not parameters['include_hidden']
69
76
                and message.get('hidden', False)):
70
77
                continue
71
78
 
72
 
            if ('message_ids' in parameters and
73
 
                message['message_id'] not in parameters['message_ids']):
 
79
            if ('message_ids' in parameters
 
80
                and message['message_id'] not in parameters['message_ids']):
74
81
                continue
75
82
            message = dict(message)
76
83
            if 'headers' in parameters:
110
117
        return response
111
118
 
112
119
 
113
 
 
114
120
class ForkedFake:
 
121
    """A Grackle service fake, as a ContextManager."""
115
122
 
116
 
    def __init__(self, port, messages=None):
 
123
    def __init__(self, port, messages=None, write_logs=False):
 
124
        """Constructor.
 
125
        :param port: The tcp port to use
 
126
        :param messages: A dict of lists of dicts representing messages.  The
 
127
            outer dict represents the archive, the list represents the list of
 
128
            messages for that archive.
 
129
        :param write_logs: If true, log messages will be written to stdout.
 
130
        """
117
131
        self.pid = None
118
132
        self.port = port
119
133
        if messages is None:
121
135
        else:
122
136
            self.messages = messages
123
137
        self.read_end, self.write_end = os.pipe()
 
138
        self.write_logs = write_logs
124
139
 
125
140
    @staticmethod
126
141
    def from_client(client, messages=None):
 
142
        """Instantiate a ForkedFake from the client.
 
143
 
 
144
        :param port: The client  to provide service for.
 
145
        :param messages: A dict of lists of dicts representing messages.  The
 
146
            outer dict represents the archive, the list represents the list of
 
147
            messages for that archive.
 
148
        """
127
149
        return ForkedFake(client.port, messages)
128
150
 
129
151
    def is_ready(self):
 
152
        """Tell the parent process that the server is ready for writes."""
130
153
        os.write(self.write_end, 'asdf')
131
154
 
132
155
    def __enter__(self):
 
156
        """Run the service.
 
157
 
 
158
        Fork and start a server in the child.  Return when the server is ready
 
159
        for use."""
133
160
        pid = os.fork()
134
161
        if pid == 0:
135
162
            self.start_server()
138
165
        return
139
166
 
140
167
    def start_server(self):
 
168
        """Start the HTTP server."""
141
169
        service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
142
170
        service.store = GrackleStore(self.messages)
143
171
        for archive_id, messages in service.store.messages.iteritems():
144
172
            for message in messages:
145
173
                message.setdefault('headers', {})
146
174
        self.is_ready()
147
 
#        logging.basicConfig(
148
 
#            stream=sys.stderr, level=logging.INFO)
 
175
        if self.write_logs:
 
176
            logging.basicConfig(
 
177
                stream=sys.stderr, level=logging.INFO)
149
178
        service.serve_forever()
150
179
 
151
180
    def __exit__(self, exc_type, exc_val, traceback):
158
187
 
159
188
 
160
189
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
 
190
    """A request handler that forwards to server.store."""
161
191
 
162
192
    def __init__(self, *args, **kwargs):
 
193
        """Constructor.  Sets up logging."""
163
194
        self.logger = logging.getLogger('http')
164
195
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
165
196
 
166
197
    def do_POST(self):
 
198
        """Create a message on POST."""
167
199
        message = self.rfile.read(int(self.headers['content-length']))
168
200
        if message == 'This is a message':
169
201
            self.send_response(httplib.CREATED)
173
205
            self.send_error(httplib.BAD_REQUEST)
174
206
 
175
207
    def do_GET(self):
 
208
        """Retrieve a list of messages on GET."""
176
209
        scheme, netloc, path, params, query_string, fragments = (
177
210
            urlparse(self.path))
178
211
        parts = path.split('/')
189
222
                return
190
223
 
191
224
    def log_message(self, format, *args):
 
225
        """Override log_message to use standard Python logging."""
192
226
        message = "%s - - [%s] %s\n" % (
193
 
            self.address_string(), self.log_date_time_string(), format%args)
 
227
            self.address_string(), self.log_date_time_string(), format % args)
194
228
        self.logger.info(message)
195
229
 
196
230
 
212
246
 
213
247
    def assertMessageIDs(self, ids, messages):
214
248
        self.assertIDOrder(
215
 
            sorted(ids), sorted(messages, key=lambda m:m['message_id']))
 
249
            sorted(ids), sorted(messages, key=lambda m: m['message_id']))
216
250
 
217
251
    def test_get_messages(self):
218
252
        client = GrackleClient('localhost', 8435)
318
352
        with ForkedFake.from_client(client,
319
353
                {'baz': [{'message_id': 'foo', 'date': '2011-03-25'},
320
354
                 {'message_id': 'bar', 'date': '2011-03-24'}]}):
321
 
            with ExpectedException(UnsupportedOrder):
 
355
            with ExpectedException(UnsupportedOrder, ''):
322
356
                client.get_messages('baz', order='nonsense')
323
357
 
324
358
    def test_get_messages_headers_no_headers(self):
378
412
            self.assertMessageIDs(['bar', 'foo'], response['messages'])
379
413
            response = client.get_messages('baz', include_hidden=False)
380
414
            self.assertMessageIDs(['bar'], response['messages'])
381