summaryrefslogtreecommitdiffstats
path: root/test/pyhttpd
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2022-09-21 13:03:44 +0200
committerStefan Eissing <icing@apache.org>2022-09-21 13:03:44 +0200
commitcbb10f366c95401b717e26791d31f1d084dee195 (patch)
tree029cf85d2385294f8e87b6ee07c03e8f385382b5 /test/pyhttpd
parent *) mod_proxy_http2: use only the ':authority' header to forward 'Host' (diff)
downloadapache2-cbb10f366c95401b717e26791d31f1d084dee195.tar.xz
apache2-cbb10f366c95401b717e26791d31f1d084dee195.zip
*) tests: load the top-level mod_aptest in all test suites.
- aptest logs the test name from the header 'AP-Test-Name' with the request line. LogLevel aptest:info is switched on. - pytest sets 'AP-Test-Name' for all curl/nghttp invocation against the server. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1904188 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/pyhttpd')
-rw-r--r--test/pyhttpd/env.py52
-rw-r--r--test/pyhttpd/mod_aptest/mod_aptest.c66
-rw-r--r--test/pyhttpd/nghttp.py10
3 files changed, 115 insertions, 13 deletions
diff --git a/test/pyhttpd/env.py b/test/pyhttpd/env.py
index 45f6d2f066..991ead9e11 100644
--- a/test/pyhttpd/env.py
+++ b/test/pyhttpd/env.py
@@ -90,6 +90,7 @@ class HttpdTestSetup:
self.add_modules([self.env.ssl_module])
self._make_modules_conf()
self._make_htdocs()
+ self._add_aptest()
self.env.clear_curl_headerfiles()
def _make_dirs(self):
@@ -179,6 +180,21 @@ class HttpdTestSetup:
st = os.stat(py_file)
os.chmod(py_file, st.st_mode | stat.S_IEXEC)
+ def _add_aptest(self):
+ local_dir = os.path.dirname(inspect.getfile(HttpdTestSetup))
+ p = subprocess.run([self.env.apxs, '-c', 'mod_aptest.c'],
+ capture_output=True,
+ cwd=os.path.join(local_dir, 'mod_aptest'))
+ rv = p.returncode
+ if rv != 0:
+ log.error(f"compiling mod_aptest failed: {p.stderr}")
+ raise Exception(f"compiling mod_aptest failed: {p.stderr}")
+
+ modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
+ with open(modules_conf, 'a') as fd:
+ # load our test module which is not installed
+ fd.write(f"LoadModule aptest_module \"{local_dir}/mod_aptest/.libs/mod_aptest.so\"\n")
+
class HttpdTestEnv:
@@ -255,7 +271,7 @@ class HttpdTestEnv:
self._verbosity = pytestconfig.option.verbose if pytestconfig is not None else 0
self._test_conf = os.path.join(self._server_conf_dir, "test.conf")
self._httpd_base_conf = []
- self._httpd_log_modules = []
+ self._httpd_log_modules = ['aptest']
self._log_interesting = None
self._setup = None
@@ -269,6 +285,8 @@ class HttpdTestEnv:
self._verify_certs = False
self._curl_headerfiles_n = 0
+ self._h2load_version = None
+ self._current_test = None
def add_httpd_conf(self, lines: List[str]):
self._httpd_base_conf.extend(lines)
@@ -403,6 +421,13 @@ class HttpdTestEnv:
return self._ca
@property
+ def current_test_name(self) -> str:
+ return self._current_test
+
+ def set_current_test_name(self, val) -> None:
+ self._current_test = val
+
+ @property
def apachectl_stderr(self):
return self._apachectl_stderr
@@ -416,6 +441,7 @@ class HttpdTestEnv:
return []
def _versiontuple(self, v):
+ v = re.sub(r'(\d+\.\d+(\.\d+)?)(-\S+)?', r'\1', v)
return tuple(map(int, v.split('.')))
def httpd_is_at_least(self, minv):
@@ -428,14 +454,16 @@ class HttpdTestEnv:
def h2load_is_at_least(self, minv):
if not self.has_h2load():
return False
- p = subprocess.run([self._h2load, '--version'], capture_output=True, text=True)
- if p.returncode != 0:
- return False
- s = p.stdout.strip()
- m = re.match(r'h2load nghttp2/(\S+)', s)
- if m:
- hv = self._versiontuple(m.group(1))
- return hv >= self._versiontuple(minv)
+ if self._h2load_version is None:
+ p = subprocess.run([self._h2load, '--version'], capture_output=True, text=True)
+ if p.returncode != 0:
+ return False
+ s = p.stdout.strip()
+ m = re.match(r'h2load nghttp2/(\S+)', s)
+ if m:
+ self._h2load_version = self._versiontuple(m.group(1))
+ if self._h2load_version is not None:
+ return self._h2load_version >= self._versiontuple(minv)
return False
def has_nghttp(self):
@@ -627,6 +655,9 @@ 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):
@@ -739,7 +770,8 @@ class HttpdTestEnv:
return -1
def nghttp(self):
- return Nghttp(self._nghttp, connect_addr=self._httpd_addr, tmp_dir=self.gen_dir)
+ return Nghttp(self._nghttp, connect_addr=self._httpd_addr,
+ tmp_dir=self.gen_dir, test_name=self._current_test)
def h2load_status(self, run: ExecResult):
stats = {}
diff --git a/test/pyhttpd/mod_aptest/mod_aptest.c b/test/pyhttpd/mod_aptest/mod_aptest.c
new file mode 100644
index 0000000000..d1a8e0533d
--- /dev/null
+++ b/test/pyhttpd/mod_aptest/mod_aptest.c
@@ -0,0 +1,66 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <apr_optional.h>
+#include <apr_optional_hooks.h>
+#include <apr_strings.h>
+#include <apr_cstr.h>
+#include <apr_want.h>
+
+#include <httpd.h>
+#include <http_protocol.h>
+#include <http_request.h>
+#include <http_log.h>
+
+static void aptest_hooks(apr_pool_t *pool);
+
+AP_DECLARE_MODULE(aptest) = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* func to create per dir config */
+ NULL, /* func to merge per dir config */
+ NULL, /* func to create per server config */
+ NULL, /* func to merge per server config */
+ NULL, /* command handlers */
+ aptest_hooks,
+#if defined(AP_MODULE_FLAG_NONE)
+ AP_MODULE_FLAG_ALWAYS_MERGE
+#endif
+};
+
+
+static int aptest_post_read_request(request_rec *r)
+{
+ const char *test_name = apr_table_get(r->headers_in, "AP-Test-Name");
+ if (test_name) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "test[%s]: %s",
+ test_name, r->the_request);
+ }
+ return DECLINED;
+}
+
+/* Install this module into the apache2 infrastructure.
+ */
+static void aptest_hooks(apr_pool_t *pool)
+{
+ ap_log_perror(APLOG_MARK, APLOG_TRACE1, 0, pool,
+ "installing hooks and handlers");
+
+ /* test case monitoring */
+ ap_hook_post_read_request(aptest_post_read_request, NULL,
+ NULL, APR_HOOK_MIDDLE);
+
+}
+
diff --git a/test/pyhttpd/nghttp.py b/test/pyhttpd/nghttp.py
index 84b8f20c6f..6dea97b55c 100644
--- a/test/pyhttpd/nghttp.py
+++ b/test/pyhttpd/nghttp.py
@@ -15,10 +15,12 @@ def _get_path(x):
class Nghttp:
- def __init__(self, path, connect_addr=None, tmp_dir="/tmp"):
+ def __init__(self, path, connect_addr=None, tmp_dir="/tmp",
+ test_name: str = None):
self.NGHTTP = path
self.CONNECT_ADDR = connect_addr
self.TMP_DIR = tmp_dir
+ self._test_name = test_name
@staticmethod
def get_stream(streams, sid):
@@ -104,7 +106,7 @@ class Nghttp:
body += m.group(1)
s = self.get_stream(streams, m.group(2))
if s:
- print("stream %d: recv %d header" % (s["id"], len(s["header"])))
+ print("stream %d: recv %d header" % (s["id"], len(s["header"])))
response = s["response"]
hkey = "header"
if "header" in response:
@@ -194,9 +196,11 @@ class Nghttp:
output["response"] = streams[main_stream]["response"]
output["paddings"] = streams[main_stream]["paddings"]
return output
-
+
def _raw(self, url, timeout, options):
args = ["-v"]
+ if self._test_name is not None:
+ args.append(f'--header=AP-Test-Name: {self._test_name}')
if options:
args.extend(options)
r = self._baserun(url, timeout, args)