~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/http_server.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-03-18 09:13:28 UTC
  • mfrom: (5096.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100318091328-8fo347hq4at1usky
(vila) Get better feedback about why
        TestGetFileMTime.test_get_file_mtime is failing

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import errno
18
18
import httplib
20
20
import posixpath
21
21
import random
22
22
import re
 
23
import select
23
24
import SimpleHTTPServer
24
25
import socket
25
26
import SocketServer
30
31
import urlparse
31
32
 
32
33
from bzrlib import transport
 
34
from bzrlib.tests import test_server
33
35
from bzrlib.transport import local
34
36
 
35
37
 
36
 
class WebserverNotAvailable(Exception):
37
 
    pass
38
 
 
39
 
 
40
38
class BadWebserverPath(ValueError):
41
39
    def __str__(self):
42
40
        return 'path %s is not in %s' % self.args
140
138
            # common)
141
139
            self.send_response(301)
142
140
            self.send_header("Location", self.path + "/")
143
 
            # Indicates that the body is empty for HTTP/1.1 clients 
 
141
            # Indicates that the body is empty for HTTP/1.1 clients
144
142
            self.send_header('Content-Length', '0')
145
143
            self.end_headers()
146
144
            return None
180
178
            content_length += self._header_line_length(
181
179
                'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
182
180
            content_length += len('\r\n') # end headers
183
 
            content_length += end - start # + 1
 
181
            content_length += end - start + 1
184
182
        content_length += len(boundary_line)
185
183
        self.send_header('Content-length', content_length)
186
184
        self.end_headers()
321
319
        self.test_case_server = test_case_server
322
320
        self._home_dir = test_case_server._home_dir
323
321
 
324
 
    def tearDown(self):
 
322
    def stop_server(self):
325
323
         """Called to clean-up the server.
326
 
 
 
324
 
327
325
         Since the server may be (surely is, even) in a blocking listen, we
328
326
         shutdown its socket before closing it.
329
327
         """
346
344
             # WSAENOTCONN (10057) 'Socket is not connected' is harmless on
347
345
             # windows (occurs before the first connection attempt
348
346
             # vila--20071230)
349
 
             if not len(e.args) or e.args[0] != 10057:
 
347
 
 
348
             # 'Socket is not connected' can also occur on OSX, with a
 
349
             # "regular" ENOTCONN (when something went wrong during test case
 
350
             # setup leading to self.setUp() *not* being called but
 
351
             # self.stop_server() still being called -- vila20081106
 
352
             if not len(e.args) or e.args[0] not in (errno.ENOTCONN, 10057):
350
353
                 raise
351
354
         # Let the server properly close the socket
352
355
         self.server_close()
380
383
        # lying around.
381
384
        self.daemon_threads = True
382
385
 
 
386
    def process_request_thread(self, request, client_address):
 
387
        SocketServer.ThreadingTCPServer.process_request_thread(
 
388
            self, request, client_address)
 
389
        # Under some circumstances (as in bug #383920), we need to force the
 
390
        # shutdown as python delays it until gc occur otherwise and the client
 
391
        # may hang.
 
392
        try:
 
393
            # The request process has been completed, the thread is about to
 
394
            # die, let's shutdown the socket if we can.
 
395
            request.shutdown(socket.SHUT_RDWR)
 
396
        except (socket.error, select.error), e:
 
397
            if e[0] in (errno.EBADF, errno.ENOTCONN):
 
398
                # Right, the socket is already down
 
399
                pass
 
400
            else:
 
401
                raise
 
402
 
383
403
 
384
404
class HttpServer(transport.Server):
385
405
    """A test server for http transports.
418
438
        # Allows tests to verify number of GET requests issued
419
439
        self.GET_request_nb = 0
420
440
 
 
441
    def create_httpd(self, serv_cls, rhandler_cls):
 
442
        return serv_cls((self.host, self.port), self.request_handler, self)
 
443
 
 
444
    def __repr__(self):
 
445
        return "%s(%s:%s)" % \
 
446
            (self.__class__.__name__, self.host, self.port)
 
447
 
421
448
    def _get_httpd(self):
422
449
        if self._httpd is None:
423
450
            rhandler = self.request_handler
435
462
            if serv_cls is None:
436
463
                raise httplib.UnknownProtocol(proto_vers)
437
464
            else:
438
 
                self._httpd = serv_cls((self.host, self.port), rhandler, self)
439
 
            host, self.port = self._httpd.socket.getsockname()
 
465
                self._httpd = self.create_httpd(serv_cls, rhandler)
 
466
            self.host, self.port = self._httpd.socket.getsockname()
440
467
        return self._httpd
441
468
 
442
469
    def _http_start(self):
467
494
                httpd.handle_request()
468
495
            except socket.timeout:
469
496
                pass
 
497
            except (socket.error, select.error), e:
 
498
                if (e[0] == errno.EBADF
 
499
                    or (sys.platform == 'win32' and e[0] == 10038)):
 
500
                    # Starting with python-2.6, handle_request may raise socket
 
501
                    # or select exceptions when the server is shut down (as we
 
502
                    # do).
 
503
                    # 10038 = WSAENOTSOCK
 
504
                    # http://msdn.microsoft.com/en-us/library/ms740668%28VS.85%29.aspx
 
505
                    pass
 
506
                else:
 
507
                    raise
470
508
 
471
509
    def _get_remote_url(self, path):
472
510
        path_parts = path.split(os.path.sep)
484
522
        """Capture Server log output."""
485
523
        self.logs.append(format % args)
486
524
 
487
 
    def setUp(self, backing_transport_server=None):
488
 
        """See bzrlib.transport.Server.setUp.
489
 
        
 
525
    def start_server(self, backing_transport_server=None):
 
526
        """See bzrlib.transport.Server.start_server.
 
527
 
490
528
        :param backing_transport_server: The transport that requests over this
491
529
            protocol should be forwarded to. Note that this is currently not
492
530
            supported for HTTP.
493
531
        """
494
532
        # XXX: TODO: make the server back onto vfs_server rather than local
495
533
        # disk.
496
 
        if not (backing_transport_server is None or \
497
 
                isinstance(backing_transport_server, local.LocalURLServer)):
 
534
        if not (backing_transport_server is None
 
535
                or isinstance(backing_transport_server,
 
536
                              test_server.LocalURLServer)):
498
537
            raise AssertionError(
499
538
                "HTTPServer currently assumes local transport, got %s" % \
500
539
                backing_transport_server)
520
559
        self._http_starting.release()
521
560
        self.logs = []
522
561
 
523
 
    def tearDown(self):
524
 
        """See bzrlib.transport.Server.tearDown."""
525
 
        self._httpd.tearDown()
 
562
    def stop_server(self):
 
563
        self._httpd.stop_server()
526
564
        self._http_running = False
527
565
        # We don't need to 'self._http_thread.join()' here since the thread is
528
566
        # a daemonic one and will be garbage collected anyway. Joining just