Content-Length: 421520 | pFad | http://github.com/python/cpython/commit/5d9c8fe3f6168785cb608dddd3010042f39bb226

BA gh-131178: add E2E mockless tests for `http.server` command-line inte… · python/cpython@5d9c8fe · GitHub
Skip to content

Commit 5d9c8fe

Browse files
authored
gh-131178: add E2E mockless tests for http.server command-line interface (#134279)
1 parent 7b1010a commit 5d9c8fe

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

Lib/test/test_httpservers.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import html
2222
import http, http.client
2323
import urllib.parse
24+
import urllib.request
2425
import tempfile
2526
import time
2627
import datetime
@@ -33,6 +34,8 @@
3334
from test.support import (
3435
is_apple, import_helper, os_helper, threading_helper
3536
)
37+
from test.support.script_helper import kill_python, spawn_python
38+
from test.support.socket_helper import find_unused_port
3639

3740
try:
3841
import ssl
@@ -1452,6 +1455,73 @@ def test_unknown_flag(self, _):
14521455
self.assertIn('error', stderr.getvalue())
14531456

14541457

1458+
class CommandLineRunTimeTestCase(unittest.TestCase):
1459+
served_data = os.urandom(32)
1460+
served_filename = 'served_filename'
1461+
tls_cert = certdata_file('ssl_cert.pem')
1462+
tls_key = certdata_file('ssl_key.pem')
1463+
tls_password = b'somepass'
1464+
tls_password_file = 'ssl_key_password'
1465+
1466+
def setUp(self):
1467+
super().setUp()
1468+
server_dir_context = os_helper.temp_cwd()
1469+
server_dir = self.enterContext(server_dir_context)
1470+
with open(self.served_filename, 'wb') as f:
1471+
f.write(self.served_data)
1472+
with open(self.tls_password_file, 'wb') as f:
1473+
f.write(self.tls_password)
1474+
1475+
def fetch_file(self, path, context=None):
1476+
req = urllib.request.Request(path, method='GET')
1477+
with urllib.request.urlopen(req, context=context) as res:
1478+
return res.read()
1479+
1480+
def parse_cli_output(self, output):
1481+
match = re.search(r'Serving (HTTP|HTTPS) on (.+) port (\d+)', output)
1482+
if match is None:
1483+
return None, None, None
1484+
return match.group(1).lower(), match.group(2), int(match.group(3))
1485+
1486+
def wait_for_server(self, proc, protocol, bind, port):
1487+
"""Check that the server has been successfully started."""
1488+
line = proc.stdout.readline().strip()
1489+
if support.verbose:
1490+
print()
1491+
print('python -m http.server: ', line)
1492+
return self.parse_cli_output(line) == (protocol, bind, port)
1493+
1494+
def test_http_client(self):
1495+
bind, port = '127.0.0.1', find_unused_port()
1496+
proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind,
1497+
bufsize=1, text=True)
1498+
self.addCleanup(kill_python, proc)
1499+
self.addCleanup(proc.terminate)
1500+
self.assertTrue(self.wait_for_server(proc, 'http', bind, port))
1501+
res = self.fetch_file(f'http://{bind}:{port}/{self.served_filename}')
1502+
self.assertEqual(res, self.served_data)
1503+
1504+
@unittest.skipIf(ssl is None, "requires ssl")
1505+
def test_https_client(self):
1506+
context = ssl.create_default_context()
1507+
# allow self-signed certificates
1508+
context.check_hostname = False
1509+
context.verify_mode = ssl.CERT_NONE
1510+
1511+
bind, port = '127.0.0.1', find_unused_port()
1512+
proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind,
1513+
'--tls-cert', self.tls_cert,
1514+
'--tls-key', self.tls_key,
1515+
'--tls-password-file', self.tls_password_file,
1516+
bufsize=1, text=True)
1517+
self.addCleanup(kill_python, proc)
1518+
self.addCleanup(proc.terminate)
1519+
self.assertTrue(self.wait_for_server(proc, 'https', bind, port))
1520+
url = f'https://{bind}:{port}/{self.served_filename}'
1521+
res = self.fetch_file(url, context=context)
1522+
self.assertEqual(res, self.served_data)
1523+
1524+
14551525
def setUpModule():
14561526
unittest.addModuleCleanup(os.chdir, os.getcwd())
14571527

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/python/cpython/commit/5d9c8fe3f6168785cb608dddd3010042f39bb226

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy