62
50
return make_message(message_id, parts.as_string(), headers, hidden)
65
class XXXForkedFakeService:
66
"""A Grackle service fake, as a ContextManager."""
68
def __init__(self, port, message_archives=None, write_logs=False):
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.
79
if message_archives is None:
80
self.message_archives = {}
82
self.message_archives = message_archives
83
self.read_end, self.write_end = os.pipe()
84
self.write_logs = write_logs
87
def from_client(client, message_archives=None):
88
"""Instantiate a ForkedFakeService from the client.
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.
95
return ForkedFakeService(client.port, message_archives)
98
"""Tell the parent process that the server is ready for writes."""
99
os.write(self.write_end, 'asdf')
104
Fork and start a server in the child. Return when the server is ready
110
os.read(self.read_end, 1)
113
def start_server(self):
114
"""Start the HTTP server."""
115
service = HTTPServer(('', self.port), FakeGrackleRequestHandler)
116
service.store = MemoryStore(self.message_archives)
120
stream=sys.stderr, level=logging.INFO)
121
service.serve_forever()
123
def __exit__(self, exc_type, exc_val, traceback):
124
os.kill(self.pid, SIGKILL)
127
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
128
"""A request handler that forwards to server.store."""
130
def __init__(self, *args, **kwargs):
131
"""Constructor. Sets up logging."""
132
self.logger = logging.getLogger('http')
133
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
136
"""Create an archive or message on PUT."""
137
scheme, netloc, path, params, query_string, fragments = (
139
parts = path.split('/')
140
if parts[1] != 'archive':
141
# This is an unknonwn operation?
144
# This expected path is /archive/archive_id.
146
self.server.store.put_archive(parts[2])
147
self.send_response(httplib.CREATED)
150
except Exception, error:
152
httplib.BAD_REQUEST, error.__doc__)
154
# This expected path is /archive/archive_id/message_id.
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)
162
self.send_error(httplib.BAD_REQUEST)
165
"""Change a message on POST."""
166
scheme, netloc, path, params, query_string, fragments = (
168
parts = path.split('/')
169
if parts[1] != 'archive':
170
# This is an unknonwn operation?
173
# This expected path is /archive/archive_id/message_id.
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)
180
self.wfile.write(simplejson.dumps(response))
182
self.send_error(httplib.BAD_REQUEST)
185
"""Retrieve a list of messages on GET."""
186
scheme, netloc, path, params, query_string, fragments = (
188
parts = path.split('/')
189
if parts[1] == 'archive':
191
response = self.server.store.get_messages(
192
parts[2], query_string)
193
self.send_response(httplib.OK)
195
self.wfile.write(simplejson.dumps(response))
196
except Exception, error:
198
httplib.BAD_REQUEST, error.__doc__)
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)
208
53
class TestPutArchive(TestCase):
210
55
def test_put_archive(self):