Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/test/test_httpservers.py

    r2 r391  
    55"""
    66
    7 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
    8 from SimpleHTTPServer import SimpleHTTPRequestHandler
    9 from CGIHTTPServer import CGIHTTPRequestHandler
    10 
    117import os
    128import sys
     9import re
    1310import base64
    1411import shutil
     
    1613import httplib
    1714import tempfile
    18 import threading
    19 
    2015import unittest
     16import CGIHTTPServer
     17
     18
     19from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
     20from SimpleHTTPServer import SimpleHTTPRequestHandler
     21from CGIHTTPServer import CGIHTTPRequestHandler
     22from StringIO import StringIO
    2123from test import test_support
     24
     25
     26threading = test_support.import_module('threading')
    2227
    2328
     
    2530    def log_message(self, *args):
    2631        # don't write log messages to stderr
     32        pass
     33
     34class SocketlessRequestHandler(SimpleHTTPRequestHandler):
     35    def __init__(self):
     36        self.get_called = False
     37        self.protocol_version = "HTTP/1.1"
     38
     39    def do_GET(self):
     40        self.get_called = True
     41        self.send_response(200)
     42        self.send_header('Content-Type', 'text/html')
     43        self.end_headers()
     44        self.wfile.write(b'<html><body>Data</body></html>\r\n')
     45
     46    def log_message(self, fmt, *args):
    2747        pass
    2848
     
    3353        self.request_handler = request_handler
    3454        self.test_object = test_object
    35         self.test_object.lock.acquire()
    3655
    3756    def run(self):
    3857        self.server = HTTPServer(('', 0), self.request_handler)
    3958        self.test_object.PORT = self.server.socket.getsockname()[1]
    40         self.test_object.lock.release()
     59        self.test_object.server_started.set()
     60        self.test_object = None
    4161        try:
    42             self.server.serve_forever()
     62            self.server.serve_forever(0.05)
    4363        finally:
    4464            self.server.server_close()
     
    5070class BaseTestCase(unittest.TestCase):
    5171    def setUp(self):
    52         self.lock = threading.Lock()
     72        self._threads = test_support.threading_setup()
     73        os.environ = test_support.EnvironmentVarGuard()
     74        self.server_started = threading.Event()
    5375        self.thread = TestServerThread(self, self.request_handler)
    5476        self.thread.start()
    55         self.lock.acquire()
     77        self.server_started.wait()
    5678
    5779    def tearDown(self):
    58         self.lock.release()
    5980        self.thread.stop()
     81        os.environ.__exit__()
     82        test_support.threading_cleanup(*self._threads)
    6083
    6184    def request(self, uri, method='GET', body=None, headers={}):
     
    6386        self.connection.request(method, uri, body, headers)
    6487        return self.connection.getresponse()
     88
     89class BaseHTTPRequestHandlerTestCase(unittest.TestCase):
     90    """Test the functionality of the BaseHTTPServer focussing on
     91    BaseHTTPRequestHandler.
     92    """
     93
     94    HTTPResponseMatch = re.compile('HTTP/1.[0-9]+ 200 OK')
     95
     96    def setUp (self):
     97        self.handler = SocketlessRequestHandler()
     98
     99    def send_typical_request(self, message):
     100        input_msg = StringIO(message)
     101        output = StringIO()
     102        self.handler.rfile = input_msg
     103        self.handler.wfile = output
     104        self.handler.handle_one_request()
     105        output.seek(0)
     106        return output.readlines()
     107
     108    def verify_get_called(self):
     109        self.assertTrue(self.handler.get_called)
     110
     111    def verify_expected_headers(self, headers):
     112        for fieldName in 'Server: ', 'Date: ', 'Content-Type: ':
     113            self.assertEqual(sum(h.startswith(fieldName) for h in headers), 1)
     114
     115    def verify_http_server_response(self, response):
     116        match = self.HTTPResponseMatch.search(response)
     117        self.assertTrue(match is not None)
     118
     119    def test_http_1_1(self):
     120        result = self.send_typical_request('GET / HTTP/1.1\r\n\r\n')
     121        self.verify_http_server_response(result[0])
     122        self.verify_expected_headers(result[1:-1])
     123        self.verify_get_called()
     124        self.assertEqual(result[-1], '<html><body>Data</body></html>\r\n')
     125
     126    def test_http_1_0(self):
     127        result = self.send_typical_request('GET / HTTP/1.0\r\n\r\n')
     128        self.verify_http_server_response(result[0])
     129        self.verify_expected_headers(result[1:-1])
     130        self.verify_get_called()
     131        self.assertEqual(result[-1], '<html><body>Data</body></html>\r\n')
     132
     133    def test_http_0_9(self):
     134        result = self.send_typical_request('GET / HTTP/0.9\r\n\r\n')
     135        self.assertEqual(len(result), 1)
     136        self.assertEqual(result[0], '<html><body>Data</body></html>\r\n')
     137        self.verify_get_called()
     138
     139    def test_with_continue_1_0(self):
     140        result = self.send_typical_request('GET / HTTP/1.0\r\nExpect: 100-continue\r\n\r\n')
     141        self.verify_http_server_response(result[0])
     142        self.verify_expected_headers(result[1:-1])
     143        self.verify_get_called()
     144        self.assertEqual(result[-1], '<html><body>Data</body></html>\r\n')
     145
     146    def test_request_length(self):
     147        # Issue #10714: huge request lines are discarded, to avoid Denial
     148        # of Service attacks.
     149        result = self.send_typical_request(b'GET ' + b'x' * 65537)
     150        self.assertEqual(result[0], b'HTTP/1.1 414 Request-URI Too Long\r\n')
     151        self.assertFalse(self.handler.get_called)
    65152
    66153
     
    99186        self.con.request('GET', '/')
    100187        res = self.con.getresponse()
    101         self.assertEquals(res.status, 501)
     188        self.assertEqual(res.status, 501)
    102189
    103190    def test_request_line_trimming(self):
     
    106193        self.con.endheaders()
    107194        res = self.con.getresponse()
    108         self.assertEquals(res.status, 501)
     195        self.assertEqual(res.status, 501)
    109196
    110197    def test_version_bogus(self):
     
    113200        self.con.endheaders()
    114201        res = self.con.getresponse()
    115         self.assertEquals(res.status, 400)
     202        self.assertEqual(res.status, 400)
    116203
    117204    def test_version_digits(self):
     
    120207        self.con.endheaders()
    121208        res = self.con.getresponse()
    122         self.assertEquals(res.status, 400)
     209        self.assertEqual(res.status, 400)
    123210
    124211    def test_version_none_get(self):
     
    127214        self.con.endheaders()
    128215        res = self.con.getresponse()
    129         self.assertEquals(res.status, 501)
     216        self.assertEqual(res.status, 501)
    130217
    131218    def test_version_none(self):
     
    134221        self.con.endheaders()
    135222        res = self.con.getresponse()
    136         self.assertEquals(res.status, 400)
     223        self.assertEqual(res.status, 400)
    137224
    138225    def test_version_invalid(self):
     
    142229        self.con.endheaders()
    143230        res = self.con.getresponse()
    144         self.assertEquals(res.status, 505)
     231        self.assertEqual(res.status, 505)
    145232
    146233    def test_send_blank(self):
     
    149236        self.con.endheaders()
    150237        res = self.con.getresponse()
    151         self.assertEquals(res.status, 400)
     238        self.assertEqual(res.status, 400)
    152239
    153240    def test_header_close(self):
     
    156243        self.con.endheaders()
    157244        res = self.con.getresponse()
    158         self.assertEquals(res.status, 501)
     245        self.assertEqual(res.status, 501)
    159246
    160247    def test_head_keep_alive(self):
     
    164251        self.con.endheaders()
    165252        res = self.con.getresponse()
    166         self.assertEquals(res.status, 501)
     253        self.assertEqual(res.status, 501)
    167254
    168255    def test_handler(self):
    169256        self.con.request('TEST', '/')
    170257        res = self.con.getresponse()
    171         self.assertEquals(res.status, 204)
     258        self.assertEqual(res.status, 204)
    172259
    173260    def test_return_header_keep_alive(self):
    174261        self.con.request('KEEP', '/')
    175262        res = self.con.getresponse()
    176         self.assertEquals(res.getheader('Connection'), 'keep-alive')
     263        self.assertEqual(res.getheader('Connection'), 'keep-alive')
    177264        self.con.request('TEST', '/')
     265        self.addCleanup(self.con.close)
    178266
    179267    def test_internal_key_error(self):
    180268        self.con.request('KEYERROR', '/')
    181269        res = self.con.getresponse()
    182         self.assertEquals(res.status, 999)
     270        self.assertEqual(res.status, 999)
    183271
    184272    def test_return_custom_status(self):
    185273        self.con.request('CUSTOM', '/')
    186274        res = self.con.getresponse()
    187         self.assertEquals(res.status, 999)
     275        self.assertEqual(res.status, 999)
    188276
    189277
     
    209297            try:
    210298                shutil.rmtree(self.tempdir)
    211             except:
     299            except OSError:
    212300                pass
    213301        finally:
     
    216304    def check_status_and_reason(self, response, status, data=None):
    217305        body = response.read()
    218         self.assert_(response)
    219         self.assertEquals(response.status, status)
    220         self.assert_(response.reason != None)
     306        self.assertTrue(response)
     307        self.assertEqual(response.status, status)
     308        self.assertIsNotNone(response.reason)
    221309        if data:
    222310            self.assertEqual(data, body)
     
    226314        response = self.request(self.tempdir_name + '/test')
    227315        self.check_status_and_reason(response, 200, data=self.data)
     316        # check for trailing "/" which should return 404. See Issue17324
     317        response = self.request(self.tempdir_name + '/test/')
     318        self.check_status_and_reason(response, 404)
    228319        response = self.request(self.tempdir_name + '/')
    229320        self.check_status_and_reason(response, 200)
     
    237328        response = self.request('/' + self.tempdir_name + '/')
    238329        self.check_status_and_reason(response, 200)
    239         if os.name == 'posix':
    240             # chmod won't work as expected on Windows platforms
     330
     331        # chmod() doesn't work as expected on Windows, and filesystem
     332        # permissions are ignored by root on Unix.
     333        if os.name == 'posix' and os.geteuid() != 0:
    241334            os.chmod(self.tempdir, 0)
    242335            response = self.request(self.tempdir_name + '/')
     
    279372
    280373form = cgi.FieldStorage()
    281 print "%%s, %%s, %%s" %% (form.getfirst("spam"), form.getfirst("eggs"),\
    282               form.getfirst("bacon"))
     374print "%%s, %%s, %%s" %% (form.getfirst("spam"), form.getfirst("eggs"),
     375                          form.getfirst("bacon"))
    283376"""
    284377
     378
     379@unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
     380        "This test can't be run reliably as root (issue #13308).")
    285381class CGIHTTPServerTestCase(BaseTestCase):
    286382    class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler):
     
    293389        os.mkdir(self.cgi_dir)
    294390
     391        # The shebang line should be pure ASCII: use symlink if possible.
     392        # See issue #7668.
     393        if hasattr(os, 'symlink'):
     394            self.pythonexe = os.path.join(self.parent_dir, 'python')
     395            os.symlink(sys.executable, self.pythonexe)
     396        else:
     397            self.pythonexe = sys.executable
     398
     399        self.nocgi_path = os.path.join(self.parent_dir, 'nocgi.py')
     400        with open(self.nocgi_path, 'w') as fp:
     401            fp.write(cgi_file1 % self.pythonexe)
     402        os.chmod(self.nocgi_path, 0777)
     403
    295404        self.file1_path = os.path.join(self.cgi_dir, 'file1.py')
    296405        with open(self.file1_path, 'w') as file1:
    297             file1.write(cgi_file1 % sys.executable)
     406            file1.write(cgi_file1 % self.pythonexe)
    298407        os.chmod(self.file1_path, 0777)
    299408
    300409        self.file2_path = os.path.join(self.cgi_dir, 'file2.py')
    301410        with open(self.file2_path, 'w') as file2:
    302             file2.write(cgi_file2 % sys.executable)
     411            file2.write(cgi_file2 % self.pythonexe)
    303412        os.chmod(self.file2_path, 0777)
    304413
     
    309418        try:
    310419            os.chdir(self.cwd)
     420            if self.pythonexe != sys.executable:
     421                os.remove(self.pythonexe)
     422            os.remove(self.nocgi_path)
    311423            os.remove(self.file1_path)
    312424            os.remove(self.file2_path)
     
    316428            BaseTestCase.tearDown(self)
    317429
     430    def test_url_collapse_path(self):
     431        # verify tail is the last portion and head is the rest on proper urls
     432        test_vectors = {
     433            '': '//',
     434            '..': IndexError,
     435            '/.//..': IndexError,
     436            '/': '//',
     437            '//': '//',
     438            '/\\': '//\\',
     439            '/.//': '//',
     440            'cgi-bin/file1.py': '/cgi-bin/file1.py',
     441            '/cgi-bin/file1.py': '/cgi-bin/file1.py',
     442            'a': '//a',
     443            '/a': '//a',
     444            '//a': '//a',
     445            './a': '//a',
     446            './C:/': '/C:/',
     447            '/a/b': '/a/b',
     448            '/a/b/': '/a/b/',
     449            '/a/b/.': '/a/b/',
     450            '/a/b/c/..': '/a/b/',
     451            '/a/b/c/../d': '/a/b/d',
     452            '/a/b/c/../d/e/../f': '/a/b/d/f',
     453            '/a/b/c/../d/e/../../f': '/a/b/f',
     454            '/a/b/c/../d/e/.././././..//f': '/a/b/f',
     455            '../a/b/c/../d/e/.././././..//f': IndexError,
     456            '/a/b/c/../d/e/../../../f': '/a/f',
     457            '/a/b/c/../d/e/../../../../f': '//f',
     458            '/a/b/c/../d/e/../../../../../f': IndexError,
     459            '/a/b/c/../d/e/../../../../f/..': '//',
     460            '/a/b/c/../d/e/../../../../f/../.': '//',
     461        }
     462        for path, expected in test_vectors.iteritems():
     463            if isinstance(expected, type) and issubclass(expected, Exception):
     464                self.assertRaises(expected,
     465                                  CGIHTTPServer._url_collapse_path, path)
     466            else:
     467                actual = CGIHTTPServer._url_collapse_path(path)
     468                self.assertEqual(expected, actual,
     469                                 msg='path = %r\nGot:    %r\nWanted: %r' %
     470                                 (path, actual, expected))
     471
    318472    def test_headers_and_content(self):
    319473        res = self.request('/cgi-bin/file1.py')
    320         self.assertEquals(('Hello World\n', 'text/html', 200), \
    321              (res.read(), res.getheader('Content-type'), res.status))
     474        self.assertEqual(('Hello World\n', 'text/html', 200),
     475            (res.read(), res.getheader('Content-type'), res.status))
     476
     477    def test_issue19435(self):
     478        res = self.request('///////////nocgi.py/../cgi-bin/nothere.sh')
     479        self.assertEqual(res.status, 404)
    322480
    323481    def test_post(self):
     
    326484        res = self.request('/cgi-bin/file2.py', 'POST', params, headers)
    327485
    328         self.assertEquals(res.read(), '1, python, 123456\n')
     486        self.assertEqual(res.read(), '1, python, 123456\n')
    329487
    330488    def test_invaliduri(self):
    331489        res = self.request('/cgi-bin/invalid')
    332490        res.read()
    333         self.assertEquals(res.status, 404)
     491        self.assertEqual(res.status, 404)
    334492
    335493    def test_authorization(self):
    336         headers = {'Authorization' : 'Basic %s' % \
    337                 base64.b64encode('username:pass')}
     494        headers = {'Authorization' : 'Basic %s' %
     495                   base64.b64encode('username:pass')}
    338496        res = self.request('/cgi-bin/file1.py', 'GET', headers=headers)
    339         self.assertEquals(('Hello World\n', 'text/html', 200), \
     497        self.assertEqual(('Hello World\n', 'text/html', 200),
     498                (res.read(), res.getheader('Content-type'), res.status))
     499
     500    def test_no_leading_slash(self):
     501        # http://bugs.python.org/issue2254
     502        res = self.request('cgi-bin/file1.py')
     503        self.assertEqual(('Hello World\n', 'text/html', 200),
    340504             (res.read(), res.getheader('Content-type'), res.status))
    341505
     506    def test_os_environ_is_not_altered(self):
     507        signature = "Test CGI Server"
     508        os.environ['SERVER_SOFTWARE'] = signature
     509        res = self.request('/cgi-bin/file1.py')
     510        self.assertEqual((b'Hello World\n', 'text/html', 200),
     511                (res.read(), res.getheader('Content-type'), res.status))
     512        self.assertEqual(os.environ['SERVER_SOFTWARE'], signature)
     513
     514
     515class SimpleHTTPRequestHandlerTestCase(unittest.TestCase):
     516    """ Test url parsing """
     517    def setUp(self):
     518        self.translated = os.getcwd()
     519        self.translated = os.path.join(self.translated, 'filename')
     520        self.handler = SocketlessRequestHandler()
     521
     522    def test_query_arguments(self):
     523        path = self.handler.translate_path('/filename')
     524        self.assertEqual(path, self.translated)
     525        path = self.handler.translate_path('/filename?foo=bar')
     526        self.assertEqual(path, self.translated)
     527        path = self.handler.translate_path('/filename?a=b&spam=eggs#zot')
     528        self.assertEqual(path, self.translated)
     529
     530    def test_start_with_double_slash(self):
     531        path = self.handler.translate_path('//filename')
     532        self.assertEqual(path, self.translated)
     533        path = self.handler.translate_path('//filename?foo=bar')
     534        self.assertEqual(path, self.translated)
     535
    342536
    343537def test_main(verbose=None):
    344     cwd = os.getcwd()
    345     env = os.environ.copy()
    346538    try:
    347         test_support.run_unittest(BaseHTTPServerTestCase,
     539        cwd = os.getcwd()
     540        test_support.run_unittest(BaseHTTPRequestHandlerTestCase,
     541                                  SimpleHTTPRequestHandlerTestCase,
     542                                  BaseHTTPServerTestCase,
    348543                                  SimpleHTTPServerTestCase,
    349544                                  CGIHTTPServerTestCase
    350                                   )
     545                                 )
    351546    finally:
    352         test_support.reap_children()
    353         os.environ.clear()
    354         os.environ.update(env)
    355547        os.chdir(cwd)
    356548
Note: See TracChangeset for help on using the changeset viewer.