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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy