1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6236dae4SAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 3*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 4*6236dae4SAndroid Build Coastguard Worker# _ _ ____ _ 5*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 6*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 7*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 8*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 9*6236dae4SAndroid Build Coastguard Worker# 10*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 11*6236dae4SAndroid Build Coastguard Worker# 12*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 13*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 14*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 15*6236dae4SAndroid Build Coastguard Worker# 16*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 17*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 18*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 19*6236dae4SAndroid Build Coastguard Worker# 20*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 22*6236dae4SAndroid Build Coastguard Worker# 23*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 24*6236dae4SAndroid Build Coastguard Worker# 25*6236dae4SAndroid Build Coastguard Worker########################################################################### 26*6236dae4SAndroid Build Coastguard Worker# 27*6236dae4SAndroid Build Coastguard Workerimport logging 28*6236dae4SAndroid Build Coastguard Workerimport os 29*6236dae4SAndroid Build Coastguard Workerimport re 30*6236dae4SAndroid Build Coastguard Workerimport shutil 31*6236dae4SAndroid Build Coastguard Workerimport socket 32*6236dae4SAndroid Build Coastguard Workerimport subprocess 33*6236dae4SAndroid Build Coastguard Workerimport tempfile 34*6236dae4SAndroid Build Coastguard Workerfrom configparser import ConfigParser, ExtendedInterpolation 35*6236dae4SAndroid Build Coastguard Workerfrom typing import Optional 36*6236dae4SAndroid Build Coastguard Worker 37*6236dae4SAndroid Build Coastguard Workerfrom .certs import CertificateSpec, Credentials, TestCA 38*6236dae4SAndroid Build Coastguard Workerfrom .ports import alloc_ports 39*6236dae4SAndroid Build Coastguard Worker 40*6236dae4SAndroid Build Coastguard Worker 41*6236dae4SAndroid Build Coastguard Workerlog = logging.getLogger(__name__) 42*6236dae4SAndroid Build Coastguard Worker 43*6236dae4SAndroid Build Coastguard Worker 44*6236dae4SAndroid Build Coastguard Workerdef init_config_from(conf_path): 45*6236dae4SAndroid Build Coastguard Worker if os.path.isfile(conf_path): 46*6236dae4SAndroid Build Coastguard Worker config = ConfigParser(interpolation=ExtendedInterpolation()) 47*6236dae4SAndroid Build Coastguard Worker config.read(conf_path) 48*6236dae4SAndroid Build Coastguard Worker return config 49*6236dae4SAndroid Build Coastguard Worker return None 50*6236dae4SAndroid Build Coastguard Worker 51*6236dae4SAndroid Build Coastguard Worker 52*6236dae4SAndroid Build Coastguard WorkerTESTS_HTTPD_PATH = os.path.dirname(os.path.dirname(__file__)) 53*6236dae4SAndroid Build Coastguard WorkerTOP_PATH = os.path.join(os.getcwd(), os.path.pardir) 54*6236dae4SAndroid Build Coastguard WorkerDEF_CONFIG = init_config_from(os.path.join(TOP_PATH, 'tests', 'http', 'config.ini')) 55*6236dae4SAndroid Build Coastguard WorkerCURL = os.path.join(TOP_PATH, 'src', 'curl') 56*6236dae4SAndroid Build Coastguard Worker 57*6236dae4SAndroid Build Coastguard Worker 58*6236dae4SAndroid Build Coastguard Workerclass EnvConfig: 59*6236dae4SAndroid Build Coastguard Worker 60*6236dae4SAndroid Build Coastguard Worker def __init__(self): 61*6236dae4SAndroid Build Coastguard Worker self.tests_dir = TESTS_HTTPD_PATH 62*6236dae4SAndroid Build Coastguard Worker self.gen_dir = os.path.join(self.tests_dir, 'gen') 63*6236dae4SAndroid Build Coastguard Worker self.project_dir = os.path.dirname(os.path.dirname(self.tests_dir)) 64*6236dae4SAndroid Build Coastguard Worker self.build_dir = TOP_PATH 65*6236dae4SAndroid Build Coastguard Worker self.config = DEF_CONFIG 66*6236dae4SAndroid Build Coastguard Worker # check cur and its features 67*6236dae4SAndroid Build Coastguard Worker self.curl = CURL 68*6236dae4SAndroid Build Coastguard Worker if 'CURL' in os.environ: 69*6236dae4SAndroid Build Coastguard Worker self.curl = os.environ['CURL'] 70*6236dae4SAndroid Build Coastguard Worker self.curl_props = { 71*6236dae4SAndroid Build Coastguard Worker 'version_string': '', 72*6236dae4SAndroid Build Coastguard Worker 'version': '', 73*6236dae4SAndroid Build Coastguard Worker 'os': '', 74*6236dae4SAndroid Build Coastguard Worker 'fullname': '', 75*6236dae4SAndroid Build Coastguard Worker 'features_string': '', 76*6236dae4SAndroid Build Coastguard Worker 'features': set(), 77*6236dae4SAndroid Build Coastguard Worker 'protocols_string': '', 78*6236dae4SAndroid Build Coastguard Worker 'protocols': set(), 79*6236dae4SAndroid Build Coastguard Worker 'libs': set(), 80*6236dae4SAndroid Build Coastguard Worker 'lib_versions': set(), 81*6236dae4SAndroid Build Coastguard Worker } 82*6236dae4SAndroid Build Coastguard Worker self.curl_is_debug = False 83*6236dae4SAndroid Build Coastguard Worker self.curl_protos = [] 84*6236dae4SAndroid Build Coastguard Worker p = subprocess.run(args=[self.curl, '-V'], 85*6236dae4SAndroid Build Coastguard Worker capture_output=True, text=True) 86*6236dae4SAndroid Build Coastguard Worker if p.returncode != 0: 87*6236dae4SAndroid Build Coastguard Worker raise RuntimeError(f'{self.curl} -V failed with exit code: {p.returncode}') 88*6236dae4SAndroid Build Coastguard Worker if p.stderr.startswith('WARNING:'): 89*6236dae4SAndroid Build Coastguard Worker self.curl_is_debug = True 90*6236dae4SAndroid Build Coastguard Worker for line in p.stdout.splitlines(keepends=False): 91*6236dae4SAndroid Build Coastguard Worker if line.startswith('curl '): 92*6236dae4SAndroid Build Coastguard Worker self.curl_props['version_string'] = line 93*6236dae4SAndroid Build Coastguard Worker m = re.match(r'^curl (?P<version>\S+) (?P<os>\S+) (?P<libs>.*)$', line) 94*6236dae4SAndroid Build Coastguard Worker if m: 95*6236dae4SAndroid Build Coastguard Worker self.curl_props['fullname'] = m.group(0) 96*6236dae4SAndroid Build Coastguard Worker self.curl_props['version'] = m.group('version') 97*6236dae4SAndroid Build Coastguard Worker self.curl_props['os'] = m.group('os') 98*6236dae4SAndroid Build Coastguard Worker self.curl_props['lib_versions'] = { 99*6236dae4SAndroid Build Coastguard Worker lib.lower() for lib in m.group('libs').split(' ') 100*6236dae4SAndroid Build Coastguard Worker } 101*6236dae4SAndroid Build Coastguard Worker self.curl_props['libs'] = { 102*6236dae4SAndroid Build Coastguard Worker re.sub(r'/[a-z0-9.-]*', '', lib) for lib in self.curl_props['lib_versions'] 103*6236dae4SAndroid Build Coastguard Worker } 104*6236dae4SAndroid Build Coastguard Worker if line.startswith('Features: '): 105*6236dae4SAndroid Build Coastguard Worker self.curl_props['features_string'] = line[10:] 106*6236dae4SAndroid Build Coastguard Worker self.curl_props['features'] = { 107*6236dae4SAndroid Build Coastguard Worker feat.lower() for feat in line[10:].split(' ') 108*6236dae4SAndroid Build Coastguard Worker } 109*6236dae4SAndroid Build Coastguard Worker if line.startswith('Protocols: '): 110*6236dae4SAndroid Build Coastguard Worker self.curl_props['protocols_string'] = line[11:] 111*6236dae4SAndroid Build Coastguard Worker self.curl_props['protocols'] = { 112*6236dae4SAndroid Build Coastguard Worker prot.lower() for prot in line[11:].split(' ') 113*6236dae4SAndroid Build Coastguard Worker } 114*6236dae4SAndroid Build Coastguard Worker 115*6236dae4SAndroid Build Coastguard Worker self.ports = alloc_ports(port_specs={ 116*6236dae4SAndroid Build Coastguard Worker 'ftp': socket.SOCK_STREAM, 117*6236dae4SAndroid Build Coastguard Worker 'ftps': socket.SOCK_STREAM, 118*6236dae4SAndroid Build Coastguard Worker 'http': socket.SOCK_STREAM, 119*6236dae4SAndroid Build Coastguard Worker 'https': socket.SOCK_STREAM, 120*6236dae4SAndroid Build Coastguard Worker 'nghttpx_https': socket.SOCK_STREAM, 121*6236dae4SAndroid Build Coastguard Worker 'proxy': socket.SOCK_STREAM, 122*6236dae4SAndroid Build Coastguard Worker 'proxys': socket.SOCK_STREAM, 123*6236dae4SAndroid Build Coastguard Worker 'h2proxys': socket.SOCK_STREAM, 124*6236dae4SAndroid Build Coastguard Worker 'caddy': socket.SOCK_STREAM, 125*6236dae4SAndroid Build Coastguard Worker 'caddys': socket.SOCK_STREAM, 126*6236dae4SAndroid Build Coastguard Worker 'ws': socket.SOCK_STREAM, 127*6236dae4SAndroid Build Coastguard Worker }) 128*6236dae4SAndroid Build Coastguard Worker self.httpd = self.config['httpd']['httpd'] 129*6236dae4SAndroid Build Coastguard Worker self.apachectl = self.config['httpd']['apachectl'] 130*6236dae4SAndroid Build Coastguard Worker self.apxs = self.config['httpd']['apxs'] 131*6236dae4SAndroid Build Coastguard Worker if len(self.apxs) == 0: 132*6236dae4SAndroid Build Coastguard Worker self.apxs = None 133*6236dae4SAndroid Build Coastguard Worker self._httpd_version = None 134*6236dae4SAndroid Build Coastguard Worker 135*6236dae4SAndroid Build Coastguard Worker self.examples_pem = { 136*6236dae4SAndroid Build Coastguard Worker 'key': 'xxx', 137*6236dae4SAndroid Build Coastguard Worker 'cert': 'xxx', 138*6236dae4SAndroid Build Coastguard Worker } 139*6236dae4SAndroid Build Coastguard Worker self.htdocs_dir = os.path.join(self.gen_dir, 'htdocs') 140*6236dae4SAndroid Build Coastguard Worker self.tld = 'http.curl.se' 141*6236dae4SAndroid Build Coastguard Worker self.domain1 = f"one.{self.tld}" 142*6236dae4SAndroid Build Coastguard Worker self.domain1brotli = f"brotli.one.{self.tld}" 143*6236dae4SAndroid Build Coastguard Worker self.domain2 = f"two.{self.tld}" 144*6236dae4SAndroid Build Coastguard Worker self.ftp_domain = f"ftp.{self.tld}" 145*6236dae4SAndroid Build Coastguard Worker self.proxy_domain = f"proxy.{self.tld}" 146*6236dae4SAndroid Build Coastguard Worker self.cert_specs = [ 147*6236dae4SAndroid Build Coastguard Worker CertificateSpec(domains=[self.domain1, self.domain1brotli, 'localhost', '127.0.0.1'], key_type='rsa2048'), 148*6236dae4SAndroid Build Coastguard Worker CertificateSpec(domains=[self.domain2], key_type='rsa2048'), 149*6236dae4SAndroid Build Coastguard Worker CertificateSpec(domains=[self.ftp_domain], key_type='rsa2048'), 150*6236dae4SAndroid Build Coastguard Worker CertificateSpec(domains=[self.proxy_domain, '127.0.0.1'], key_type='rsa2048'), 151*6236dae4SAndroid Build Coastguard Worker CertificateSpec(name="clientsX", sub_specs=[ 152*6236dae4SAndroid Build Coastguard Worker CertificateSpec(name="user1", client=True), 153*6236dae4SAndroid Build Coastguard Worker ]), 154*6236dae4SAndroid Build Coastguard Worker ] 155*6236dae4SAndroid Build Coastguard Worker 156*6236dae4SAndroid Build Coastguard Worker self.nghttpx = self.config['nghttpx']['nghttpx'] 157*6236dae4SAndroid Build Coastguard Worker if len(self.nghttpx.strip()) == 0: 158*6236dae4SAndroid Build Coastguard Worker self.nghttpx = None 159*6236dae4SAndroid Build Coastguard Worker self._nghttpx_version = None 160*6236dae4SAndroid Build Coastguard Worker self.nghttpx_with_h3 = False 161*6236dae4SAndroid Build Coastguard Worker if self.nghttpx is not None: 162*6236dae4SAndroid Build Coastguard Worker p = subprocess.run(args=[self.nghttpx, '-v'], 163*6236dae4SAndroid Build Coastguard Worker capture_output=True, text=True) 164*6236dae4SAndroid Build Coastguard Worker if p.returncode != 0: 165*6236dae4SAndroid Build Coastguard Worker # not a working nghttpx 166*6236dae4SAndroid Build Coastguard Worker self.nghttpx = None 167*6236dae4SAndroid Build Coastguard Worker else: 168*6236dae4SAndroid Build Coastguard Worker self._nghttpx_version = re.sub(r'^nghttpx\s*', '', p.stdout.strip()) 169*6236dae4SAndroid Build Coastguard Worker self.nghttpx_with_h3 = re.match(r'.* nghttp3/.*', p.stdout.strip()) is not None 170*6236dae4SAndroid Build Coastguard Worker log.debug(f'nghttpx -v: {p.stdout}') 171*6236dae4SAndroid Build Coastguard Worker 172*6236dae4SAndroid Build Coastguard Worker self.caddy = self.config['caddy']['caddy'] 173*6236dae4SAndroid Build Coastguard Worker self._caddy_version = None 174*6236dae4SAndroid Build Coastguard Worker if len(self.caddy.strip()) == 0: 175*6236dae4SAndroid Build Coastguard Worker self.caddy = None 176*6236dae4SAndroid Build Coastguard Worker if self.caddy is not None: 177*6236dae4SAndroid Build Coastguard Worker try: 178*6236dae4SAndroid Build Coastguard Worker p = subprocess.run(args=[self.caddy, 'version'], 179*6236dae4SAndroid Build Coastguard Worker capture_output=True, text=True) 180*6236dae4SAndroid Build Coastguard Worker if p.returncode != 0: 181*6236dae4SAndroid Build Coastguard Worker # not a working caddy 182*6236dae4SAndroid Build Coastguard Worker self.caddy = None 183*6236dae4SAndroid Build Coastguard Worker m = re.match(r'v?(\d+\.\d+\.\d+).*', p.stdout) 184*6236dae4SAndroid Build Coastguard Worker if m: 185*6236dae4SAndroid Build Coastguard Worker self._caddy_version = m.group(1) 186*6236dae4SAndroid Build Coastguard Worker else: 187*6236dae4SAndroid Build Coastguard Worker raise RuntimeError(f'Unable to determine cadd version from: {p.stdout}') 188*6236dae4SAndroid Build Coastguard Worker # TODO: specify specific exceptions here 189*6236dae4SAndroid Build Coastguard Worker except: # noqa: E722 190*6236dae4SAndroid Build Coastguard Worker self.caddy = None 191*6236dae4SAndroid Build Coastguard Worker 192*6236dae4SAndroid Build Coastguard Worker self.vsftpd = self.config['vsftpd']['vsftpd'] 193*6236dae4SAndroid Build Coastguard Worker self._vsftpd_version = None 194*6236dae4SAndroid Build Coastguard Worker if self.vsftpd is not None: 195*6236dae4SAndroid Build Coastguard Worker try: 196*6236dae4SAndroid Build Coastguard Worker with tempfile.TemporaryFile('w+') as tmp: 197*6236dae4SAndroid Build Coastguard Worker p = subprocess.run(args=[self.vsftpd, '-v'], 198*6236dae4SAndroid Build Coastguard Worker capture_output=True, text=True, stdin=tmp) 199*6236dae4SAndroid Build Coastguard Worker if p.returncode != 0: 200*6236dae4SAndroid Build Coastguard Worker # not a working vsftpd 201*6236dae4SAndroid Build Coastguard Worker self.vsftpd = None 202*6236dae4SAndroid Build Coastguard Worker if p.stderr: 203*6236dae4SAndroid Build Coastguard Worker ver_text = p.stderr 204*6236dae4SAndroid Build Coastguard Worker else: 205*6236dae4SAndroid Build Coastguard Worker # Oddly, some versions of vsftpd write to stdin (!) 206*6236dae4SAndroid Build Coastguard Worker # instead of stderr, which is odd but works. If there 207*6236dae4SAndroid Build Coastguard Worker # is nothing on stderr, read the file on stdin and use 208*6236dae4SAndroid Build Coastguard Worker # any data there instead. 209*6236dae4SAndroid Build Coastguard Worker tmp.seek(0) 210*6236dae4SAndroid Build Coastguard Worker ver_text = tmp.read() 211*6236dae4SAndroid Build Coastguard Worker m = re.match(r'vsftpd: version (\d+\.\d+\.\d+)', ver_text) 212*6236dae4SAndroid Build Coastguard Worker if m: 213*6236dae4SAndroid Build Coastguard Worker self._vsftpd_version = m.group(1) 214*6236dae4SAndroid Build Coastguard Worker elif len(p.stderr) == 0: 215*6236dae4SAndroid Build Coastguard Worker # vsftp does not use stdout or stderr for printing its version... -.- 216*6236dae4SAndroid Build Coastguard Worker self._vsftpd_version = 'unknown' 217*6236dae4SAndroid Build Coastguard Worker else: 218*6236dae4SAndroid Build Coastguard Worker raise Exception(f'Unable to determine VsFTPD version from: {p.stderr}') 219*6236dae4SAndroid Build Coastguard Worker except Exception: 220*6236dae4SAndroid Build Coastguard Worker self.vsftpd = None 221*6236dae4SAndroid Build Coastguard Worker 222*6236dae4SAndroid Build Coastguard Worker self._tcpdump = shutil.which('tcpdump') 223*6236dae4SAndroid Build Coastguard Worker 224*6236dae4SAndroid Build Coastguard Worker @property 225*6236dae4SAndroid Build Coastguard Worker def httpd_version(self): 226*6236dae4SAndroid Build Coastguard Worker if self._httpd_version is None and self.apxs is not None: 227*6236dae4SAndroid Build Coastguard Worker try: 228*6236dae4SAndroid Build Coastguard Worker p = subprocess.run(args=[self.apxs, '-q', 'HTTPD_VERSION'], 229*6236dae4SAndroid Build Coastguard Worker capture_output=True, text=True) 230*6236dae4SAndroid Build Coastguard Worker if p.returncode != 0: 231*6236dae4SAndroid Build Coastguard Worker log.error(f'{self.apxs} failed to query HTTPD_VERSION: {p}') 232*6236dae4SAndroid Build Coastguard Worker else: 233*6236dae4SAndroid Build Coastguard Worker self._httpd_version = p.stdout.strip() 234*6236dae4SAndroid Build Coastguard Worker except Exception: 235*6236dae4SAndroid Build Coastguard Worker log.exception(f'{self.apxs} failed to run') 236*6236dae4SAndroid Build Coastguard Worker return self._httpd_version 237*6236dae4SAndroid Build Coastguard Worker 238*6236dae4SAndroid Build Coastguard Worker def versiontuple(self, v): 239*6236dae4SAndroid Build Coastguard Worker v = re.sub(r'(\d+\.\d+(\.\d+)?)(-\S+)?', r'\1', v) 240*6236dae4SAndroid Build Coastguard Worker return tuple(map(int, v.split('.'))) 241*6236dae4SAndroid Build Coastguard Worker 242*6236dae4SAndroid Build Coastguard Worker def httpd_is_at_least(self, minv): 243*6236dae4SAndroid Build Coastguard Worker if self.httpd_version is None: 244*6236dae4SAndroid Build Coastguard Worker return False 245*6236dae4SAndroid Build Coastguard Worker hv = self.versiontuple(self.httpd_version) 246*6236dae4SAndroid Build Coastguard Worker return hv >= self.versiontuple(minv) 247*6236dae4SAndroid Build Coastguard Worker 248*6236dae4SAndroid Build Coastguard Worker def caddy_is_at_least(self, minv): 249*6236dae4SAndroid Build Coastguard Worker if self.caddy_version is None: 250*6236dae4SAndroid Build Coastguard Worker return False 251*6236dae4SAndroid Build Coastguard Worker hv = self.versiontuple(self.caddy_version) 252*6236dae4SAndroid Build Coastguard Worker return hv >= self.versiontuple(minv) 253*6236dae4SAndroid Build Coastguard Worker 254*6236dae4SAndroid Build Coastguard Worker def is_complete(self) -> bool: 255*6236dae4SAndroid Build Coastguard Worker return os.path.isfile(self.httpd) and \ 256*6236dae4SAndroid Build Coastguard Worker os.path.isfile(self.apachectl) and \ 257*6236dae4SAndroid Build Coastguard Worker self.apxs is not None and \ 258*6236dae4SAndroid Build Coastguard Worker os.path.isfile(self.apxs) 259*6236dae4SAndroid Build Coastguard Worker 260*6236dae4SAndroid Build Coastguard Worker def get_incomplete_reason(self) -> Optional[str]: 261*6236dae4SAndroid Build Coastguard Worker if self.httpd is None or len(self.httpd.strip()) == 0: 262*6236dae4SAndroid Build Coastguard Worker return 'httpd not configured, see `--with-test-httpd=<path>`' 263*6236dae4SAndroid Build Coastguard Worker if not os.path.isfile(self.httpd): 264*6236dae4SAndroid Build Coastguard Worker return f'httpd ({self.httpd}) not found' 265*6236dae4SAndroid Build Coastguard Worker if not os.path.isfile(self.apachectl): 266*6236dae4SAndroid Build Coastguard Worker return f'apachectl ({self.apachectl}) not found' 267*6236dae4SAndroid Build Coastguard Worker if self.apxs is None: 268*6236dae4SAndroid Build Coastguard Worker return "command apxs not found (commonly provided in apache2-dev)" 269*6236dae4SAndroid Build Coastguard Worker if not os.path.isfile(self.apxs): 270*6236dae4SAndroid Build Coastguard Worker return f"apxs ({self.apxs}) not found" 271*6236dae4SAndroid Build Coastguard Worker return None 272*6236dae4SAndroid Build Coastguard Worker 273*6236dae4SAndroid Build Coastguard Worker @property 274*6236dae4SAndroid Build Coastguard Worker def nghttpx_version(self): 275*6236dae4SAndroid Build Coastguard Worker return self._nghttpx_version 276*6236dae4SAndroid Build Coastguard Worker 277*6236dae4SAndroid Build Coastguard Worker @property 278*6236dae4SAndroid Build Coastguard Worker def caddy_version(self): 279*6236dae4SAndroid Build Coastguard Worker return self._caddy_version 280*6236dae4SAndroid Build Coastguard Worker 281*6236dae4SAndroid Build Coastguard Worker @property 282*6236dae4SAndroid Build Coastguard Worker def vsftpd_version(self): 283*6236dae4SAndroid Build Coastguard Worker return self._vsftpd_version 284*6236dae4SAndroid Build Coastguard Worker 285*6236dae4SAndroid Build Coastguard Worker @property 286*6236dae4SAndroid Build Coastguard Worker def tcpdmp(self) -> Optional[str]: 287*6236dae4SAndroid Build Coastguard Worker return self._tcpdump 288*6236dae4SAndroid Build Coastguard Worker 289*6236dae4SAndroid Build Coastguard Worker 290*6236dae4SAndroid Build Coastguard Workerclass Env: 291*6236dae4SAndroid Build Coastguard Worker 292*6236dae4SAndroid Build Coastguard Worker CONFIG = EnvConfig() 293*6236dae4SAndroid Build Coastguard Worker 294*6236dae4SAndroid Build Coastguard Worker @staticmethod 295*6236dae4SAndroid Build Coastguard Worker def setup_incomplete() -> bool: 296*6236dae4SAndroid Build Coastguard Worker return not Env.CONFIG.is_complete() 297*6236dae4SAndroid Build Coastguard Worker 298*6236dae4SAndroid Build Coastguard Worker @staticmethod 299*6236dae4SAndroid Build Coastguard Worker def incomplete_reason() -> Optional[str]: 300*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.get_incomplete_reason() 301*6236dae4SAndroid Build Coastguard Worker 302*6236dae4SAndroid Build Coastguard Worker @staticmethod 303*6236dae4SAndroid Build Coastguard Worker def have_nghttpx() -> bool: 304*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.nghttpx is not None 305*6236dae4SAndroid Build Coastguard Worker 306*6236dae4SAndroid Build Coastguard Worker @staticmethod 307*6236dae4SAndroid Build Coastguard Worker def have_h3_server() -> bool: 308*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.nghttpx_with_h3 309*6236dae4SAndroid Build Coastguard Worker 310*6236dae4SAndroid Build Coastguard Worker @staticmethod 311*6236dae4SAndroid Build Coastguard Worker def have_ssl_curl() -> bool: 312*6236dae4SAndroid Build Coastguard Worker return Env.curl_has_feature('ssl') or Env.curl_has_feature('multissl') 313*6236dae4SAndroid Build Coastguard Worker 314*6236dae4SAndroid Build Coastguard Worker @staticmethod 315*6236dae4SAndroid Build Coastguard Worker def have_h2_curl() -> bool: 316*6236dae4SAndroid Build Coastguard Worker return 'http2' in Env.CONFIG.curl_props['features'] 317*6236dae4SAndroid Build Coastguard Worker 318*6236dae4SAndroid Build Coastguard Worker @staticmethod 319*6236dae4SAndroid Build Coastguard Worker def have_h3_curl() -> bool: 320*6236dae4SAndroid Build Coastguard Worker return 'http3' in Env.CONFIG.curl_props['features'] 321*6236dae4SAndroid Build Coastguard Worker 322*6236dae4SAndroid Build Coastguard Worker @staticmethod 323*6236dae4SAndroid Build Coastguard Worker def curl_uses_lib(libname: str) -> bool: 324*6236dae4SAndroid Build Coastguard Worker return libname.lower() in Env.CONFIG.curl_props['libs'] 325*6236dae4SAndroid Build Coastguard Worker 326*6236dae4SAndroid Build Coastguard Worker @staticmethod 327*6236dae4SAndroid Build Coastguard Worker def curl_uses_ossl_quic() -> bool: 328*6236dae4SAndroid Build Coastguard Worker if Env.have_h3_curl(): 329*6236dae4SAndroid Build Coastguard Worker return not Env.curl_uses_lib('ngtcp2') and Env.curl_uses_lib('nghttp3') 330*6236dae4SAndroid Build Coastguard Worker return False 331*6236dae4SAndroid Build Coastguard Worker 332*6236dae4SAndroid Build Coastguard Worker @staticmethod 333*6236dae4SAndroid Build Coastguard Worker def curl_version_string() -> str: 334*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['version_string'] 335*6236dae4SAndroid Build Coastguard Worker 336*6236dae4SAndroid Build Coastguard Worker @staticmethod 337*6236dae4SAndroid Build Coastguard Worker def curl_features_string() -> str: 338*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['features_string'] 339*6236dae4SAndroid Build Coastguard Worker 340*6236dae4SAndroid Build Coastguard Worker @staticmethod 341*6236dae4SAndroid Build Coastguard Worker def curl_has_feature(feature: str) -> bool: 342*6236dae4SAndroid Build Coastguard Worker return feature.lower() in Env.CONFIG.curl_props['features'] 343*6236dae4SAndroid Build Coastguard Worker 344*6236dae4SAndroid Build Coastguard Worker @staticmethod 345*6236dae4SAndroid Build Coastguard Worker def curl_protocols_string() -> str: 346*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['protocols_string'] 347*6236dae4SAndroid Build Coastguard Worker 348*6236dae4SAndroid Build Coastguard Worker @staticmethod 349*6236dae4SAndroid Build Coastguard Worker def curl_has_protocol(protocol: str) -> bool: 350*6236dae4SAndroid Build Coastguard Worker return protocol.lower() in Env.CONFIG.curl_props['protocols'] 351*6236dae4SAndroid Build Coastguard Worker 352*6236dae4SAndroid Build Coastguard Worker @staticmethod 353*6236dae4SAndroid Build Coastguard Worker def curl_lib_version(libname: str) -> str: 354*6236dae4SAndroid Build Coastguard Worker prefix = f'{libname.lower()}/' 355*6236dae4SAndroid Build Coastguard Worker for lversion in Env.CONFIG.curl_props['lib_versions']: 356*6236dae4SAndroid Build Coastguard Worker if lversion.startswith(prefix): 357*6236dae4SAndroid Build Coastguard Worker return lversion[len(prefix):] 358*6236dae4SAndroid Build Coastguard Worker return 'unknown' 359*6236dae4SAndroid Build Coastguard Worker 360*6236dae4SAndroid Build Coastguard Worker @staticmethod 361*6236dae4SAndroid Build Coastguard Worker def curl_lib_version_at_least(libname: str, min_version) -> bool: 362*6236dae4SAndroid Build Coastguard Worker lversion = Env.curl_lib_version(libname) 363*6236dae4SAndroid Build Coastguard Worker if lversion != 'unknown': 364*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.versiontuple(min_version) <= \ 365*6236dae4SAndroid Build Coastguard Worker Env.CONFIG.versiontuple(lversion) 366*6236dae4SAndroid Build Coastguard Worker return False 367*6236dae4SAndroid Build Coastguard Worker 368*6236dae4SAndroid Build Coastguard Worker @staticmethod 369*6236dae4SAndroid Build Coastguard Worker def curl_os() -> str: 370*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['os'] 371*6236dae4SAndroid Build Coastguard Worker 372*6236dae4SAndroid Build Coastguard Worker @staticmethod 373*6236dae4SAndroid Build Coastguard Worker def curl_fullname() -> str: 374*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['fullname'] 375*6236dae4SAndroid Build Coastguard Worker 376*6236dae4SAndroid Build Coastguard Worker @staticmethod 377*6236dae4SAndroid Build Coastguard Worker def curl_version() -> str: 378*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_props['version'] 379*6236dae4SAndroid Build Coastguard Worker 380*6236dae4SAndroid Build Coastguard Worker @staticmethod 381*6236dae4SAndroid Build Coastguard Worker def curl_is_debug() -> bool: 382*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.curl_is_debug 383*6236dae4SAndroid Build Coastguard Worker 384*6236dae4SAndroid Build Coastguard Worker @staticmethod 385*6236dae4SAndroid Build Coastguard Worker def have_h3() -> bool: 386*6236dae4SAndroid Build Coastguard Worker return Env.have_h3_curl() and Env.have_h3_server() 387*6236dae4SAndroid Build Coastguard Worker 388*6236dae4SAndroid Build Coastguard Worker @staticmethod 389*6236dae4SAndroid Build Coastguard Worker def httpd_version() -> str: 390*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.httpd_version 391*6236dae4SAndroid Build Coastguard Worker 392*6236dae4SAndroid Build Coastguard Worker @staticmethod 393*6236dae4SAndroid Build Coastguard Worker def nghttpx_version() -> str: 394*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.nghttpx_version 395*6236dae4SAndroid Build Coastguard Worker 396*6236dae4SAndroid Build Coastguard Worker @staticmethod 397*6236dae4SAndroid Build Coastguard Worker def caddy_version() -> str: 398*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.caddy_version 399*6236dae4SAndroid Build Coastguard Worker 400*6236dae4SAndroid Build Coastguard Worker @staticmethod 401*6236dae4SAndroid Build Coastguard Worker def caddy_is_at_least(minv) -> bool: 402*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.caddy_is_at_least(minv) 403*6236dae4SAndroid Build Coastguard Worker 404*6236dae4SAndroid Build Coastguard Worker @staticmethod 405*6236dae4SAndroid Build Coastguard Worker def httpd_is_at_least(minv) -> bool: 406*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.httpd_is_at_least(minv) 407*6236dae4SAndroid Build Coastguard Worker 408*6236dae4SAndroid Build Coastguard Worker @staticmethod 409*6236dae4SAndroid Build Coastguard Worker def has_caddy() -> bool: 410*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.caddy is not None 411*6236dae4SAndroid Build Coastguard Worker 412*6236dae4SAndroid Build Coastguard Worker @staticmethod 413*6236dae4SAndroid Build Coastguard Worker def has_vsftpd() -> bool: 414*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.vsftpd is not None 415*6236dae4SAndroid Build Coastguard Worker 416*6236dae4SAndroid Build Coastguard Worker @staticmethod 417*6236dae4SAndroid Build Coastguard Worker def vsftpd_version() -> str: 418*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.vsftpd_version 419*6236dae4SAndroid Build Coastguard Worker 420*6236dae4SAndroid Build Coastguard Worker @staticmethod 421*6236dae4SAndroid Build Coastguard Worker def tcpdump() -> Optional[str]: 422*6236dae4SAndroid Build Coastguard Worker return Env.CONFIG.tcpdmp 423*6236dae4SAndroid Build Coastguard Worker 424*6236dae4SAndroid Build Coastguard Worker def __init__(self, pytestconfig=None): 425*6236dae4SAndroid Build Coastguard Worker self._verbose = pytestconfig.option.verbose \ 426*6236dae4SAndroid Build Coastguard Worker if pytestconfig is not None else 0 427*6236dae4SAndroid Build Coastguard Worker self._ca = None 428*6236dae4SAndroid Build Coastguard Worker self._test_timeout = 300.0 if self._verbose > 1 else 60.0 # seconds 429*6236dae4SAndroid Build Coastguard Worker 430*6236dae4SAndroid Build Coastguard Worker def issue_certs(self): 431*6236dae4SAndroid Build Coastguard Worker if self._ca is None: 432*6236dae4SAndroid Build Coastguard Worker ca_dir = os.path.join(self.CONFIG.gen_dir, 'ca') 433*6236dae4SAndroid Build Coastguard Worker self._ca = TestCA.create_root(name=self.CONFIG.tld, 434*6236dae4SAndroid Build Coastguard Worker store_dir=ca_dir, 435*6236dae4SAndroid Build Coastguard Worker key_type="rsa2048") 436*6236dae4SAndroid Build Coastguard Worker self._ca.issue_certs(self.CONFIG.cert_specs) 437*6236dae4SAndroid Build Coastguard Worker 438*6236dae4SAndroid Build Coastguard Worker def setup(self): 439*6236dae4SAndroid Build Coastguard Worker os.makedirs(self.gen_dir, exist_ok=True) 440*6236dae4SAndroid Build Coastguard Worker os.makedirs(self.htdocs_dir, exist_ok=True) 441*6236dae4SAndroid Build Coastguard Worker self.issue_certs() 442*6236dae4SAndroid Build Coastguard Worker 443*6236dae4SAndroid Build Coastguard Worker def get_credentials(self, domain) -> Optional[Credentials]: 444*6236dae4SAndroid Build Coastguard Worker creds = self.ca.get_credentials_for_name(domain) 445*6236dae4SAndroid Build Coastguard Worker if len(creds) > 0: 446*6236dae4SAndroid Build Coastguard Worker return creds[0] 447*6236dae4SAndroid Build Coastguard Worker return None 448*6236dae4SAndroid Build Coastguard Worker 449*6236dae4SAndroid Build Coastguard Worker @property 450*6236dae4SAndroid Build Coastguard Worker def verbose(self) -> int: 451*6236dae4SAndroid Build Coastguard Worker return self._verbose 452*6236dae4SAndroid Build Coastguard Worker 453*6236dae4SAndroid Build Coastguard Worker @property 454*6236dae4SAndroid Build Coastguard Worker def test_timeout(self) -> Optional[float]: 455*6236dae4SAndroid Build Coastguard Worker return self._test_timeout 456*6236dae4SAndroid Build Coastguard Worker 457*6236dae4SAndroid Build Coastguard Worker @test_timeout.setter 458*6236dae4SAndroid Build Coastguard Worker def test_timeout(self, val: Optional[float]): 459*6236dae4SAndroid Build Coastguard Worker self._test_timeout = val 460*6236dae4SAndroid Build Coastguard Worker 461*6236dae4SAndroid Build Coastguard Worker @property 462*6236dae4SAndroid Build Coastguard Worker def gen_dir(self) -> str: 463*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.gen_dir 464*6236dae4SAndroid Build Coastguard Worker 465*6236dae4SAndroid Build Coastguard Worker @property 466*6236dae4SAndroid Build Coastguard Worker def project_dir(self) -> str: 467*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.project_dir 468*6236dae4SAndroid Build Coastguard Worker 469*6236dae4SAndroid Build Coastguard Worker @property 470*6236dae4SAndroid Build Coastguard Worker def build_dir(self) -> str: 471*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.build_dir 472*6236dae4SAndroid Build Coastguard Worker 473*6236dae4SAndroid Build Coastguard Worker @property 474*6236dae4SAndroid Build Coastguard Worker def ca(self): 475*6236dae4SAndroid Build Coastguard Worker return self._ca 476*6236dae4SAndroid Build Coastguard Worker 477*6236dae4SAndroid Build Coastguard Worker @property 478*6236dae4SAndroid Build Coastguard Worker def htdocs_dir(self) -> str: 479*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.htdocs_dir 480*6236dae4SAndroid Build Coastguard Worker 481*6236dae4SAndroid Build Coastguard Worker @property 482*6236dae4SAndroid Build Coastguard Worker def tld(self) -> str: 483*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.tld 484*6236dae4SAndroid Build Coastguard Worker 485*6236dae4SAndroid Build Coastguard Worker @property 486*6236dae4SAndroid Build Coastguard Worker def domain1(self) -> str: 487*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.domain1 488*6236dae4SAndroid Build Coastguard Worker 489*6236dae4SAndroid Build Coastguard Worker @property 490*6236dae4SAndroid Build Coastguard Worker def domain1brotli(self) -> str: 491*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.domain1brotli 492*6236dae4SAndroid Build Coastguard Worker 493*6236dae4SAndroid Build Coastguard Worker @property 494*6236dae4SAndroid Build Coastguard Worker def domain2(self) -> str: 495*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.domain2 496*6236dae4SAndroid Build Coastguard Worker 497*6236dae4SAndroid Build Coastguard Worker @property 498*6236dae4SAndroid Build Coastguard Worker def ftp_domain(self) -> str: 499*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ftp_domain 500*6236dae4SAndroid Build Coastguard Worker 501*6236dae4SAndroid Build Coastguard Worker @property 502*6236dae4SAndroid Build Coastguard Worker def proxy_domain(self) -> str: 503*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.proxy_domain 504*6236dae4SAndroid Build Coastguard Worker 505*6236dae4SAndroid Build Coastguard Worker @property 506*6236dae4SAndroid Build Coastguard Worker def http_port(self) -> int: 507*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['http'] 508*6236dae4SAndroid Build Coastguard Worker 509*6236dae4SAndroid Build Coastguard Worker @property 510*6236dae4SAndroid Build Coastguard Worker def https_port(self) -> int: 511*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['https'] 512*6236dae4SAndroid Build Coastguard Worker 513*6236dae4SAndroid Build Coastguard Worker @property 514*6236dae4SAndroid Build Coastguard Worker def nghttpx_https_port(self) -> int: 515*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['nghttpx_https'] 516*6236dae4SAndroid Build Coastguard Worker 517*6236dae4SAndroid Build Coastguard Worker @property 518*6236dae4SAndroid Build Coastguard Worker def h3_port(self) -> int: 519*6236dae4SAndroid Build Coastguard Worker return self.https_port 520*6236dae4SAndroid Build Coastguard Worker 521*6236dae4SAndroid Build Coastguard Worker @property 522*6236dae4SAndroid Build Coastguard Worker def proxy_port(self) -> int: 523*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['proxy'] 524*6236dae4SAndroid Build Coastguard Worker 525*6236dae4SAndroid Build Coastguard Worker @property 526*6236dae4SAndroid Build Coastguard Worker def proxys_port(self) -> int: 527*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['proxys'] 528*6236dae4SAndroid Build Coastguard Worker 529*6236dae4SAndroid Build Coastguard Worker @property 530*6236dae4SAndroid Build Coastguard Worker def ftp_port(self) -> int: 531*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['ftp'] 532*6236dae4SAndroid Build Coastguard Worker 533*6236dae4SAndroid Build Coastguard Worker @property 534*6236dae4SAndroid Build Coastguard Worker def ftps_port(self) -> int: 535*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['ftps'] 536*6236dae4SAndroid Build Coastguard Worker 537*6236dae4SAndroid Build Coastguard Worker @property 538*6236dae4SAndroid Build Coastguard Worker def h2proxys_port(self) -> int: 539*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['h2proxys'] 540*6236dae4SAndroid Build Coastguard Worker 541*6236dae4SAndroid Build Coastguard Worker def pts_port(self, proto: str = 'http/1.1') -> int: 542*6236dae4SAndroid Build Coastguard Worker # proxy tunnel port 543*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['h2proxys' if proto == 'h2' else 'proxys'] 544*6236dae4SAndroid Build Coastguard Worker 545*6236dae4SAndroid Build Coastguard Worker @property 546*6236dae4SAndroid Build Coastguard Worker def caddy(self) -> str: 547*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.caddy 548*6236dae4SAndroid Build Coastguard Worker 549*6236dae4SAndroid Build Coastguard Worker @property 550*6236dae4SAndroid Build Coastguard Worker def caddy_https_port(self) -> int: 551*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['caddys'] 552*6236dae4SAndroid Build Coastguard Worker 553*6236dae4SAndroid Build Coastguard Worker @property 554*6236dae4SAndroid Build Coastguard Worker def caddy_http_port(self) -> int: 555*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['caddy'] 556*6236dae4SAndroid Build Coastguard Worker 557*6236dae4SAndroid Build Coastguard Worker @property 558*6236dae4SAndroid Build Coastguard Worker def vsftpd(self) -> str: 559*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.vsftpd 560*6236dae4SAndroid Build Coastguard Worker 561*6236dae4SAndroid Build Coastguard Worker @property 562*6236dae4SAndroid Build Coastguard Worker def ws_port(self) -> int: 563*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.ports['ws'] 564*6236dae4SAndroid Build Coastguard Worker 565*6236dae4SAndroid Build Coastguard Worker @property 566*6236dae4SAndroid Build Coastguard Worker def curl(self) -> str: 567*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.curl 568*6236dae4SAndroid Build Coastguard Worker 569*6236dae4SAndroid Build Coastguard Worker @property 570*6236dae4SAndroid Build Coastguard Worker def httpd(self) -> str: 571*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.httpd 572*6236dae4SAndroid Build Coastguard Worker 573*6236dae4SAndroid Build Coastguard Worker @property 574*6236dae4SAndroid Build Coastguard Worker def apachectl(self) -> str: 575*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.apachectl 576*6236dae4SAndroid Build Coastguard Worker 577*6236dae4SAndroid Build Coastguard Worker @property 578*6236dae4SAndroid Build Coastguard Worker def apxs(self) -> str: 579*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.apxs 580*6236dae4SAndroid Build Coastguard Worker 581*6236dae4SAndroid Build Coastguard Worker @property 582*6236dae4SAndroid Build Coastguard Worker def nghttpx(self) -> Optional[str]: 583*6236dae4SAndroid Build Coastguard Worker return self.CONFIG.nghttpx 584*6236dae4SAndroid Build Coastguard Worker 585*6236dae4SAndroid Build Coastguard Worker @property 586*6236dae4SAndroid Build Coastguard Worker def slow_network(self) -> bool: 587*6236dae4SAndroid Build Coastguard Worker return "CURL_DBG_SOCK_WBLOCK" in os.environ or \ 588*6236dae4SAndroid Build Coastguard Worker "CURL_DBG_SOCK_WPARTIAL" in os.environ 589*6236dae4SAndroid Build Coastguard Worker 590*6236dae4SAndroid Build Coastguard Worker @property 591*6236dae4SAndroid Build Coastguard Worker def ci_run(self) -> bool: 592*6236dae4SAndroid Build Coastguard Worker return "CURL_CI" in os.environ 593*6236dae4SAndroid Build Coastguard Worker 594*6236dae4SAndroid Build Coastguard Worker def port_for(self, alpn_proto: Optional[str] = None): 595*6236dae4SAndroid Build Coastguard Worker if alpn_proto is None or \ 596*6236dae4SAndroid Build Coastguard Worker alpn_proto in ['h2', 'http/1.1', 'http/1.0', 'http/0.9']: 597*6236dae4SAndroid Build Coastguard Worker return self.https_port 598*6236dae4SAndroid Build Coastguard Worker if alpn_proto in ['h3']: 599*6236dae4SAndroid Build Coastguard Worker return self.h3_port 600*6236dae4SAndroid Build Coastguard Worker return self.http_port 601*6236dae4SAndroid Build Coastguard Worker 602*6236dae4SAndroid Build Coastguard Worker def authority_for(self, domain: str, alpn_proto: Optional[str] = None): 603*6236dae4SAndroid Build Coastguard Worker return f'{domain}:{self.port_for(alpn_proto=alpn_proto)}' 604*6236dae4SAndroid Build Coastguard Worker 605*6236dae4SAndroid Build Coastguard Worker def make_data_file(self, indir: str, fname: str, fsize: int, 606*6236dae4SAndroid Build Coastguard Worker line_length: int = 1024) -> str: 607*6236dae4SAndroid Build Coastguard Worker if line_length < 11: 608*6236dae4SAndroid Build Coastguard Worker raise RuntimeError('line_length less than 11 not supported') 609*6236dae4SAndroid Build Coastguard Worker fpath = os.path.join(indir, fname) 610*6236dae4SAndroid Build Coastguard Worker s10 = "0123456789" 611*6236dae4SAndroid Build Coastguard Worker s = round((line_length / 10) + 1) * s10 612*6236dae4SAndroid Build Coastguard Worker s = s[0:line_length-11] 613*6236dae4SAndroid Build Coastguard Worker with open(fpath, 'w') as fd: 614*6236dae4SAndroid Build Coastguard Worker for i in range(int(fsize / line_length)): 615*6236dae4SAndroid Build Coastguard Worker fd.write(f"{i:09d}-{s}\n") 616*6236dae4SAndroid Build Coastguard Worker remain = int(fsize % line_length) 617*6236dae4SAndroid Build Coastguard Worker if remain != 0: 618*6236dae4SAndroid Build Coastguard Worker i = int(fsize / line_length) + 1 619*6236dae4SAndroid Build Coastguard Worker fd.write(f"{i:09d}-{s}"[0:remain-1] + "\n") 620*6236dae4SAndroid Build Coastguard Worker return fpath 621