~didrocks/unity/altf10

« back to all changes in this revision

Viewing changes to grackle/tests/test_client.py

  • Committer: Curtis Hovey
  • Date: 2012-03-17 21:01:26 UTC
  • Revision ID: curtis.hovey@canonical.com-20120317210126-tx0p2lg8qr1ch172
Remove old http request handler and fake service.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from BaseHTTPServer import (
2
 
    HTTPServer,
3
 
    BaseHTTPRequestHandler,
4
 
    )
5
1
from email.message import Message
6
2
from email.mime.multipart import MIMEMultipart
7
3
from email.mime.text import MIMEText
8
 
import httplib
9
 
import logging
10
 
import os
11
 
from signal import SIGKILL
12
 
import simplejson
13
4
from StringIO import StringIO
14
 
import sys
15
5
from unittest import TestCase
16
 
from urlparse import urlparse
17
6
 
18
7
from testtools import ExpectedException
19
8
 
27
16
from grackle.service import ForkedFakeService
28
17
from grackle.store import (
29
18
    make_json_message,
30
 
    MemoryStore,
31
19
    )
32
20
 
33
21
 
62
50
    return make_message(message_id, parts.as_string(), headers, hidden)
63
51
 
64
52
 
65
 
class XXXForkedFakeService:
66
 
    """A Grackle service fake, as a ContextManager."""
67
 
 
68
 
    def __init__(self, port, message_archives=None, write_logs=False):
69
 
        """Constructor.
70
 
 
71
 
        :param port: The tcp port to use.
72
 
        :param message_archives: A dict of lists of dicts representing
73
 
            archives of messages. The outer dict represents the archive,
74
 
            the list represents the list of messages for that archive.
75
 
        :param write_logs: If true, log messages will be written to stdout.
76
 
        """
77
 
        self.pid = None
78
 
        self.port = port
79
 
        if message_archives is None:
80
 
            self.message_archives = {}
81
 
        else:
82
 
            self.message_archives = message_archives
83
 
        self.read_end, self.write_end = os.pipe()
84
 
        self.write_logs = write_logs
85
 
 
86
 
    @staticmethod
87
 
    def from_client(client, message_archives=None):
88
 
        """Instantiate a ForkedFakeService from the client.
89
 
 
90
 
        :param port: The client to provide service for.
91
 
        :param message_archives: A dict of lists of dicts representing
92
 
            archives of messages. The outer dict represents the archive,
93
 
            the list represents the list of messages for that archive.
94
 
        """
95
 
        return ForkedFakeService(client.port, message_archives)
96
 
 
97
 
    def is_ready(self):
98
 
        """Tell the parent process that the server is ready for writes."""
99
 
        os.write(self.write_end, 'asdf')
100
 
 
101
 
    def __enter__(self):
102
 
        """Run the service.
103
 
 
104
 
        Fork and start a server in the child.  Return when the server is ready
105
 
        for use."""
106
 
        pid = os.fork()
107
 
        if pid == 0:
108
 
            self.start_server()
109
 
        self.pid = pid
110
 
        os.read(self.read_end, 1)
111
 
        return
112
 
 
113
 
    def start_server(self):
114
 
        """Start the HTTP server."""
115
 
        service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
116
 
        service.store = MemoryStore(self.message_archives)
117
 
        self.is_ready()
118
 
        if self.write_logs:
119
 
            logging.basicConfig(
120
 
                stream=sys.stderr, level=logging.INFO)
121
 
        service.serve_forever()
122
 
 
123
 
    def __exit__(self, exc_type, exc_val, traceback):
124
 
        os.kill(self.pid, SIGKILL)
125
 
 
126
 
 
127
 
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
128
 
    """A request handler that forwards to server.store."""
129
 
 
130
 
    def __init__(self, *args, **kwargs):
131
 
        """Constructor.  Sets up logging."""
132
 
        self.logger = logging.getLogger('http')
133
 
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
134
 
 
135
 
    def do_PUT(self):
136
 
        """Create an archive or message on PUT."""
137
 
        scheme, netloc, path, params, query_string, fragments = (
138
 
            urlparse(self.path))
139
 
        parts = path.split('/')
140
 
        if parts[1] != 'archive':
141
 
            # This is an unknonwn operation?
142
 
            return
143
 
        if len(parts) == 3:
144
 
            # This expected path is /archive/archive_id.
145
 
            try:
146
 
                self.server.store.put_archive(parts[2])
147
 
                self.send_response(httplib.CREATED)
148
 
                self.end_headers()
149
 
                self.wfile.close()
150
 
            except Exception, error:
151
 
                self.send_response(
152
 
                    httplib.BAD_REQUEST, error.__doc__)
153
 
        if len(parts) == 4:
154
 
            # This expected path is /archive/archive_id/message_id.
155
 
            try:
156
 
                message = self.rfile.read(int(self.headers['content-length']))
157
 
                self.server.store.put_message(parts[2], parts[3], message)
158
 
                self.send_response(httplib.CREATED)
159
 
                self.end_headers()
160
 
                self.wfile.close()
161
 
            except:
162
 
                self.send_error(httplib.BAD_REQUEST)
163
 
 
164
 
    def do_POST(self):
165
 
        """Change a message on POST."""
166
 
        scheme, netloc, path, params, query_string, fragments = (
167
 
            urlparse(self.path))
168
 
        parts = path.split('/')
169
 
        if parts[1] != 'archive':
170
 
            # This is an unknonwn operation?
171
 
            return
172
 
        if len(parts) == 4:
173
 
            # This expected path is /archive/archive_id/message_id.
174
 
            try:
175
 
                # This expected path is /archive/archive_id/message_id.
176
 
                response = self.server.store.hide_message(
177
 
                    parts[2], parts[3], query_string)
178
 
                self.send_response(httplib.OK)
179
 
                self.end_headers()
180
 
                self.wfile.write(simplejson.dumps(response))
181
 
            except:
182
 
                self.send_error(httplib.BAD_REQUEST)
183
 
 
184
 
    def do_GET(self):
185
 
        """Retrieve a list of messages on GET."""
186
 
        scheme, netloc, path, params, query_string, fragments = (
187
 
            urlparse(self.path))
188
 
        parts = path.split('/')
189
 
        if parts[1] == 'archive':
190
 
            try:
191
 
                response = self.server.store.get_messages(
192
 
                    parts[2], query_string)
193
 
                self.send_response(httplib.OK)
194
 
                self.end_headers()
195
 
                self.wfile.write(simplejson.dumps(response))
196
 
            except Exception, error:
197
 
                self.send_response(
198
 
                    httplib.BAD_REQUEST, error.__doc__)
199
 
                return
200
 
 
201
 
    def log_message(self, format, *args):
202
 
        """Override log_message to use standard Python logging."""
203
 
        message = "%s - - [%s] %s\n" % (
204
 
            self.address_string(), self.log_date_time_string(), format % args)
205
 
        self.logger.info(message)
206
 
 
207
 
 
208
53
class TestPutArchive(TestCase):
209
54
 
210
55
    def test_put_archive(self):