/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

  • Committer: Robert Collins
  • Date: 2010-05-05 00:05:29 UTC
  • mto: This revision was merged to the branch mainline in revision 5206.
  • Revision ID: robertc@robertcollins.net-20100505000529-ltmllyms5watqj5u
Make 'pydoc bzrlib.tests.build_tree_shape' useful.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010, 2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
import errno
18
 
import socket
19
 
try:
20
 
    import socketserver
21
 
except ImportError:
22
 
    import SocketServer as socketserver
23
 
import sys
24
 
import threading
25
 
 
26
 
 
27
 
from breezy import (
28
 
    cethread,
29
 
    errors,
30
 
    osutils,
 
17
from bzrlib import (
31
18
    transport,
32
19
    urlutils,
33
20
    )
34
 
from breezy.transport import (
 
21
from bzrlib.transport import (
35
22
    chroot,
36
23
    pathfilter,
37
24
    )
38
 
from breezy.bzr.smart import (
39
 
    medium,
40
 
    server,
41
 
    )
42
 
 
43
 
 
44
 
def debug_threads():
45
 
    # FIXME: There is a dependency loop between breezy.tests and
46
 
    # breezy.tests.test_server that needs to be fixed. In the mean time
47
 
    # defining this function is enough for our needs. -- vila 20100611
48
 
    from breezy import tests
49
 
    return 'threads' in tests.selftest_debug_flags
 
25
from bzrlib.smart import server
50
26
 
51
27
 
52
28
class TestServer(transport.Server):
55
31
    The TestServer interface provides a server for a given transport. We use
56
32
    these servers as loopback testing tools. For any given transport the
57
33
    Servers it provides must either allow writing, or serve the contents
58
 
    of osutils.getcwd() at the time start_server is called.
 
34
    of os.getcwdu() at the time start_server is called.
59
35
 
60
36
    Note that these are real servers - they must implement all the things
61
37
    that we want bzr transports to take advantage of.
68
44
        a database like svn, or a memory only transport, it should return
69
45
        a connection to a newly established resource for this Server.
70
46
        Otherwise it should return a url that will provide access to the path
71
 
        that was osutils.getcwd() when start_server() was called.
 
47
        that was os.getcwdu() when start_server() was called.
72
48
 
73
49
        Subsequent calls will return the same resource.
74
50
        """
106
82
    """
107
83
 
108
84
    def start_server(self, server=None):
109
 
        """See breezy.transport.Server.start_server.
 
85
        """See bzrlib.transport.Server.start_server.
110
86
 
111
87
        :server: decorate the urls given by server. If not provided a
112
88
        LocalServer is created.
132
108
        return self.get_decorator_class()._get_url_prefix()
133
109
 
134
110
    def get_bogus_url(self):
135
 
        """See breezy.transport.Server.get_bogus_url."""
 
111
        """See bzrlib.transport.Server.get_bogus_url."""
136
112
        return self.get_url_prefix() + self._server.get_bogus_url()
137
113
 
138
114
    def get_url(self):
139
 
        """See breezy.transport.Server.get_url."""
 
115
        """See bzrlib.transport.Server.get_url."""
140
116
        return self.get_url_prefix() + self._server.get_url()
141
117
 
142
118
 
144
120
    """Server for the BrokenRenameTransportDecorator for testing with."""
145
121
 
146
122
    def get_decorator_class(self):
147
 
        from breezy.transport import brokenrename
 
123
        from bzrlib.transport import brokenrename
148
124
        return brokenrename.BrokenRenameTransportDecorator
149
125
 
150
126
 
152
128
    """Server for the FakeNFSTransportDecorator for testing with."""
153
129
 
154
130
    def get_decorator_class(self):
155
 
        from breezy.transport import fakenfs
 
131
        from bzrlib.transport import fakenfs
156
132
        return fakenfs.FakeNFSTransportDecorator
157
133
 
158
134
 
163
139
    """
164
140
 
165
141
    def get_decorator_class(self):
166
 
        from breezy.transport import fakevfat
 
142
        from bzrlib.transport import fakevfat
167
143
        return fakevfat.FakeVFATTransportDecorator
168
144
 
169
145
 
171
147
    """Server for testing."""
172
148
 
173
149
    def get_decorator_class(self):
174
 
        from breezy.transport import log
 
150
        from bzrlib.transport import log
175
151
        return log.TransportLogDecorator
176
152
 
177
153
 
179
155
    """Server for the NoSmartTransportDecorator for testing with."""
180
156
 
181
157
    def get_decorator_class(self):
182
 
        from breezy.transport import nosmart
 
158
        from bzrlib.transport import nosmart
183
159
        return nosmart.NoSmartTransportDecorator
184
160
 
185
161
 
187
163
    """Server for the ReadonlyTransportDecorator for testing with."""
188
164
 
189
165
    def get_decorator_class(self):
190
 
        from breezy.transport import readonly
 
166
        from bzrlib.transport import readonly
191
167
        return readonly.ReadonlyTransportDecorator
192
168
 
193
169
 
195
171
    """Server for the TransportTraceDecorator for testing with."""
196
172
 
197
173
    def get_decorator_class(self):
198
 
        from breezy.transport import trace
 
174
        from bzrlib.transport import trace
199
175
        return trace.TransportTraceDecorator
200
176
 
201
177
 
203
179
    """Server for the UnlistableTransportDecorator for testing with."""
204
180
 
205
181
    def get_decorator_class(self):
206
 
        from breezy.transport import unlistable
 
182
        from bzrlib.transport import unlistable
207
183
        return unlistable.UnlistableTransportDecorator
208
184
 
209
185
 
216
192
    def start_server(self, backing_server=None):
217
193
        """Setup the Chroot on backing_server."""
218
194
        if backing_server is not None:
219
 
            self.backing_transport = transport.get_transport_from_url(
 
195
            self.backing_transport = transport.get_transport(
220
196
                backing_server.get_url())
221
197
        else:
222
 
            self.backing_transport = transport.get_transport_from_path('.')
 
198
            self.backing_transport = transport.get_transport('.')
223
199
        self.backing_transport.clone('added-by-filter').ensure_base()
224
200
        self.filter_func = lambda x: 'added-by-filter/' + x
225
201
        super(TestingPathFilteringServer, self).start_server()
237
213
    def start_server(self, backing_server=None):
238
214
        """Setup the Chroot on backing_server."""
239
215
        if backing_server is not None:
240
 
            self.backing_transport = transport.get_transport_from_url(
 
216
            self.backing_transport = transport.get_transport(
241
217
                backing_server.get_url())
242
218
        else:
243
 
            self.backing_transport = transport.get_transport_from_path('.')
 
219
            self.backing_transport = transport.get_transport('.')
244
220
        super(TestingChrootServer, self).start_server()
245
221
 
246
222
    def get_bogus_url(self):
247
223
        raise NotImplementedError
248
224
 
249
225
 
250
 
class TestThread(cethread.CatchingExceptionThread):
251
 
 
252
 
    def join(self, timeout=5):
253
 
        """Overrides to use a default timeout.
254
 
 
255
 
        The default timeout is set to 5 and should expire only when a thread
256
 
        serving a client connection is hung.
257
 
        """
258
 
        super(TestThread, self).join(timeout)
259
 
        if timeout and self.isAlive():
260
 
            # The timeout expired without joining the thread, the thread is
261
 
            # therefore stucked and that's a failure as far as the test is
262
 
            # concerned. We used to hang here.
263
 
 
264
 
            # FIXME: we need to kill the thread, but as far as the test is
265
 
            # concerned, raising an assertion is too strong. On most of the
266
 
            # platforms, this doesn't occur, so just mentioning the problem is
267
 
            # enough for now -- vila 2010824
268
 
            sys.stderr.write('thread %s hung\n' % (self.name,))
269
 
            # raise AssertionError('thread %s hung' % (self.name,))
270
 
 
271
 
 
272
 
class TestingTCPServerMixin(object):
273
 
    """Mixin to support running socketserver.TCPServer in a thread.
274
 
 
275
 
    Tests are connecting from the main thread, the server has to be run in a
276
 
    separate thread.
277
 
    """
278
 
 
279
 
    def __init__(self):
280
 
        self.started = threading.Event()
281
 
        self.serving = None
282
 
        self.stopped = threading.Event()
283
 
        # We collect the resources used by the clients so we can release them
284
 
        # when shutting down
285
 
        self.clients = []
286
 
        self.ignored_exceptions = None
287
 
 
288
 
    def server_bind(self):
289
 
        self.socket.bind(self.server_address)
290
 
        self.server_address = self.socket.getsockname()
291
 
 
292
 
    def serve(self):
293
 
        self.serving = True
294
 
        # We are listening and ready to accept connections
295
 
        self.started.set()
296
 
        try:
297
 
            while self.serving:
298
 
                # Really a connection but the python framework is generic and
299
 
                # call them requests
300
 
                self.handle_request()
301
 
            # Let's close the listening socket
302
 
            self.server_close()
303
 
        finally:
304
 
            self.stopped.set()
305
 
 
306
 
    def handle_request(self):
307
 
        """Handle one request.
308
 
 
309
 
        The python version swallows some socket exceptions and we don't use
310
 
        timeout, so we override it to better control the server behavior.
311
 
        """
312
 
        request, client_address = self.get_request()
313
 
        if self.verify_request(request, client_address):
314
 
            try:
315
 
                self.process_request(request, client_address)
316
 
            except BaseException:
317
 
                self.handle_error(request, client_address)
318
 
        else:
319
 
            self.close_request(request)
320
 
 
321
 
    def get_request(self):
322
 
        return self.socket.accept()
323
 
 
324
 
    def verify_request(self, request, client_address):
325
 
        """Verify the request.
326
 
 
327
 
        Return True if we should proceed with this request, False if we should
328
 
        not even touch a single byte in the socket ! This is useful when we
329
 
        stop the server with a dummy last connection.
330
 
        """
331
 
        return self.serving
332
 
 
333
 
    def handle_error(self, request, client_address):
334
 
        # Stop serving and re-raise the last exception seen
335
 
        self.serving = False
336
 
        # The following can be used for debugging purposes, it will display the
337
 
        # exception and the traceback just when it occurs instead of waiting
338
 
        # for the thread to be joined.
339
 
        # socketserver.BaseServer.handle_error(self, request, client_address)
340
 
 
341
 
        # We call close_request manually, because we are going to raise an
342
 
        # exception. The socketserver implementation calls:
343
 
        #   handle_error(...)
344
 
        #   close_request(...)
345
 
        # But because we raise the exception, close_request will never be
346
 
        # triggered. This helps client not block waiting for a response when
347
 
        # the server gets an exception.
348
 
        self.close_request(request)
349
 
        raise
350
 
 
351
 
    def ignored_exceptions_during_shutdown(self, e):
352
 
        if sys.platform == 'win32':
353
 
            accepted_errnos = [errno.EBADF,
354
 
                               errno.EPIPE,
355
 
                               errno.WSAEBADF,
356
 
                               errno.WSAECONNRESET,
357
 
                               errno.WSAENOTCONN,
358
 
                               errno.WSAESHUTDOWN,
359
 
                               ]
360
 
        else:
361
 
            accepted_errnos = [errno.EBADF,
362
 
                               errno.ECONNRESET,
363
 
                               errno.ENOTCONN,
364
 
                               errno.EPIPE,
365
 
                               ]
366
 
        if isinstance(e, socket.error) and e.errno in accepted_errnos:
367
 
            return True
368
 
        return False
369
 
 
370
 
    # The following methods are called by the main thread
371
 
 
372
 
    def stop_client_connections(self):
373
 
        while self.clients:
374
 
            c = self.clients.pop()
375
 
            self.shutdown_client(c)
376
 
 
377
 
    def shutdown_socket(self, sock):
378
 
        """Properly shutdown a socket.
379
 
 
380
 
        This should be called only when no other thread is trying to use the
381
 
        socket.
382
 
        """
383
 
        try:
384
 
            sock.shutdown(socket.SHUT_RDWR)
385
 
            sock.close()
386
 
        except Exception as e:
387
 
            if self.ignored_exceptions(e):
388
 
                pass
389
 
            else:
390
 
                raise
391
 
 
392
 
    # The following methods are called by the main thread
393
 
 
394
 
    def set_ignored_exceptions(self, thread, ignored_exceptions):
395
 
        self.ignored_exceptions = ignored_exceptions
396
 
        thread.set_ignored_exceptions(self.ignored_exceptions)
397
 
 
398
 
    def _pending_exception(self, thread):
399
 
        """Raise server uncaught exception.
400
 
 
401
 
        Daughter classes can override this if they use daughter threads.
402
 
        """
403
 
        thread.pending_exception()
404
 
 
405
 
 
406
 
class TestingTCPServer(TestingTCPServerMixin, socketserver.TCPServer):
407
 
 
408
 
    def __init__(self, server_address, request_handler_class):
409
 
        TestingTCPServerMixin.__init__(self)
410
 
        socketserver.TCPServer.__init__(self, server_address,
411
 
                                        request_handler_class)
412
 
 
413
 
    def get_request(self):
414
 
        """Get the request and client address from the socket."""
415
 
        sock, addr = TestingTCPServerMixin.get_request(self)
416
 
        self.clients.append((sock, addr))
417
 
        return sock, addr
418
 
 
419
 
    # The following methods are called by the main thread
420
 
 
421
 
    def shutdown_client(self, client):
422
 
        sock, addr = client
423
 
        self.shutdown_socket(sock)
424
 
 
425
 
 
426
 
class TestingThreadingTCPServer(TestingTCPServerMixin,
427
 
                                socketserver.ThreadingTCPServer):
428
 
 
429
 
    def __init__(self, server_address, request_handler_class):
430
 
        TestingTCPServerMixin.__init__(self)
431
 
        socketserver.ThreadingTCPServer.__init__(self, server_address,
432
 
                                                 request_handler_class)
433
 
 
434
 
    def get_request(self):
435
 
        """Get the request and client address from the socket."""
436
 
        sock, addr = TestingTCPServerMixin.get_request(self)
437
 
        # The thread is not created yet, it will be updated in process_request
438
 
        self.clients.append((sock, addr, None))
439
 
        return sock, addr
440
 
 
441
 
    def process_request_thread(self, started, detached, stopped,
442
 
                               request, client_address):
443
 
        started.set()
444
 
        # We will be on our own once the server tells us we're detached
445
 
        detached.wait()
446
 
        socketserver.ThreadingTCPServer.process_request_thread(
447
 
            self, request, client_address)
448
 
        self.close_request(request)
449
 
        stopped.set()
450
 
 
451
 
    def process_request(self, request, client_address):
452
 
        """Start a new thread to process the request."""
453
 
        started = threading.Event()
454
 
        detached = threading.Event()
455
 
        stopped = threading.Event()
456
 
        t = TestThread(
457
 
            sync_event=stopped,
458
 
            name='%s -> %s' % (client_address, self.server_address),
459
 
            target=self.process_request_thread,
460
 
            args=(started, detached, stopped, request, client_address))
461
 
        # Update the client description
462
 
        self.clients.pop()
463
 
        self.clients.append((request, client_address, t))
464
 
        # Propagate the exception handler since we must use the same one as
465
 
        # TestingTCPServer for connections running in their own threads.
466
 
        t.set_ignored_exceptions(self.ignored_exceptions)
467
 
        t.start()
468
 
        started.wait()
469
 
        # If an exception occured during the thread start, it will get raised.
470
 
        t.pending_exception()
471
 
        if debug_threads():
472
 
            sys.stderr.write('Client thread %s started\n' % (t.name,))
473
 
        # Tell the thread, it's now on its own for exception handling.
474
 
        detached.set()
475
 
 
476
 
    # The following methods are called by the main thread
477
 
 
478
 
    def shutdown_client(self, client):
479
 
        sock, addr, connection_thread = client
480
 
        self.shutdown_socket(sock)
481
 
        if connection_thread is not None:
482
 
            # The thread has been created only if the request is processed but
483
 
            # after the connection is inited. This could happen during server
484
 
            # shutdown. If an exception occurred in the thread it will be
485
 
            # re-raised
486
 
            if debug_threads():
487
 
                sys.stderr.write('Client thread %s will be joined\n'
488
 
                                 % (connection_thread.name,))
489
 
            connection_thread.join()
490
 
 
491
 
    def set_ignored_exceptions(self, thread, ignored_exceptions):
492
 
        TestingTCPServerMixin.set_ignored_exceptions(self, thread,
493
 
                                                     ignored_exceptions)
494
 
        for sock, addr, connection_thread in self.clients:
495
 
            if connection_thread is not None:
496
 
                connection_thread.set_ignored_exceptions(
497
 
                    self.ignored_exceptions)
498
 
 
499
 
    def _pending_exception(self, thread):
500
 
        for sock, addr, connection_thread in self.clients:
501
 
            if connection_thread is not None:
502
 
                connection_thread.pending_exception()
503
 
        TestingTCPServerMixin._pending_exception(self, thread)
504
 
 
505
 
 
506
 
class TestingTCPServerInAThread(transport.Server):
507
 
    """A server in a thread that re-raise thread exceptions."""
508
 
 
509
 
    def __init__(self, server_address, server_class, request_handler_class):
510
 
        self.server_class = server_class
511
 
        self.request_handler_class = request_handler_class
512
 
        self.host, self.port = server_address
513
 
        self.server = None
514
 
        self._server_thread = None
515
 
 
516
 
    def __repr__(self):
517
 
        return "%s(%s:%s)" % (self.__class__.__name__, self.host, self.port)
518
 
 
519
 
    def create_server(self):
520
 
        return self.server_class((self.host, self.port),
521
 
                                 self.request_handler_class)
522
 
 
523
 
    def start_server(self):
524
 
        self.server = self.create_server()
525
 
        self._server_thread = TestThread(
526
 
            sync_event=self.server.started,
527
 
            target=self.run_server)
528
 
        self._server_thread.start()
529
 
        # Wait for the server thread to start (i.e. release the lock)
530
 
        self.server.started.wait()
531
 
        # Get the real address, especially the port
532
 
        self.host, self.port = self.server.server_address
533
 
        self._server_thread.name = self.server.server_address
534
 
        if debug_threads():
535
 
            sys.stderr.write('Server thread %s started\n'
536
 
                             % (self._server_thread.name,))
537
 
        # If an exception occured during the server start, it will get raised,
538
 
        # otherwise, the server is blocked on its accept() call.
539
 
        self._server_thread.pending_exception()
540
 
        # From now on, we'll use a different event to ensure the server can set
541
 
        # its exception
542
 
        self._server_thread.set_sync_event(self.server.stopped)
543
 
 
544
 
    def run_server(self):
545
 
        self.server.serve()
546
 
 
547
 
    def stop_server(self):
548
 
        if self.server is None:
549
 
            return
550
 
        try:
551
 
            # The server has been started successfully, shut it down now.  As
552
 
            # soon as we stop serving, no more connection are accepted except
553
 
            # one to get out of the blocking listen.
554
 
            self.set_ignored_exceptions(
555
 
                self.server.ignored_exceptions_during_shutdown)
556
 
            self.server.serving = False
557
 
            if debug_threads():
558
 
                sys.stderr.write('Server thread %s will be joined\n'
559
 
                                 % (self._server_thread.name,))
560
 
            # The server is listening for a last connection, let's give it:
561
 
            last_conn = None
562
 
            try:
563
 
                last_conn = osutils.connect_socket((self.host, self.port))
564
 
            except socket.error:
565
 
                # But ignore connection errors as the point is to unblock the
566
 
                # server thread, it may happen that it's not blocked or even
567
 
                # not started.
568
 
                pass
569
 
            # We start shutting down the clients while the server itself is
570
 
            # shutting down.
571
 
            self.server.stop_client_connections()
572
 
            # Now we wait for the thread running self.server.serve() to finish
573
 
            self.server.stopped.wait()
574
 
            if last_conn is not None:
575
 
                # Close the last connection without trying to use it. The
576
 
                # server will not process a single byte on that socket to avoid
577
 
                # complications (SSL starts with a handshake for example).
578
 
                last_conn.close()
579
 
            # Check for any exception that could have occurred in the server
580
 
            # thread
581
 
            try:
582
 
                self._server_thread.join()
583
 
            except Exception as e:
584
 
                if self.server.ignored_exceptions(e):
585
 
                    pass
586
 
                else:
587
 
                    raise
588
 
        finally:
589
 
            # Make sure we can be called twice safely, note that this means
590
 
            # that we will raise a single exception even if several occurred in
591
 
            # the various threads involved.
592
 
            self.server = None
593
 
 
594
 
    def set_ignored_exceptions(self, ignored_exceptions):
595
 
        """Install an exception handler for the server."""
596
 
        self.server.set_ignored_exceptions(self._server_thread,
597
 
                                           ignored_exceptions)
598
 
 
599
 
    def pending_exception(self):
600
 
        """Raise uncaught exception in the server."""
601
 
        self.server._pending_exception(self._server_thread)
602
 
 
603
 
 
604
 
class TestingSmartConnectionHandler(socketserver.BaseRequestHandler,
605
 
                                    medium.SmartServerSocketStreamMedium):
606
 
 
607
 
    def __init__(self, request, client_address, server):
608
 
        medium.SmartServerSocketStreamMedium.__init__(
609
 
            self, request, server.backing_transport,
610
 
            server.root_client_path,
611
 
            timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
612
 
        request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
613
 
        socketserver.BaseRequestHandler.__init__(self, request, client_address,
614
 
                                                 server)
615
 
 
616
 
    def handle(self):
617
 
        try:
618
 
            while not self.finished:
619
 
                server_protocol = self._build_protocol()
620
 
                self._serve_one_request(server_protocol)
621
 
        except errors.ConnectionTimeout:
622
 
            # idle connections aren't considered a failure of the server
623
 
            return
624
 
 
625
 
 
626
 
_DEFAULT_TESTING_CLIENT_TIMEOUT = 60.0
627
 
 
628
 
 
629
 
class TestingSmartServer(TestingThreadingTCPServer, server.SmartTCPServer):
630
 
 
631
 
    def __init__(self, server_address, request_handler_class,
632
 
                 backing_transport, root_client_path):
633
 
        TestingThreadingTCPServer.__init__(self, server_address,
634
 
                                           request_handler_class)
635
 
        server.SmartTCPServer.__init__(
636
 
            self, backing_transport,
637
 
            root_client_path, client_timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
638
 
 
639
 
    def serve(self):
640
 
        self.run_server_started_hooks()
641
 
        try:
642
 
            TestingThreadingTCPServer.serve(self)
643
 
        finally:
644
 
            self.run_server_stopped_hooks()
645
 
 
646
 
    def get_url(self):
647
 
        """Return the url of the server"""
648
 
        return "bzr://%s:%d/" % self.server_address
649
 
 
650
 
 
651
 
class SmartTCPServer_for_testing(TestingTCPServerInAThread):
 
226
class SmartTCPServer_for_testing(server.SmartTCPServer):
652
227
    """Server suitable for use by transport tests.
653
228
 
654
229
    This server is backed by the process's cwd.
655
230
    """
656
231
 
657
232
    def __init__(self, thread_name_suffix=''):
 
233
        super(SmartTCPServer_for_testing, self).__init__(None)
658
234
        self.client_path_extra = None
659
235
        self.thread_name_suffix = thread_name_suffix
660
 
        self.host = '127.0.0.1'
661
 
        self.port = 0
662
 
        super(SmartTCPServer_for_testing, self).__init__(
663
 
            (self.host, self.port),
664
 
            TestingSmartServer,
665
 
            TestingSmartConnectionHandler)
666
236
 
667
 
    def create_server(self):
668
 
        return self.server_class((self.host, self.port),
669
 
                                 self.request_handler_class,
670
 
                                 self.backing_transport,
671
 
                                 self.root_client_path)
 
237
    def get_backing_transport(self, backing_transport_server):
 
238
        """Get a backing transport from a server we are decorating."""
 
239
        return transport.get_transport(backing_transport_server.get_url())
672
240
 
673
241
    def start_server(self, backing_transport_server=None,
674
 
                     client_path_extra='/extra/'):
 
242
              client_path_extra='/extra/'):
675
243
        """Set up server for testing.
676
244
 
677
245
        :param backing_transport_server: backing server to use.  If not
686
254
        """
687
255
        if not client_path_extra.startswith('/'):
688
256
            raise ValueError(client_path_extra)
689
 
        self.root_client_path = self.client_path_extra = client_path_extra
690
 
        from breezy.transport.chroot import ChrootServer
 
257
        from bzrlib.transport.chroot import ChrootServer
691
258
        if backing_transport_server is None:
692
259
            backing_transport_server = LocalURLServer()
693
260
        self.chroot_server = ChrootServer(
694
261
            self.get_backing_transport(backing_transport_server))
695
262
        self.chroot_server.start_server()
696
 
        self.backing_transport = transport.get_transport_from_url(
 
263
        self.backing_transport = transport.get_transport(
697
264
            self.chroot_server.get_url())
698
 
        super(SmartTCPServer_for_testing, self).start_server()
 
265
        self.root_client_path = self.client_path_extra = client_path_extra
 
266
        self.start_background_thread(self.thread_name_suffix)
699
267
 
700
268
    def stop_server(self):
701
 
        try:
702
 
            super(SmartTCPServer_for_testing, self).stop_server()
703
 
        finally:
704
 
            self.chroot_server.stop_server()
705
 
 
706
 
    def get_backing_transport(self, backing_transport_server):
707
 
        """Get a backing transport from a server we are decorating."""
708
 
        return transport.get_transport_from_url(
709
 
            backing_transport_server.get_url())
 
269
        self.stop_background_thread()
 
270
        self.chroot_server.stop_server()
710
271
 
711
272
    def get_url(self):
712
 
        url = self.server.get_url()
 
273
        url = super(SmartTCPServer_for_testing, self).get_url()
713
274
        return url[:-1] + self.client_path_extra
714
275
 
715
276
    def get_bogus_url(self):
723
284
    def get_backing_transport(self, backing_transport_server):
724
285
        """Get a backing transport from a server we are decorating."""
725
286
        url = 'readonly+' + backing_transport_server.get_url()
726
 
        return transport.get_transport_from_url(url)
 
287
        return transport.get_transport(url)
727
288
 
728
289
 
729
290
class SmartTCPServer_for_testing_v2_only(SmartTCPServer_for_testing):
738
299
 
739
300
 
740
301
class ReadonlySmartTCPServer_for_testing_v2_only(
741
 
        SmartTCPServer_for_testing_v2_only):
 
302
    SmartTCPServer_for_testing_v2_only):
742
303
    """Get a readonly server for testing."""
743
304
 
744
305
    def get_backing_transport(self, backing_transport_server):
745
306
        """Get a backing transport from a server we are decorating."""
746
307
        url = 'readonly+' + backing_transport_server.get_url()
747
 
        return transport.get_transport_from_url(url)
 
308
        return transport.get_transport(url)
 
309
 
 
310
 
 
311
 
 
312