diff options
Diffstat (limited to '')
-rw-r--r-- | test/pyhttpd/env.py | 143 |
1 files changed, 119 insertions, 24 deletions
diff --git a/test/pyhttpd/env.py b/test/pyhttpd/env.py index af856ef..1d4e8b1 100644 --- a/test/pyhttpd/env.py +++ b/test/pyhttpd/env.py @@ -65,6 +65,8 @@ class HttpdTestSetup: "proxy_http", ] + CURL_STDOUT_SEPARATOR = "===CURL_STDOUT_SEPARATOR===" + def __init__(self, env: 'HttpdTestEnv'): self.env = env self._source_dirs = [os.path.dirname(inspect.getfile(HttpdTestSetup))] @@ -94,9 +96,8 @@ class HttpdTestSetup: self.env.clear_curl_headerfiles() def _make_dirs(self): - if os.path.exists(self.env.gen_dir): - shutil.rmtree(self.env.gen_dir) - os.makedirs(self.env.gen_dir) + if not os.path.exists(self.env.gen_dir): + os.makedirs(self.env.gen_dir) if not os.path.exists(self.env.server_logs_dir): os.makedirs(self.env.server_logs_dir) @@ -236,6 +237,8 @@ class HttpdTestEnv: if HttpdTestEnv.LIBEXEC_DIR is None: HttpdTestEnv.LIBEXEC_DIR = self._libexec_dir = self.get_apxs_var('LIBEXECDIR') self._curl = self.config.get('global', 'curl_bin') + if 'CURL' in os.environ: + self._curl = os.environ['CURL'] self._nghttp = self.config.get('global', 'nghttp') if self._nghttp is None: self._nghttp = 'nghttp' @@ -247,8 +250,10 @@ class HttpdTestEnv: self._http_port2 = int(self.config.get('test', 'http_port2')) self._https_port = int(self.config.get('test', 'https_port')) self._proxy_port = int(self.config.get('test', 'proxy_port')) + self._ws_port = int(self.config.get('test', 'ws_port')) self._http_tld = self.config.get('test', 'http_tld') self._test_dir = self.config.get('test', 'test_dir') + self._clients_dir = os.path.join(os.path.dirname(self._test_dir), 'clients') self._gen_dir = self.config.get('test', 'gen_dir') self._server_dir = os.path.join(self._gen_dir, 'apache') self._server_conf_dir = os.path.join(self._server_dir, "conf") @@ -286,6 +291,7 @@ class HttpdTestEnv: self._verify_certs = False self._curl_headerfiles_n = 0 + self._curl_version = None self._h2load_version = None self._current_test = None @@ -319,6 +325,10 @@ class HttpdTestEnv: self._log_interesting += f" {name}:{log_level}" @property + def curl(self) -> str: + return self._curl + + @property def apxs(self) -> str: return self._apxs @@ -359,6 +369,10 @@ class HttpdTestEnv: return self._proxy_port @property + def ws_port(self) -> int: + return self._ws_port + + @property def http_tld(self) -> str: return self._http_tld @@ -383,6 +397,10 @@ class HttpdTestEnv: return self._test_dir @property + def clients_dir(self) -> str: + return self._clients_dir + + @property def server_dir(self) -> str: return self._server_dir @@ -471,6 +489,34 @@ class HttpdTestEnv: return self._h2load_version >= self._versiontuple(minv) return False + def curl_is_at_least(self, minv): + if self._curl_version is None: + p = subprocess.run([self._curl, '-V'], capture_output=True, text=True) + if p.returncode != 0: + return False + for l in p.stdout.splitlines(): + m = re.match(r'curl ([0-9.]+)[- ].*', l) + if m: + self._curl_version = self._versiontuple(m.group(1)) + break + if self._curl_version is not None: + return self._curl_version >= self._versiontuple(minv) + return False + + def curl_is_less_than(self, version): + if self._curl_version is None: + p = subprocess.run([self._curl, '-V'], capture_output=True, text=True) + if p.returncode != 0: + return False + for l in p.stdout.splitlines(): + m = re.match(r'curl ([0-9.]+)[- ].*', l) + if m: + self._curl_version = self._versiontuple(m.group(1)) + break + if self._curl_version is not None: + return self._curl_version < self._versiontuple(version) + return False + def has_nghttp(self): return self._nghttp != "" @@ -497,14 +543,28 @@ class HttpdTestEnv: if not os.path.exists(path): return os.makedirs(path) - def run(self, args, intext=None, debug_log=True): + def run(self, args, stdout_list=False, intext=None, inbytes=None, debug_log=True): if debug_log: log.debug(f"run: {args}") start = datetime.now() + if intext is not None: + inbytes = intext.encode() p = subprocess.run(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, - input=intext.encode() if intext else None) + input=inbytes) + stdout_as_list = None + if stdout_list: + try: + out = p.stdout.decode() + if HttpdTestSetup.CURL_STDOUT_SEPARATOR in out: + stdout_as_list = out.split(HttpdTestSetup.CURL_STDOUT_SEPARATOR) + if not stdout_as_list[len(stdout_as_list) - 1]: + stdout_as_list.pop() + p.stdout.replace(HttpdTestSetup.CURL_STDOUT_SEPARATOR.encode(), b'') + except: + pass return ExecResult(args=args, exit_code=p.returncode, stdout=p.stdout, stderr=p.stderr, + stdout_as_list=stdout_as_list, duration=datetime.now() - start) def mkurl(self, scheme, hostname, path='/'): @@ -515,8 +575,13 @@ class HttpdTestEnv: with open(self._test_conf, 'w') as fd: fd.write('\n'.join(self._httpd_base_conf)) fd.write('\n') + fd.write(f"CoreDumpDirectory {self._server_dir}\n") if self._verbosity >= 2: - fd.write(f"LogLevel core:trace5 {self.mpm_module}:trace5\n") + fd.write(f"LogLevel core:trace5 {self.mpm_module}:trace5 http:trace5\n") + if self._verbosity >= 3: + fd.write(f"LogLevel dumpio:trace7\n") + fd.write(f"DumpIoOutput on\n") + fd.write(f"DumpIoInput on\n") if self._log_interesting: fd.write(self._log_interesting) fd.write('\n\n') @@ -637,17 +702,10 @@ class HttpdTestEnv: os.remove(os.path.join(self.gen_dir, fname)) self._curl_headerfiles_n = 0 - def curl_complete_args(self, urls, timeout=None, options=None, - insecure=False, force_resolve=True): - if not isinstance(urls, list): - urls = [urls] - u = urlparse(urls[0]) - #assert u.hostname, f"hostname not in url: {urls[0]}" - headerfile = f"{self.gen_dir}/curl.headers.{self._curl_headerfiles_n}" - self._curl_headerfiles_n += 1 + def curl_resolve_args(self, url, insecure=False, force_resolve=True, options=None): + u = urlparse(url) args = [ - self._curl, "-s", "--path-as-is", "-D", headerfile, ] if u.scheme == 'http': pass @@ -660,19 +718,33 @@ class HttpdTestEnv: if ca_pem: args.extend(["--cacert", ca_pem]) - if self._current_test is not None: - args.extend(["-H", f'AP-Test-Name: {self._current_test}']) - if force_resolve and u.hostname and u.hostname != 'localhost' \ and u.hostname != self._httpd_addr \ and not re.match(r'^(\d+|\[|:).*', u.hostname): - assert u.port, f"port not in url: {urls[0]}" + assert u.port, f"port not in url: {url}" args.extend(["--resolve", f"{u.hostname}:{u.port}:{self._httpd_addr}"]) + return args + + def curl_complete_args(self, urls, stdout_list=False, + timeout=None, options=None, + insecure=False, force_resolve=True): + headerfile = f"{self.gen_dir}/curl.headers.{self._curl_headerfiles_n}" + self._curl_headerfiles_n += 1 + + args = [ + self._curl, "-s", "--path-as-is", "-D", headerfile, + ] + args.extend(self.curl_resolve_args(urls[0], insecure=insecure, + force_resolve=force_resolve, + options=options)) + if stdout_list: + args.extend(['-w', '%{stdout}' + HttpdTestSetup.CURL_STDOUT_SEPARATOR]) + if self._current_test is not None: + args.extend(["-H", f'AP-Test-Name: {self._current_test}']) if timeout is not None and int(timeout) > 0: args.extend(["--connect-timeout", str(int(timeout))]) if options: args.extend(options) - args += urls return args, headerfile def curl_parse_headerfile(self, headerfile: str, r: ExecResult = None) -> ExecResult: @@ -730,16 +802,24 @@ class HttpdTestEnv: return r def curl_raw(self, urls, timeout=10, options=None, insecure=False, - force_resolve=True): + force_resolve=True, no_stdout_list=False): + if not isinstance(urls, list): + urls = [urls] + stdout_list = False + if len(urls) > 1 and not no_stdout_list: + stdout_list = True args, headerfile = self.curl_complete_args( - urls=urls, timeout=timeout, options=options, insecure=insecure, + urls=urls, stdout_list=stdout_list, + timeout=timeout, options=options, insecure=insecure, force_resolve=force_resolve) - r = self.run(args) + args += urls + r = self.run(args, stdout_list=stdout_list) if r.exit_code == 0: self.curl_parse_headerfile(headerfile, r=r) if r.json: r.response["json"] = r.json - os.remove(headerfile) + if os.path.isfile(headerfile): + os.remove(headerfile) return r def curl_get(self, url, insecure=False, options=None): @@ -801,3 +881,18 @@ class HttpdTestEnv: } run.add_results({"h2load": stats}) return run + + def make_data_file(self, indir: str, fname: str, fsize: int) -> str: + fpath = os.path.join(indir, fname) + s10 = "0123456789" + s = (101 * s10) + s10[0:3] + with open(fpath, 'w') as fd: + for i in range(int(fsize / 1024)): + fd.write(f"{i:09d}-{s}\n") + remain = int(fsize % 1024) + if remain != 0: + i = int(fsize / 1024) + 1 + s = f"{i:09d}-{s}\n" + fd.write(s[0:remain]) + return fpath + |