~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

  • Committer: Jelmer Vernooij
  • Date: 2016-04-03 16:32:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6617.
  • Revision ID: jelmer@jelmer.uk-20160403163231-h72bo0uyek2gikw0
Don't put French text in doc/en/user-reference when LANGUAGE=fr_CH.UTF_8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import SocketServer
20
20
import sys
21
21
import threading
 
22
import traceback
22
23
 
23
24
 
24
25
from bzrlib import (
25
26
    cethread,
 
27
    errors,
26
28
    osutils,
27
29
    transport,
28
30
    urlutils,
212
214
    def start_server(self, backing_server=None):
213
215
        """Setup the Chroot on backing_server."""
214
216
        if backing_server is not None:
215
 
            self.backing_transport = transport.get_transport(
 
217
            self.backing_transport = transport.get_transport_from_url(
216
218
                backing_server.get_url())
217
219
        else:
218
 
            self.backing_transport = transport.get_transport('.')
 
220
            self.backing_transport = transport.get_transport_from_path('.')
219
221
        self.backing_transport.clone('added-by-filter').ensure_base()
220
222
        self.filter_func = lambda x: 'added-by-filter/' + x
221
223
        super(TestingPathFilteringServer, self).start_server()
233
235
    def start_server(self, backing_server=None):
234
236
        """Setup the Chroot on backing_server."""
235
237
        if backing_server is not None:
236
 
            self.backing_transport = transport.get_transport(
 
238
            self.backing_transport = transport.get_transport_from_url(
237
239
                backing_server.get_url())
238
240
        else:
239
 
            self.backing_transport = transport.get_transport('.')
 
241
            self.backing_transport = transport.get_transport_from_path('.')
240
242
        super(TestingChrootServer, self).start_server()
241
243
 
242
244
    def get_bogus_url(self):
265
267
            #raise AssertionError('thread %s hung' % (self.name,))
266
268
 
267
269
 
268
 
class TestingTCPServerMixin:
 
270
class TestingTCPServerMixin(object):
269
271
    """Mixin to support running SocketServer.TCPServer in a thread.
270
272
 
271
273
    Tests are connecting from the main thread, the server has to be run in a
311
313
                self.process_request(request, client_address)
312
314
            except:
313
315
                self.handle_error(request, client_address)
314
 
                self.close_request(request)
 
316
        else:
 
317
            self.close_request(request)
315
318
 
316
319
    def get_request(self):
317
320
        return self.socket.accept()
331
334
        # The following can be used for debugging purposes, it will display the
332
335
        # exception and the traceback just when it occurs instead of waiting
333
336
        # for the thread to be joined.
334
 
 
335
337
        # SocketServer.BaseServer.handle_error(self, request, client_address)
 
338
 
 
339
        # We call close_request manually, because we are going to raise an
 
340
        # exception. The SocketServer implementation calls:
 
341
        #   handle_error(...)
 
342
        #   close_request(...)
 
343
        # But because we raise the exception, close_request will never be
 
344
        # triggered. This helps client not block waiting for a response when
 
345
        # the server gets an exception.
 
346
        self.close_request(request)
336
347
        raise
337
348
 
338
349
    def ignored_exceptions_during_shutdown(self, e):
418
429
        SocketServer.ThreadingTCPServer.__init__(self, server_address,
419
430
                                                 request_handler_class)
420
431
 
421
 
    def get_request (self):
 
432
    def get_request(self):
422
433
        """Get the request and client address from the socket."""
423
434
        sock, addr = TestingTCPServerMixin.get_request(self)
424
 
        # The thread is not create yet, it will be updated in process_request
 
435
        # The thread is not created yet, it will be updated in process_request
425
436
        self.clients.append((sock, addr, None))
426
437
        return sock, addr
427
438
 
428
 
    def process_request_thread(self, started, stopped, request, client_address):
 
439
    def process_request_thread(self, started, detached, stopped,
 
440
                               request, client_address):
429
441
        started.set()
 
442
        # We will be on our own once the server tells us we're detached
 
443
        detached.wait()
430
444
        SocketServer.ThreadingTCPServer.process_request_thread(
431
445
            self, request, client_address)
432
446
        self.close_request(request)
435
449
    def process_request(self, request, client_address):
436
450
        """Start a new thread to process the request."""
437
451
        started = threading.Event()
 
452
        detached = threading.Event()
438
453
        stopped = threading.Event()
439
454
        t = TestThread(
440
455
            sync_event=stopped,
441
456
            name='%s -> %s' % (client_address, self.server_address),
442
457
            target = self.process_request_thread,
443
 
            args = (started, stopped, request, client_address))
 
458
            args = (started, detached, stopped, request, client_address))
444
459
        # Update the client description
445
460
        self.clients.pop()
446
461
        self.clients.append((request, client_address, t))
449
464
        t.set_ignored_exceptions(self.ignored_exceptions)
450
465
        t.start()
451
466
        started.wait()
452
 
        if debug_threads():
453
 
            sys.stderr.write('Client thread %s started\n' % (t.name,))
454
467
        # If an exception occured during the thread start, it will get raised.
455
 
        # In rare cases, an exception raised during the request processing may
456
 
        # also get caught here (see http://pad.lv/869366)
457
468
        t.pending_exception()
 
469
        if debug_threads():
 
470
            sys.stderr.write('Client thread %s started\n' % (t.name,))
 
471
        # Tell the thread, it's now on its own for exception handling.
 
472
        detached.set()
458
473
 
459
474
    # The following methods are called by the main thread
460
475
 
590
605
    def __init__(self, request, client_address, server):
591
606
        medium.SmartServerSocketStreamMedium.__init__(
592
607
            self, request, server.backing_transport,
593
 
            server.root_client_path)
 
608
            server.root_client_path,
 
609
            timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
594
610
        request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
595
611
        SocketServer.BaseRequestHandler.__init__(self, request, client_address,
596
612
                                                 server)
597
613
 
598
614
    def handle(self):
599
 
        while not self.finished:
600
 
            server_protocol = self._build_protocol()
601
 
            self._serve_one_request(server_protocol)
602
 
 
 
615
        try:
 
616
            while not self.finished:
 
617
                server_protocol = self._build_protocol()
 
618
                self._serve_one_request(server_protocol)
 
619
        except errors.ConnectionTimeout:
 
620
            # idle connections aren't considered a failure of the server
 
621
            return
 
622
 
 
623
 
 
624
_DEFAULT_TESTING_CLIENT_TIMEOUT = 60.0
603
625
 
604
626
class TestingSmartServer(TestingThreadingTCPServer, server.SmartTCPServer):
605
627
 
608
630
        TestingThreadingTCPServer.__init__(self, server_address,
609
631
                                           request_handler_class)
610
632
        server.SmartTCPServer.__init__(self, backing_transport,
611
 
                                       root_client_path)
 
633
            root_client_path, client_timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
 
634
 
612
635
    def serve(self):
613
636
        self.run_server_started_hooks()
614
637
        try:
666
689
        self.chroot_server = ChrootServer(
667
690
            self.get_backing_transport(backing_transport_server))
668
691
        self.chroot_server.start_server()
669
 
        self.backing_transport = transport.get_transport(
 
692
        self.backing_transport = transport.get_transport_from_url(
670
693
            self.chroot_server.get_url())
671
694
        super(SmartTCPServer_for_testing, self).start_server()
672
695
 
678
701
 
679
702
    def get_backing_transport(self, backing_transport_server):
680
703
        """Get a backing transport from a server we are decorating."""
681
 
        return transport.get_transport(backing_transport_server.get_url())
 
704
        return transport.get_transport_from_url(
 
705
            backing_transport_server.get_url())
682
706
 
683
707
    def get_url(self):
684
708
        url = self.server.get_url()
695
719
    def get_backing_transport(self, backing_transport_server):
696
720
        """Get a backing transport from a server we are decorating."""
697
721
        url = 'readonly+' + backing_transport_server.get_url()
698
 
        return transport.get_transport(url)
 
722
        return transport.get_transport_from_url(url)
699
723
 
700
724
 
701
725
class SmartTCPServer_for_testing_v2_only(SmartTCPServer_for_testing):
716
740
    def get_backing_transport(self, backing_transport_server):
717
741
        """Get a backing transport from a server we are decorating."""
718
742
        url = 'readonly+' + backing_transport_server.get_url()
719
 
        return transport.get_transport(url)
 
743
        return transport.get_transport_from_url(url)