60
57
Returns stdout and stderr.
60
def on_server_start(backing_urls, tcp_server):
62
target=on_server_start_thread, args=(tcp_server,))
62
64
def on_server_start_thread(tcp_server):
63
"""This runs concurrently with the server thread.
65
The server is interrupted as soon as ``func`` finishes, even if an
66
exception is encountered.
70
67
self.tcp_server = tcp_server
73
70
func(*func_args, **func_kwargs)
74
71
except Exception, e:
75
72
# Log errors to make some test failures a little less
77
trace.mutter('func broke: %r', e)
74
mutter('func broke: %r', e)
79
76
# Then stop the server
80
trace.mutter('interrupting...')
77
mutter('interrupting...')
81
78
thread.interrupt_main()
82
# When the hook is fired, it just starts ``on_server_start_thread`` and
84
def on_server_start(backing_urls, tcp_server):
86
target=on_server_start_thread, args=(tcp_server,))
89
79
SmartTCPServer.hooks.install_named_hook(
90
80
'server_started_ex', on_server_start,
91
81
'run_bzr_serve_then_func hook')
92
# It seesm thread.interrupt_main() will not raise KeyboardInterrupt
93
# until after socket.accept returns. So we set the timeout low to make
95
self.overrideAttr(SmartTCPServer, '_ACCEPT_TIMEOUT', 0.1)
96
82
# start a TCP server
98
out, err = self.run_bzr(['serve'] + list(serve_args),
84
out, err = self.run_bzr(['serve'] + list(serve_args))
100
85
except KeyboardInterrupt, e:
108
93
super(TestBzrServe, self).setUp()
109
94
self.disable_missing_extensions_warning()
111
def test_server_exception_with_hook(self):
112
"""Catch exception from the server in the server_exception hook.
114
We use ``run_bzr_serve_then_func`` without a ``func`` so the server
115
will receive a KeyboardInterrupt exception we want to catch.
118
if exception[0] is KeyboardInterrupt:
119
sys.stderr.write('catching KeyboardInterrupt\n')
123
SmartTCPServer.hooks.install_named_hook(
124
'server_exception', hook,
125
'test_server_except_hook hook')
126
args = ['--port', 'localhost:0', '--quiet']
127
out, err = self.run_bzr_serve_then_func(args, retcode=0)
128
self.assertEqual('catching KeyboardInterrupt\n', err)
130
def test_server_exception_no_hook(self):
131
"""test exception without hook returns error"""
133
out, err = self.run_bzr_serve_then_func(args, retcode=3)
135
96
def assertInetServerShutsdownCleanly(self, process):
136
97
"""Shutdown the server process looking for errors."""
137
98
# Shutdown the server: the server should shut down when it cannot read
273
234
self.assertContainsRe(content, r'hpss request: \[[0-9-]+\]')
275
def test_bzr_serve_supports_configurable_timeout(self):
276
gs = config.GlobalStack()
277
gs.set('serve.client_timeout', 0.2)
278
process, url = self.start_server_port()
279
self.build_tree_contents([('a_file', 'contents\n')])
280
# We can connect and issue a request
281
t = transport.get_transport_from_url(url)
282
self.assertEqual('contents\n', t.get_bytes('a_file'))
283
# However, if we just wait for more content from the server, it will
284
# eventually disconnect us.
285
# TODO: Use something like signal.alarm() so that if the server doesn't
286
# properly handle the timeout, we end up failing the test instead
287
# of hanging forever.
288
m = t.get_smart_medium()
290
# Now, we wait for timeout to trigger
291
err = process.stderr.readline()
293
'Connection Timeout: disconnecting client after 0.2 seconds\n',
295
self.assertServerFinishesCleanly(process)
297
def test_bzr_serve_supports_client_timeout(self):
298
process, url = self.start_server_port(['--client-timeout=0.1'])
299
self.build_tree_contents([('a_file', 'contents\n')])
300
# We can connect and issue a request
301
t = transport.get_transport_from_url(url)
302
self.assertEqual('contents\n', t.get_bytes('a_file'))
303
# However, if we just wait for more content from the server, it will
304
# eventually disconnect us.
305
# TODO: Use something like signal.alarm() so that if the server doesn't
306
# properly handle the timeout, we end up failing the test instead
307
# of hanging forever.
308
m = t.get_smart_medium()
310
# Now, we wait for timeout to trigger
311
err = process.stderr.readline()
313
'Connection Timeout: disconnecting client after 0.1 seconds\n',
315
self.assertServerFinishesCleanly(process)
317
def test_bzr_serve_graceful_shutdown(self):
318
big_contents = 'a'*64*1024
319
self.build_tree_contents([('bigfile', big_contents)])
320
process, url = self.start_server_port(['--client-timeout=1.0'])
321
t = transport.get_transport_from_url(url)
322
m = t.get_smart_medium()
323
c = client._SmartClient(m)
324
# Start, but don't finish a response
325
resp, response_handler = c.call_expecting_body('get', 'bigfile')
326
self.assertEqual(('ok',), resp)
327
# Note: process.send_signal is a Python 2.6ism
328
process.send_signal(signal.SIGHUP)
329
# Wait for the server to notice the signal, and then read the actual
330
# body of the response. That way we know that it is waiting for the
332
self.assertEqual('Requested to stop gracefully\n',
333
process.stderr.readline())
334
self.assertEqual('Waiting for 1 client(s) to finish\n',
335
process.stderr.readline())
336
body = response_handler.read_body_bytes()
337
if body != big_contents:
338
self.fail('Failed to properly read the contents of "bigfile"')
339
# Now that our request is finished, the medium should notice it has
341
self.assertEqual('', m.read_bytes(1))
342
# And the server should be stopping
343
self.assertEqual(0, process.wait())
346
237
class TestCmdServeChrooting(TestBzrServeBase):