60
50
return make_message(message_id, parts.as_string(), headers, hidden)
63
class ForkedFakeService:
64
"""A Grackle service fake, as a ContextManager."""
66
def __init__(self, port, message_archives=None, write_logs=False):
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.
77
if message_archives is None:
78
self.message_archives = {}
80
self.message_archives = message_archives
81
self.read_end, self.write_end = os.pipe()
82
self.write_logs = write_logs
85
def from_client(client, message_archives=None):
86
"""Instantiate a ForkedFakeService from the client.
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.
93
return ForkedFakeService(client.port, message_archives)
96
"""Tell the parent process that the server is ready for writes."""
97
os.write(self.write_end, 'asdf')
102
Fork and start a server in the child. Return when the server is ready
108
os.read(self.read_end, 1)
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', {})
121
stream=sys.stderr, level=logging.INFO)
122
service.serve_forever()
124
def __exit__(self, exc_type, exc_val, traceback):
125
os.kill(self.pid, SIGKILL)
128
class FakeGrackleRequestHandler(BaseHTTPRequestHandler):
129
"""A request handler that forwards to server.store."""
131
def __init__(self, *args, **kwargs):
132
"""Constructor. Sets up logging."""
133
self.logger = logging.getLogger('http')
134
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
137
"""Create an archive or message on PUT."""
138
scheme, netloc, path, params, query_string, fragments = (
140
parts = path.split('/')
141
if parts[1] != 'archive':
142
# This is an unknonwn operation?
145
# This expected path is /archive/archive_id/message_id.
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)
153
self.send_error(httplib.BAD_REQUEST)
156
"""Change a message on POST."""
157
scheme, netloc, path, params, query_string, fragments = (
159
parts = path.split('/')
160
if parts[1] != 'archive':
161
# This is an unknonwn operation?
164
# This expected path is /archive/archive_id/message_id.
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)
171
self.wfile.write(simplejson.dumps(response))
173
self.send_error(httplib.BAD_REQUEST)
176
"""Retrieve a list of messages on GET."""
177
scheme, netloc, path, params, query_string, fragments = (
179
parts = path.split('/')
180
if parts[1] == 'archive':
182
response = self.server.store.get_messages(
183
parts[2], query_string)
184
self.send_response(httplib.OK)
186
self.wfile.write(simplejson.dumps(response))
187
except Exception, error:
189
httplib.BAD_REQUEST, error.__doc__)
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)
53
class TestPutArchive(TestCase):
55
def test_put_archive(self):
56
client = GrackleClient('localhost', 8410)
58
with ForkedFakeService.from_client(client, message_archives):
59
client.put_archive('arch1')
60
response = client.get_messages('arch1')
61
self.assertEqual(0, len(response['messages']))
63
def test_put_archive_existing_archive(self):
64
client = GrackleClient('localhost', 8411)
65
message_archives = {'arch1': []}
66
with ForkedFakeService.from_client(client, message_archives):
67
with ExpectedException(ArchiveIdExists, ''):
68
client.put_archive('arch1')
199
71
class TestPutMessage(TestCase):