diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 429d9005bd7605..552fc4068d975d 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -35,7 +35,6 @@ is_apple, import_helper, os_helper, threading_helper ) from test.support.script_helper import kill_python, spawn_python -from test.support.socket_helper import find_unused_port try: import ssl @@ -1472,11 +1471,15 @@ def setUp(self): f.write(self.tls_password.encode()) self.addCleanup(os_helper.unlink, self.tls_password_file) - def fetch_file(self, path): + @unittest.skipIf(ssl is None, "requires ssl") + def get_ssl_context(self): context = ssl.create_default_context() # allow self-signed certificates context.check_hostname = False context.verify_mode = ssl.CERT_NONE + return context + + def fetch_file(self, path, context=None): req = urllib.request.Request(path, method='GET') with urllib.request.urlopen(req, context=context) as res: return res.read() @@ -1487,51 +1490,40 @@ def parse_cli_output(self, output): return None, None, None return matches.group(1), matches.group(2), int(matches.group(3)) - def wait_for_server(self, proc, protocol, port, bind, timeout=50): - """Check the server process output. - - Return True if the server was successfully started - and is listening on the given port and bind address. - """ - while timeout > 0: - line = proc.stdout.readline() - if not line: - time.sleep(0.1) - timeout -= 1 - continue - protocol_, host_, port_ = self.parse_cli_output(line) - if not protocol_ or not host_ or not port_: - time.sleep(0.1) - timeout -= 1 - continue - if protocol_ == protocol and host_ == bind and port_ == port: - return True - break - return False + def wait_for_server(self, proc, protocol): + """Check the server process output.""" + line = proc.stdout.readline() + if line: + if support.verbose > 1: + print(line) + parsed_protocol, host, port = self.parse_cli_output(line) + if protocol == parsed_protocol: + return host, port + return None, None def test_http_client(self): - port = find_unused_port() - bind = '127.0.0.1' - proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind, - bufsize=1, text=True) + proc = spawn_python('-u', '-m', 'http.server', bufsize=1, text=True) self.addCleanup(kill_python, proc) self.addCleanup(proc.terminate) - self.assertTrue(self.wait_for_server(proc, 'http', port, bind)) + bind, port = self.wait_for_server(proc, 'http') + self.assertIsNotNone(bind) + self.assertIsNotNone(port) res = self.fetch_file(f'http://{bind}:{port}/{self.served_file_name}') self.assertEqual(res, self.served_data) def test_https_client(self): - port = find_unused_port() - bind = '127.0.0.1' - proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind, + proc = spawn_python('-u', '-m', 'http.server', '--tls-cert', self.tls_cert, '--tls-key', self.tls_key, '--tls-password-file', self.tls_password_file, bufsize=1, text=True) self.addCleanup(kill_python, proc) self.addCleanup(proc.terminate) - self.assertTrue(self.wait_for_server(proc, 'https', port, bind)) - res = self.fetch_file(f'https://{bind}:{port}/{self.served_file_name}') + bind, port = self.wait_for_server(proc, 'https') + self.assertIsNotNone(bind) + self.assertIsNotNone(port) + url = f'https://{bind}:{port}/{self.served_file_name}' + res = self.fetch_file(url, context=self.get_ssl_context()) self.assertEqual(res, self.served_data)