/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 breezy/tests/test_server.py

  • Committer: Breezy landing bot
  • Author(s): Colin Watson
  • Date: 2020-11-16 21:47:08 UTC
  • mfrom: (7521.1.1 remove-lp-workaround)
  • Revision ID: breezy.the.bot@gmail.com-20201116214708-jos209mgxi41oy15
Remove breezy.git workaround for bazaar.launchpad.net.

Merged from https://code.launchpad.net/~cjwatson/brz/remove-lp-workaround/+merge/393710

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import errno
18
18
import socket
19
 
import SocketServer
 
19
import socketserver
20
20
import sys
21
21
import threading
22
 
import traceback
23
 
 
24
 
 
25
 
from bzrlib import (
 
22
 
 
23
 
 
24
from breezy import (
26
25
    cethread,
27
26
    errors,
28
27
    osutils,
29
28
    transport,
30
29
    urlutils,
31
30
    )
32
 
from bzrlib.transport import (
 
31
from breezy.transport import (
33
32
    chroot,
34
33
    pathfilter,
35
34
    )
36
 
from bzrlib.smart import (
 
35
from breezy.bzr.smart import (
37
36
    medium,
38
37
    server,
39
38
    )
40
39
 
41
40
 
42
41
def debug_threads():
43
 
    # FIXME: There is a dependency loop between bzrlib.tests and
44
 
    # bzrlib.tests.test_server that needs to be fixed. In the mean time
 
42
    # FIXME: There is a dependency loop between breezy.tests and
 
43
    # breezy.tests.test_server that needs to be fixed. In the mean time
45
44
    # defining this function is enough for our needs. -- vila 20100611
46
 
    from bzrlib import tests
 
45
    from breezy import tests
47
46
    return 'threads' in tests.selftest_debug_flags
48
47
 
49
48
 
53
52
    The TestServer interface provides a server for a given transport. We use
54
53
    these servers as loopback testing tools. For any given transport the
55
54
    Servers it provides must either allow writing, or serve the contents
56
 
    of os.getcwdu() at the time start_server is called.
 
55
    of osutils.getcwd() at the time start_server is called.
57
56
 
58
57
    Note that these are real servers - they must implement all the things
59
58
    that we want bzr transports to take advantage of.
66
65
        a database like svn, or a memory only transport, it should return
67
66
        a connection to a newly established resource for this Server.
68
67
        Otherwise it should return a url that will provide access to the path
69
 
        that was os.getcwdu() when start_server() was called.
 
68
        that was osutils.getcwd() when start_server() was called.
70
69
 
71
70
        Subsequent calls will return the same resource.
72
71
        """
104
103
    """
105
104
 
106
105
    def start_server(self, server=None):
107
 
        """See bzrlib.transport.Server.start_server.
 
106
        """See breezy.transport.Server.start_server.
108
107
 
109
108
        :server: decorate the urls given by server. If not provided a
110
109
        LocalServer is created.
130
129
        return self.get_decorator_class()._get_url_prefix()
131
130
 
132
131
    def get_bogus_url(self):
133
 
        """See bzrlib.transport.Server.get_bogus_url."""
 
132
        """See breezy.transport.Server.get_bogus_url."""
134
133
        return self.get_url_prefix() + self._server.get_bogus_url()
135
134
 
136
135
    def get_url(self):
137
 
        """See bzrlib.transport.Server.get_url."""
 
136
        """See breezy.transport.Server.get_url."""
138
137
        return self.get_url_prefix() + self._server.get_url()
139
138
 
140
139
 
142
141
    """Server for the BrokenRenameTransportDecorator for testing with."""
143
142
 
144
143
    def get_decorator_class(self):
145
 
        from bzrlib.transport import brokenrename
 
144
        from breezy.transport import brokenrename
146
145
        return brokenrename.BrokenRenameTransportDecorator
147
146
 
148
147
 
150
149
    """Server for the FakeNFSTransportDecorator for testing with."""
151
150
 
152
151
    def get_decorator_class(self):
153
 
        from bzrlib.transport import fakenfs
 
152
        from breezy.transport import fakenfs
154
153
        return fakenfs.FakeNFSTransportDecorator
155
154
 
156
155
 
161
160
    """
162
161
 
163
162
    def get_decorator_class(self):
164
 
        from bzrlib.transport import fakevfat
 
163
        from breezy.transport import fakevfat
165
164
        return fakevfat.FakeVFATTransportDecorator
166
165
 
167
166
 
169
168
    """Server for testing."""
170
169
 
171
170
    def get_decorator_class(self):
172
 
        from bzrlib.transport import log
 
171
        from breezy.transport import log
173
172
        return log.TransportLogDecorator
174
173
 
175
174
 
177
176
    """Server for the NoSmartTransportDecorator for testing with."""
178
177
 
179
178
    def get_decorator_class(self):
180
 
        from bzrlib.transport import nosmart
 
179
        from breezy.transport import nosmart
181
180
        return nosmart.NoSmartTransportDecorator
182
181
 
183
182
 
185
184
    """Server for the ReadonlyTransportDecorator for testing with."""
186
185
 
187
186
    def get_decorator_class(self):
188
 
        from bzrlib.transport import readonly
 
187
        from breezy.transport import readonly
189
188
        return readonly.ReadonlyTransportDecorator
190
189
 
191
190
 
193
192
    """Server for the TransportTraceDecorator for testing with."""
194
193
 
195
194
    def get_decorator_class(self):
196
 
        from bzrlib.transport import trace
 
195
        from breezy.transport import trace
197
196
        return trace.TransportTraceDecorator
198
197
 
199
198
 
201
200
    """Server for the UnlistableTransportDecorator for testing with."""
202
201
 
203
202
    def get_decorator_class(self):
204
 
        from bzrlib.transport import unlistable
 
203
        from breezy.transport import unlistable
205
204
        return unlistable.UnlistableTransportDecorator
206
205
 
207
206
 
254
253
        serving a client connection is hung.
255
254
        """
256
255
        super(TestThread, self).join(timeout)
257
 
        if timeout and self.isAlive():
 
256
        if timeout and self.is_alive():
258
257
            # The timeout expired without joining the thread, the thread is
259
258
            # therefore stucked and that's a failure as far as the test is
260
259
            # concerned. We used to hang here.
264
263
            # platforms, this doesn't occur, so just mentioning the problem is
265
264
            # enough for now -- vila 2010824
266
265
            sys.stderr.write('thread %s hung\n' % (self.name,))
267
 
            #raise AssertionError('thread %s hung' % (self.name,))
 
266
            # raise AssertionError('thread %s hung' % (self.name,))
268
267
 
269
268
 
270
269
class TestingTCPServerMixin(object):
271
 
    """Mixin to support running SocketServer.TCPServer in a thread.
 
270
    """Mixin to support running socketserver.TCPServer in a thread.
272
271
 
273
272
    Tests are connecting from the main thread, the server has to be run in a
274
273
    separate thread.
311
310
        if self.verify_request(request, client_address):
312
311
            try:
313
312
                self.process_request(request, client_address)
314
 
            except:
 
313
            except BaseException:
315
314
                self.handle_error(request, client_address)
316
315
        else:
317
316
            self.close_request(request)
334
333
        # The following can be used for debugging purposes, it will display the
335
334
        # exception and the traceback just when it occurs instead of waiting
336
335
        # for the thread to be joined.
337
 
        # SocketServer.BaseServer.handle_error(self, request, client_address)
 
336
        # socketserver.BaseServer.handle_error(self, request, client_address)
338
337
 
339
338
        # We call close_request manually, because we are going to raise an
340
 
        # exception. The SocketServer implementation calls:
 
339
        # exception. The socketserver implementation calls:
341
340
        #   handle_error(...)
342
341
        #   close_request(...)
343
342
        # But because we raise the exception, close_request will never be
361
360
                               errno.ENOTCONN,
362
361
                               errno.EPIPE,
363
362
                               ]
364
 
        if isinstance(e, socket.error) and e[0] in accepted_errnos:
 
363
        if isinstance(e, socket.error) and e.errno in accepted_errnos:
365
364
            return True
366
365
        return False
367
366
 
381
380
        try:
382
381
            sock.shutdown(socket.SHUT_RDWR)
383
382
            sock.close()
384
 
        except Exception, e:
 
383
        except Exception as e:
385
384
            if self.ignored_exceptions(e):
386
385
                pass
387
386
            else:
401
400
        thread.pending_exception()
402
401
 
403
402
 
404
 
class TestingTCPServer(TestingTCPServerMixin, SocketServer.TCPServer):
 
403
class TestingTCPServer(TestingTCPServerMixin, socketserver.TCPServer):
405
404
 
406
405
    def __init__(self, server_address, request_handler_class):
407
406
        TestingTCPServerMixin.__init__(self)
408
 
        SocketServer.TCPServer.__init__(self, server_address,
 
407
        socketserver.TCPServer.__init__(self, server_address,
409
408
                                        request_handler_class)
410
409
 
411
410
    def get_request(self):
422
421
 
423
422
 
424
423
class TestingThreadingTCPServer(TestingTCPServerMixin,
425
 
                                SocketServer.ThreadingTCPServer):
 
424
                                socketserver.ThreadingTCPServer):
426
425
 
427
426
    def __init__(self, server_address, request_handler_class):
428
427
        TestingTCPServerMixin.__init__(self)
429
 
        SocketServer.ThreadingTCPServer.__init__(self, server_address,
 
428
        socketserver.ThreadingTCPServer.__init__(self, server_address,
430
429
                                                 request_handler_class)
431
430
 
432
431
    def get_request(self):
441
440
        started.set()
442
441
        # We will be on our own once the server tells us we're detached
443
442
        detached.wait()
444
 
        SocketServer.ThreadingTCPServer.process_request_thread(
 
443
        socketserver.ThreadingTCPServer.process_request_thread(
445
444
            self, request, client_address)
446
445
        self.close_request(request)
447
446
        stopped.set()
454
453
        t = TestThread(
455
454
            sync_event=stopped,
456
455
            name='%s -> %s' % (client_address, self.server_address),
457
 
            target = self.process_request_thread,
458
 
            args = (started, detached, stopped, request, client_address))
 
456
            target=self.process_request_thread,
 
457
            args=(started, detached, stopped, request, client_address))
459
458
        # Update the client description
460
459
        self.clients.pop()
461
460
        self.clients.append((request, client_address, t))
559
558
            last_conn = None
560
559
            try:
561
560
                last_conn = osutils.connect_socket((self.host, self.port))
562
 
            except socket.error, e:
 
561
            except socket.error:
563
562
                # But ignore connection errors as the point is to unblock the
564
563
                # server thread, it may happen that it's not blocked or even
565
564
                # not started.
578
577
            # thread
579
578
            try:
580
579
                self._server_thread.join()
581
 
            except Exception, e:
 
580
            except Exception as e:
582
581
                if self.server.ignored_exceptions(e):
583
582
                    pass
584
583
                else:
599
598
        self.server._pending_exception(self._server_thread)
600
599
 
601
600
 
602
 
class TestingSmartConnectionHandler(SocketServer.BaseRequestHandler,
 
601
class TestingSmartConnectionHandler(socketserver.BaseRequestHandler,
603
602
                                    medium.SmartServerSocketStreamMedium):
604
603
 
605
604
    def __init__(self, request, client_address, server):
608
607
            server.root_client_path,
609
608
            timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
610
609
        request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
611
 
        SocketServer.BaseRequestHandler.__init__(self, request, client_address,
 
610
        socketserver.BaseRequestHandler.__init__(self, request, client_address,
612
611
                                                 server)
613
612
 
614
613
    def handle(self):
623
622
 
624
623
_DEFAULT_TESTING_CLIENT_TIMEOUT = 60.0
625
624
 
 
625
 
626
626
class TestingSmartServer(TestingThreadingTCPServer, server.SmartTCPServer):
627
627
 
628
628
    def __init__(self, server_address, request_handler_class,
629
629
                 backing_transport, root_client_path):
630
630
        TestingThreadingTCPServer.__init__(self, server_address,
631
631
                                           request_handler_class)
632
 
        server.SmartTCPServer.__init__(self, backing_transport,
 
632
        server.SmartTCPServer.__init__(
 
633
            self, backing_transport,
633
634
            root_client_path, client_timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
634
635
 
635
636
    def serve(self):
649
650
 
650
651
    This server is backed by the process's cwd.
651
652
    """
 
653
 
652
654
    def __init__(self, thread_name_suffix=''):
653
655
        self.client_path_extra = None
654
656
        self.thread_name_suffix = thread_name_suffix
655
657
        self.host = '127.0.0.1'
656
658
        self.port = 0
657
659
        super(SmartTCPServer_for_testing, self).__init__(
658
 
                (self.host, self.port),
659
 
                TestingSmartServer,
660
 
                TestingSmartConnectionHandler)
 
660
            (self.host, self.port),
 
661
            TestingSmartServer,
 
662
            TestingSmartConnectionHandler)
661
663
 
662
664
    def create_server(self):
663
665
        return self.server_class((self.host, self.port),
665
667
                                 self.backing_transport,
666
668
                                 self.root_client_path)
667
669
 
668
 
 
669
670
    def start_server(self, backing_transport_server=None,
670
671
                     client_path_extra='/extra/'):
671
672
        """Set up server for testing.
683
684
        if not client_path_extra.startswith('/'):
684
685
            raise ValueError(client_path_extra)
685
686
        self.root_client_path = self.client_path_extra = client_path_extra
686
 
        from bzrlib.transport.chroot import ChrootServer
 
687
        from breezy.transport.chroot import ChrootServer
687
688
        if backing_transport_server is None:
688
689
            backing_transport_server = LocalURLServer()
689
690
        self.chroot_server = ChrootServer(
734
735
 
735
736
 
736
737
class ReadonlySmartTCPServer_for_testing_v2_only(
737
 
    SmartTCPServer_for_testing_v2_only):
 
738
        SmartTCPServer_for_testing_v2_only):
738
739
    """Get a readonly server for testing."""
739
740
 
740
741
    def get_backing_transport(self, backing_transport_server):