~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_serve.py

(gz) Fix test failure on alpha by correcting format string for
 gc_chk_sha1_record (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import os
21
21
import signal
22
 
import sys
23
22
import thread
24
23
import threading
25
 
import time
26
24
 
27
25
from bzrlib import (
28
26
    builtins,
29
 
    config,
30
27
    errors,
31
28
    osutils,
32
29
    revision as _mod_revision,
33
 
    trace,
34
30
    transport,
35
31
    urlutils,
36
32
    )
45
41
    TestCaseWithMemoryTransport,
46
42
    TestCaseWithTransport,
47
43
    )
 
44
from bzrlib.trace import mutter
48
45
from bzrlib.transport import remote
49
46
 
50
47
 
59
56
 
60
57
        Returns stdout and stderr.
61
58
        """
 
59
        # install hook
 
60
        def on_server_start(backing_urls, tcp_server):
 
61
            t = threading.Thread(
 
62
                target=on_server_start_thread, args=(tcp_server,))
 
63
            t.start()
62
64
        def on_server_start_thread(tcp_server):
63
 
            """This runs concurrently with the server thread.
64
 
 
65
 
            The server is interrupted as soon as ``func`` finishes, even if an
66
 
            exception is encountered.
67
 
            """
68
65
            try:
69
66
                # Run func if set
70
67
                self.tcp_server = tcp_server
71
 
                if func is not None:
 
68
                if not func is None:
72
69
                    try:
73
70
                        func(*func_args, **func_kwargs)
74
71
                    except Exception, e:
75
72
                        # Log errors to make some test failures a little less
76
73
                        # mysterious.
77
 
                        trace.mutter('func broke: %r', e)
 
74
                        mutter('func broke: %r', e)
78
75
            finally:
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
83
 
        # return
84
 
        def on_server_start(backing_urls, tcp_server):
85
 
            t = threading.Thread(
86
 
                target=on_server_start_thread, args=(tcp_server,))
87
 
            t.start()
88
 
        # install hook
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
94
 
        # the test faster.
95
 
        self.overrideAttr(SmartTCPServer, '_ACCEPT_TIMEOUT', 0.1)
96
82
        # start a TCP server
97
83
        try:
98
 
            out, err = self.run_bzr(['serve'] + list(serve_args),
99
 
                                    retcode=retcode)
 
84
            out, err = self.run_bzr(['serve'] + list(serve_args))
100
85
        except KeyboardInterrupt, e:
101
86
            out, err = e.args
102
87
        return out, err
108
93
        super(TestBzrServe, self).setUp()
109
94
        self.disable_missing_extensions_warning()
110
95
 
111
 
    def test_server_exception_with_hook(self):
112
 
        """Catch exception from the server in the server_exception hook.
113
 
 
114
 
        We use ``run_bzr_serve_then_func`` without a ``func`` so the server
115
 
        will receive a KeyboardInterrupt exception we want to catch.
116
 
        """
117
 
        def hook(exception):
118
 
            if exception[0] is KeyboardInterrupt:
119
 
                sys.stderr.write('catching KeyboardInterrupt\n')
120
 
                return True
121
 
            else:
122
 
                return False
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)
129
 
 
130
 
    def test_server_exception_no_hook(self):
131
 
        """test exception without hook returns error"""
132
 
        args = []
133
 
        out, err = self.run_bzr_serve_then_func(args, retcode=3)
134
 
 
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
230
191
    def test_bzr_serve_port_readonly(self):
231
192
        """bzr server should provide a read only filesystem by default."""
232
193
        process, url = self.start_server_port()
233
 
        t = transport.get_transport_from_url(url)
 
194
        t = transport.get_transport(url)
234
195
        self.assertRaises(errors.TransportNotPossible, t.mkdir, 'adir')
235
196
        self.assertServerFinishesCleanly(process)
236
197
 
272
233
        f.close()
273
234
        self.assertContainsRe(content, r'hpss request: \[[0-9-]+\]')
274
235
 
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()
289
 
        m.read_bytes(1)
290
 
        # Now, we wait for timeout to trigger
291
 
        err = process.stderr.readline()
292
 
        self.assertEqual(
293
 
            'Connection Timeout: disconnecting client after 0.2 seconds\n',
294
 
            err)
295
 
        self.assertServerFinishesCleanly(process)
296
 
 
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()
309
 
        m.read_bytes(1)
310
 
        # Now, we wait for timeout to trigger
311
 
        err = process.stderr.readline()
312
 
        self.assertEqual(
313
 
            'Connection Timeout: disconnecting client after 0.1 seconds\n',
314
 
            err)
315
 
        self.assertServerFinishesCleanly(process)
316
 
 
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
331
 
        # request to finish
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
340
 
        # been disconnected.
341
 
        self.assertEqual('', m.read_bytes(1))
342
 
        # And the server should be stopping
343
 
        self.assertEqual(0, process.wait())
344
 
 
345
236
 
346
237
class TestCmdServeChrooting(TestBzrServeBase):
347
238
 
383
274
 
384
275
class TestUserdirExpansion(TestCaseWithMemoryTransport):
385
276
 
386
 
    @staticmethod
387
 
    def fake_expanduser(path):
 
277
    def fake_expanduser(self, path):
388
278
        """A simple, environment-independent, function for the duration of this
389
279
        test.
390
280
 
403
293
            self.fake_expanduser, lambda t: base_path)
404
294
        mem_transport = self.get_transport()
405
295
        mem_transport.mkdir_multi(['home', 'home/user'])
406
 
        bzr_server.set_up(mem_transport, None, None, inet=True, timeout=4.0)
 
296
        bzr_server.set_up(mem_transport, None, None, inet=True)
407
297
        self.addCleanup(bzr_server.tear_down)
408
298
        return bzr_server
409
299
 
425
315
        base_url = urlutils.local_path_to_url(base_dir) + '/'
426
316
        # Define a fake 'protocol' to capture the transport that cmd_serve
427
317
        # passes to serve_bzr.
428
 
        def capture_transport(transport, host, port, inet, timeout):
 
318
        def capture_transport(transport, host, port, inet):
429
319
            self.bzr_serve_transport = transport
430
320
        cmd = builtins.cmd_serve()
431
321
        # Read-only