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

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

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