summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2021-10-11 14:08:57 +0000
committerStefan Eissing <icing@apache.org>2021-10-11 14:08:57 +0000
commitded853c7cadc6a2b5590a0ceee5cddd0444da17a (patch)
tree2a8d944d77ba160559872ab5365bfe3a8682dccd
parentfa7f3753066ce9f323a217252b3a7798c9324fb7 (diff)
downloadhttpd-ded853c7cadc6a2b5590a0ceee5cddd0444da17a.tar.gz
* test infrastruture:
- moved common pytest code into test/pyhttpd - does basic setup for a list of host names and some htdocs - added modules/core and moved encoding tests from http2 there - all test methods have module name in in prefix now, so to test only core, run > pytest -k test_core git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1894134 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--configure.in5
-rw-r--r--test/.gitignore2
-rw-r--r--test/Makefile.in6
-rw-r--r--test/conftest.py12
-rw-r--r--test/modules/core/__init__.py1
-rw-r--r--test/modules/core/conftest.py39
-rw-r--r--test/modules/core/env.py18
-rw-r--r--test/modules/core/test_001_encoding.py (renamed from test/modules/http2/test_203_encoding.py)28
-rw-r--r--test/modules/http2/Makefile.in20
-rw-r--r--test/modules/http2/__init__.py (renamed from test/modules/http2/htdocs/cgi/files/empty.txt)0
-rw-r--r--test/modules/http2/conftest.py18
-rw-r--r--test/modules/http2/env.py99
-rw-r--r--test/modules/http2/test_000_infra.py17
-rw-r--r--test/modules/http2/test_001_httpd_alive.py21
-rw-r--r--test/modules/http2/test_002_curl_basics.py18
-rw-r--r--test/modules/http2/test_003_get.py34
-rw-r--r--test/modules/http2/test_004_post.py50
-rw-r--r--test/modules/http2/test_005_files.py6
-rw-r--r--test/modules/http2/test_006_assets.py14
-rw-r--r--test/modules/http2/test_100_conn_reuse.py14
-rw-r--r--test/modules/http2/test_101_ssl_reneg.py20
-rw-r--r--test/modules/http2/test_102_require.py8
-rw-r--r--test/modules/http2/test_103_upgrade.py28
-rw-r--r--test/modules/http2/test_104_padding.py23
-rw-r--r--test/modules/http2/test_105_timeout.py28
-rw-r--r--test/modules/http2/test_106_shutdown.py8
-rw-r--r--test/modules/http2/test_200_header_invalid.py32
-rw-r--r--test/modules/http2/test_201_header_conditional.py12
-rw-r--r--test/modules/http2/test_202_trailer.py14
-rw-r--r--test/modules/http2/test_300_interim.py10
-rw-r--r--test/modules/http2/test_400_push.py34
-rw-r--r--test/modules/http2/test_401_early_hints.py8
-rw-r--r--test/modules/http2/test_500_proxy.py24
-rw-r--r--test/modules/http2/test_600_h2proxy.py6
-rw-r--r--test/modules/http2/test_700_load_get.py8
-rw-r--r--test/modules/http2/test_710_load_post_static.py10
-rw-r--r--test/modules/http2/test_711_load_post_cgi.py10
-rw-r--r--test/modules/http2/test_712_buffering.py12
-rw-r--r--test/pyhttpd/__init__.py (renamed from test/modules/http2/htdocs/test1/apache.org-files/cse.js)0
-rw-r--r--test/pyhttpd/certs.py (renamed from test/modules/http2/h2_certs.py)56
-rw-r--r--test/pyhttpd/conf.py (renamed from test/modules/http2/h2_conf.py)32
-rw-r--r--test/pyhttpd/conf/httpd.conf.template (renamed from test/modules/http2/conf/httpd.conf.template)0
-rw-r--r--test/pyhttpd/conf/mime.types (renamed from test/modules/http2/conf/mime.types)0
-rw-r--r--test/pyhttpd/conf/test.conf (renamed from test/modules/http2/conf/test.conf)0
-rw-r--r--test/pyhttpd/config.ini.in (renamed from test/modules/http2/config.ini.in)7
-rw-r--r--test/pyhttpd/curl.py (renamed from test/modules/http2/h2_curl.py)4
-rw-r--r--test/pyhttpd/env.py (renamed from test/modules/http2/h2_env.py)178
-rw-r--r--test/pyhttpd/htdocs/alive.json (renamed from test/modules/http2/htdocs/alive.json)0
-rw-r--r--test/pyhttpd/htdocs/cgi/echo.py (renamed from test/modules/http2/htdocs/cgi/echo.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/echohd.py (renamed from test/modules/http2/htdocs/cgi/echohd.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/env.py (renamed from test/modules/http2/htdocs/cgi/env.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/files/empty.txt (renamed from test/modules/http2/htdocs/test1/apache.org-files/css.css)0
-rw-r--r--test/pyhttpd/htdocs/cgi/hecho.py (renamed from test/modules/http2/htdocs/cgi/hecho.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/hello.py (renamed from test/modules/http2/htdocs/cgi/hello.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/mnot164.py (renamed from test/modules/http2/htdocs/cgi/mnot164.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/necho.py (renamed from test/modules/http2/htdocs/cgi/necho.py)0
-rw-r--r--test/pyhttpd/htdocs/cgi/upload.py (renamed from test/modules/http2/htdocs/cgi/upload.py)0
-rw-r--r--test/pyhttpd/htdocs/forbidden.html (renamed from test/modules/http2/htdocs/forbidden.html)0
-rw-r--r--test/pyhttpd/htdocs/index.html (renamed from test/modules/http2/htdocs/index.html)0
-rw-r--r--test/pyhttpd/htdocs/noh2/alive.json (renamed from test/modules/http2/htdocs/noh2/alive.json)0
-rw-r--r--test/pyhttpd/htdocs/noh2/index.html (renamed from test/modules/http2/htdocs/noh2/index.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/001.html (renamed from test/modules/http2/htdocs/test1/001.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/002.jpg (renamed from test/modules/http2/htdocs/test1/002.jpg)bin90364 -> 90364 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/003.html (renamed from test/modules/http2/htdocs/test1/003.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/003/003_img.jpg (renamed from test/modules/http2/htdocs/test1/003/003_img.jpg)bin90364 -> 90364 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/004.html (renamed from test/modules/http2/htdocs/test1/004.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/004/gophertiles.jpg (renamed from test/modules/http2/htdocs/test1/004/gophertiles.jpg)bin742 -> 742 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/006.html (renamed from test/modules/http2/htdocs/test1/006.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/006/006.css (renamed from test/modules/http2/htdocs/test1/006/006.css)0
-rw-r--r--test/pyhttpd/htdocs/test1/006/006.js (renamed from test/modules/http2/htdocs/test1/006/006.js)0
-rw-r--r--test/pyhttpd/htdocs/test1/006/header.html (renamed from test/modules/http2/htdocs/test1/006/header.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/007.html (renamed from test/modules/http2/htdocs/test1/007.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/007/007.py (renamed from test/modules/http2/htdocs/test1/007/007.py)0
-rw-r--r--test/pyhttpd/htdocs/test1/009.py (renamed from test/modules/http2/htdocs/test1/009.py)0
-rw-r--r--test/pyhttpd/htdocs/test1/alive.json (renamed from test/modules/http2/htdocs/test1/alive.json)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/ant.jpg (renamed from test/modules/http2/htdocs/test1/apache.org-files/ant.jpg)bin6437 -> 6437 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/asf_logo.png (renamed from test/modules/http2/htdocs/test1/apache.org-files/asf_logo.png)bin29982 -> 29982 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js (renamed from test/modules/http2/htdocs/test1/apache.org-files/async-ads.js)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js.br (renamed from test/modules/http2/htdocs/test1/apache.org-files/async-ads.js.br)bin50272 -> 50272 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/cse.js (renamed from test/modules/http2/htdocs/test1/apache.org-files/jsapi.js)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/css.css (renamed from test/modules/http2/htdocs/test2/10%abnormal.txt)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/default.css (renamed from test/modules/http2/htdocs/test1/apache.org-files/default.css)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/defaulten.css (renamed from test/modules/http2/htdocs/test1/apache.org-files/defaulten.css)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/defaulten.js (renamed from test/modules/http2/htdocs/test1/apache.org-files/defaulten.js)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/jquery-2.js (renamed from test/modules/http2/htdocs/test1/apache.org-files/jquery-2.js)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/jsapi.js (renamed from test/modules/http2/htdocs/test2/x%2f.test)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/min.css (renamed from test/modules/http2/htdocs/test1/apache.org-files/min.css)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/min.css.br (renamed from test/modules/http2/htdocs/test1/apache.org-files/min.css.br)bin10116 -> 10116 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/mrunit.jpg (renamed from test/modules/http2/htdocs/test1/apache.org-files/mrunit.jpg)bin4460 -> 4460 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/search_box_icon.png (renamed from test/modules/http2/htdocs/test1/apache.org-files/search_box_icon.png)bin1018 -> 1018 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/small-logo.png (renamed from test/modules/http2/htdocs/test1/apache.org-files/small-logo.png)bin1499 -> 1499 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/styles.css (renamed from test/modules/http2/htdocs/test1/apache.org-files/styles.css)0
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org-files/synapse.jpg (renamed from test/modules/http2/htdocs/test1/apache.org-files/synapse.jpg)bin4396 -> 4396 bytes
-rw-r--r--test/pyhttpd/htdocs/test1/apache.org.html (renamed from test/modules/http2/htdocs/test1/apache.org.html)0
-rw-r--r--test/pyhttpd/htdocs/test1/index.html (renamed from test/modules/http2/htdocs/test1/index.html)0
-rwxr-xr-xtest/pyhttpd/htdocs/test2/006/006.css (renamed from test/modules/http2/htdocs/test2/006/006.css)0
-rw-r--r--test/pyhttpd/htdocs/test2/10%abnormal.txt0
-rw-r--r--test/pyhttpd/htdocs/test2/alive.json (renamed from test/modules/http2/htdocs/test2/alive.json)0
-rw-r--r--test/pyhttpd/htdocs/test2/x%2f.test0
-rw-r--r--test/pyhttpd/nghttp.py (renamed from test/modules/http2/h2_nghttp.py)2
-rw-r--r--test/pyhttpd/result.py (renamed from test/modules/http2/h2_result.py)0
101 files changed, 538 insertions, 458 deletions
diff --git a/configure.in b/configure.in
index ffe9214b8e..ead8329e68 100644
--- a/configure.in
+++ b/configure.in
@@ -994,10 +994,7 @@ APACHE_FAST_OUTPUT(support/Makefile)
if test -d ./test; then
APACHE_FAST_OUTPUT(test/Makefile)
-fi
-if test -d ./test/modules/http2; then
- APACHE_FAST_OUTPUT(test/modules/http2/Makefile)
- AC_CONFIG_FILES([test/modules/http2/config.ini])
+ AC_CONFIG_FILES([test/pyhttpd/config.ini])
fi
dnl ## Finalize the variables
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000000..f8a27a5c56
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,2 @@
+config.ini
+gen
diff --git a/test/Makefile.in b/test/Makefile.in
index 15d404d208..1bfb3e3d7c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -18,3 +18,9 @@ test: $(bin_PROGRAMS)
# dbu_OBJECTS = dbu.lo
# dbu: $(dbu_OBJECTS)
# $(LINK) $(dbu_OBJECTS) $(PROGRAM_LDADD)
+
+clean:
+ rm -rf gen
+
+distclean:
+ rm -f pytest/config.ini \ No newline at end of file
diff --git a/test/conftest.py b/test/conftest.py
new file mode 100644
index 0000000000..b12b1d6d78
--- /dev/null
+++ b/test/conftest.py
@@ -0,0 +1,12 @@
+import sys
+import os
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '.'))
+
+from pyhttpd.env import HttpdTestEnv
+
+def pytest_report_header(config, startdir):
+ env = HttpdTestEnv()
+ return f"[apache httpd: {env.get_httpd_version()}, mpm: {env.mpm_type}, {env.prefix}]"
+
+
diff --git a/test/modules/core/__init__.py b/test/modules/core/__init__.py
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/test/modules/core/__init__.py
@@ -0,0 +1 @@
+
diff --git a/test/modules/core/conftest.py b/test/modules/core/conftest.py
new file mode 100644
index 0000000000..b0be4af5f4
--- /dev/null
+++ b/test/modules/core/conftest.py
@@ -0,0 +1,39 @@
+import logging
+import os
+
+import pytest
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+from .env import CoreTestEnv
+
+
+def pytest_report_header(config, startdir):
+ env = CoreTestEnv(setup_dirs=False)
+ return f"core [apache: {env.get_httpd_version()}, mpm: {env.mpm_type}, {env.prefix}]"
+
+
+@pytest.fixture(scope="module")
+def env(pytestconfig) -> CoreTestEnv:
+ level = logging.INFO
+ console = logging.StreamHandler()
+ console.setLevel(level)
+ console.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
+ logging.getLogger('').addHandler(console)
+ logging.getLogger('').setLevel(level=level)
+ env = CoreTestEnv(pytestconfig=pytestconfig)
+ env.apache_access_log_clear()
+ env.apache_error_log_clear()
+ return env
+
+
+@pytest.fixture(autouse=True, scope="module")
+def _session_scope(env):
+ yield
+ assert env.apache_stop() == 0
+ errors, warnings = env.apache_errors_and_warnings()
+ assert (len(errors), len(warnings)) == (0, 0),\
+ f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
+ "{0}\n{1}\n".format("\n".join(errors), "\n".join(warnings))
+
diff --git a/test/modules/core/env.py b/test/modules/core/env.py
new file mode 100644
index 0000000000..9b09e90c61
--- /dev/null
+++ b/test/modules/core/env.py
@@ -0,0 +1,18 @@
+import inspect
+import logging
+import os
+
+from pyhttpd.env import HttpdTestEnv, HttpdTestSetup
+
+log = logging.getLogger(__name__)
+
+
+class CoreTestEnv(HttpdTestEnv):
+
+ def __init__(self, pytestconfig=None, setup_dirs=True):
+ super().__init__(pytestconfig=pytestconfig,
+ local_dir=os.path.dirname(inspect.getfile(CoreTestEnv)))
+ if setup_dirs:
+ self._setup = HttpdTestSetup(env=self)
+ self._setup.make()
+ self.issue_certs()
diff --git a/test/modules/http2/test_203_encoding.py b/test/modules/core/test_001_encoding.py
index 60d96e0bad..2099d08cf0 100644
--- a/test/modules/http2/test_203_encoding.py
+++ b/test/modules/core/test_001_encoding.py
@@ -1,8 +1,6 @@
-import time
-
import pytest
-from h2_conf import HttpdConf
+from pyhttpd.conf import HttpdConf
class TestEncoding:
@@ -11,17 +9,15 @@ class TestEncoding:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- extras = {
- 'base': f"""
+ conf = HttpdConf(env)
+ conf.add(f"""
<Directory "{env.gen_dir}">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Require all granted
</Directory>
- """,
- }
- conf = HttpdConf(env)
- conf.add_vhost_test1(extras=extras)
+ """)
+ conf.add_vhost_test1()
conf.add_vhost_test2(extras={
f"test2.{env.http_tld}": "AllowEncodedSlashes on",
})
@@ -32,9 +28,10 @@ class TestEncoding:
assert env.apache_restart() == 0
yield
errors, warnings = env.apache_errors_and_warnings()
+ nl = "\n"
assert (len(errors), len(warnings)) == (TestEncoding.EXP_AH10244_ERRS, 0),\
- f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
- "{0}\n{1}\n".format("\n".join(errors), "\n".join(warnings))
+ f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
+ f"{nl.join(errors)}\n{nl.join(warnings)}\n"
env.apache_error_log_clear()
# check handling of url encodings that are accepted
@@ -47,7 +44,7 @@ class TestEncoding:
"/nothing/%2e/%2e%2e/006/006.css",
"/nothing/%2e/%2e%2e/006/006%2ecss",
])
- def test_203_01(self, env, path):
+ def test_core_001_01(self, env, path):
url = env.mkurl("https", "test1", path)
r = env.curl_get(url)
assert r.response["status"] == 200
@@ -62,7 +59,7 @@ class TestEncoding:
"/006/../006/006.css",
"/006/%2e%2e/006/006.css",
])
- def test_203_03(self, env, path):
+ def test_core_001_03(self, env, path):
url = env.mkurl("https", "test1", path)
r = env.curl_get(url)
assert r.response["status"] == 200
@@ -83,7 +80,7 @@ class TestEncoding:
["/nothing/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404],
["/cgi-bin/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404],
])
- def test_203_04(self, env, path, status):
+ def test_core_001_04(self, env, path, status):
url = env.mkurl("https", "cgi", path)
r = env.curl_get(url)
assert r.response["status"] == status
@@ -98,8 +95,7 @@ class TestEncoding:
["test2", "/x%252f.test", 200],
["test2", "/10%25abnormal.txt", 200],
])
- def test_203_20(self, env, host, path, status):
+ def test_core_001_20(self, env, host, path, status):
url = env.mkurl("https", host, path)
r = env.curl_get(url)
assert r.response["status"] == status
-
diff --git a/test/modules/http2/Makefile.in b/test/modules/http2/Makefile.in
deleted file mode 100644
index 15d404d208..0000000000
--- a/test/modules/http2/Makefile.in
+++ /dev/null
@@ -1,20 +0,0 @@
-
-# no targets: we don't want to build anything by default. if you want the
-# test programs, then "make test"
-TARGETS =
-
-bin_PROGRAMS =
-
-PROGRAM_LDADD = $(EXTRA_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(EXTRA_LIBS)
-PROGRAM_DEPENDENCIES = \
- $(top_srcdir)/srclib/apr-util/libaprutil.la \
- $(top_srcdir)/srclib/apr/libapr.la
-
-include $(top_builddir)/build/rules.mk
-
-test: $(bin_PROGRAMS)
-
-# example for building a test proggie
-# dbu_OBJECTS = dbu.lo
-# dbu: $(dbu_OBJECTS)
-# $(LINK) $(dbu_OBJECTS) $(PROGRAM_LDADD)
diff --git a/test/modules/http2/htdocs/cgi/files/empty.txt b/test/modules/http2/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/cgi/files/empty.txt
+++ b/test/modules/http2/__init__.py
diff --git a/test/modules/http2/conftest.py b/test/modules/http2/conftest.py
index 363abae4c2..930cc0ac7c 100644
--- a/test/modules/http2/conftest.py
+++ b/test/modules/http2/conftest.py
@@ -2,9 +2,11 @@ import logging
import os
import pytest
+import sys
-from h2_certs import CertificateSpec, H2TestCA
-from h2_env import H2TestEnv
+sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+from .env import H2TestEnv
def pytest_report_header(config, startdir):
@@ -25,7 +27,7 @@ def pytest_generate_tests(metafunc):
metafunc.parametrize('repeat', range(count))
-@pytest.fixture(scope="session")
+@pytest.fixture(scope="module")
def env(pytestconfig) -> H2TestEnv:
level = logging.INFO
console = logging.StreamHandler()
@@ -34,20 +36,12 @@ def env(pytestconfig) -> H2TestEnv:
logging.getLogger('').addHandler(console)
logging.getLogger('').setLevel(level=level)
env = H2TestEnv(pytestconfig=pytestconfig)
- cert_specs = [
- CertificateSpec(domains=env.domains, key_type='rsa4096'),
- CertificateSpec(domains=env.domains_noh2, key_type='rsa2048'),
- ]
- ca = H2TestCA.create_root(name=env.http_tld,
- store_dir=os.path.join(env.server_dir, 'ca'), key_type="rsa4096")
- ca.issue_certs(cert_specs)
- env.set_ca(ca)
env.apache_access_log_clear()
env.apache_error_log_clear()
return env
-@pytest.fixture(autouse=True, scope="session")
+@pytest.fixture(autouse=True, scope="module")
def _session_scope(env):
yield
assert env.apache_stop() == 0
diff --git a/test/modules/http2/env.py b/test/modules/http2/env.py
new file mode 100644
index 0000000000..6182807486
--- /dev/null
+++ b/test/modules/http2/env.py
@@ -0,0 +1,99 @@
+import inspect
+import logging
+import os
+import subprocess
+
+from pyhttpd.certs import CertificateSpec
+from pyhttpd.conf import HttpdConf
+from pyhttpd.env import HttpdTestEnv, HttpdTestSetup
+
+log = logging.getLogger(__name__)
+
+
+class H2TestSetup(HttpdTestSetup):
+
+ def __init__(self, env: 'HttpdTestEnv'):
+ super().__init__(env=env)
+
+ def make(self):
+ super().make(add_modules=["http2", "proxy_http2"])
+ self._add_h2test()
+
+ def _add_h2test(self):
+ p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'],
+ capture_output=True,
+ cwd=os.path.join(self.env.local_dir, 'mod_h2test'))
+ rv = p.returncode
+ if rv != 0:
+ log.error(f"compiling md_h2test failed: {p.stderr}")
+ raise Exception(f"compiling md_h2test 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 h2test_module \"{self.env.local_dir}/mod_h2test/.libs/mod_h2test.so\"\n")
+
+
+class H2TestEnv(HttpdTestEnv):
+
+ def __init__(self, pytestconfig=None, setup_dirs=True):
+ super().__init__(pytestconfig=pytestconfig,
+ local_dir=os.path.dirname(inspect.getfile(H2TestEnv)),
+ add_base_conf="""
+ H2MinWorkers 1
+ H2MaxWorkers 64
+ """,
+ interesting_modules=["http2", "proxy_http2", "h2test"])
+ self.add_cert_specs([
+ CertificateSpec(domains=[
+ f"push.{self._http_tld}",
+ f"hints.{self._http_tld}",
+ f"ssl.{self._http_tld}",
+ f"pad0.{self._http_tld}",
+ f"pad1.{self._http_tld}",
+ f"pad2.{self._http_tld}",
+ f"pad3.{self._http_tld}",
+ f"pad8.{self._http_tld}",
+ ]),
+ CertificateSpec(domains=[f"noh2.{self.http_tld}"], key_type='rsa2048'),
+ ])
+ if setup_dirs:
+ self._setup = H2TestSetup(env=self)
+ self._setup.make()
+ self.issue_certs()
+ self.setup_data_1k_1m()
+
+
+ def setup_data_1k_1m(self):
+ s100 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n"
+ with open(os.path.join(self.gen_dir, "data-1k"), 'w') as f:
+ for i in range(10):
+ f.write(s100)
+ with open(os.path.join(self.gen_dir, "data-10k"), 'w') as f:
+ for i in range(100):
+ f.write(s100)
+ with open(os.path.join(self.gen_dir, "data-100k"), 'w') as f:
+ for i in range(1000):
+ f.write(s100)
+ with open(os.path.join(self.gen_dir, "data-1m"), 'w') as f:
+ for i in range(10000):
+ f.write(s100)
+
+
+class H2Conf(HttpdConf):
+
+ def __init__(self, env: HttpdTestEnv, path=None):
+ super().__init__(env=env, path=path)
+
+
+ def add_vhost_noh2(self):
+ self.start_vhost(self.env.https_port, "noh2", aliases=["noh2-alias"], doc_root="htdocs/noh2", with_ssl=True)
+ self.add(f"""
+ Protocols http/1.1
+ SSLOptions +StdEnvVars""")
+ self.end_vhost()
+ self.start_vhost(self.env.http_port, "noh2", aliases=["noh2-alias"], doc_root="htdocs/noh2", with_ssl=False)
+ self.add(" Protocols http/1.1")
+ self.add(" SSLOptions +StdEnvVars")
+ self.end_vhost()
+ return self
diff --git a/test/modules/http2/test_000_infra.py b/test/modules/http2/test_000_infra.py
deleted file mode 100644
index 4a8591e62f..0000000000
--- a/test/modules/http2/test_000_infra.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# mod-h2 test suite
-# check that our test infrastructure is sane
-#
-import pytest
-
-
-class TestStore:
-
- @pytest.fixture(autouse=True, scope='class')
- def _class_scope(self, env):
- env.setup_data_1k_1m()
- yield
-
- def test_000_00(self):
- assert 1 == 1
-
diff --git a/test/modules/http2/test_001_httpd_alive.py b/test/modules/http2/test_001_httpd_alive.py
index f198c18d5e..d922b44001 100644
--- a/test/modules/http2/test_001_httpd_alive.py
+++ b/test/modules/http2/test_001_httpd_alive.py
@@ -1,28 +1,21 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_test1().install()
+ H2Conf(env).add_vhost_test1().install()
assert env.apache_restart() == 0
# we expect to see the document from the generic server
- def test_001_01(self, env):
- r = env.curl_get(f"https://{env.domain_test1}:{env.https_port}/alive.json", 5)
+ def test_h2_001_01(self, env):
+ url = env.mkurl("https", "test1", "/alive.json")
+ r = env.curl_get(url, 5)
assert r.exit_code == 0, r.stderr + r.stdout
assert r.response["json"]
- assert True == r.response["json"]["alive"]
- assert "test1" == r.response["json"]["host"]
-
- # we expect to see the document from the generic server
- def test_001_02(self, env):
- r = env.curl_get(f"https://{env.domain_test1}:{env.https_port}/alive.json", 5)
- assert r.exit_code == 0, r.stderr
- assert r.response["json"]
- assert True == r.response["json"]["alive"]
- assert "test1" == r.response["json"]["host"]
+ assert r.response["json"]["alive"] is True
+ assert r.response["json"]["host"] == "test1"
diff --git a/test/modules/http2/test_002_curl_basics.py b/test/modules/http2/test_002_curl_basics.py
index 1c1ef699a0..3f5e9694d7 100644
--- a/test/modules/http2/test_002_curl_basics.py
+++ b/test/modules/http2/test_002_curl_basics.py
@@ -1,17 +1,17 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_test1().add_vhost_test2().install()
+ H2Conf(env).add_vhost_test1().add_vhost_test2().install()
assert env.apache_restart() == 0
# check that we see the correct documents when using the test1 server name over http:
- def test_002_01(self, env):
+ def test_h2_002_01(self, env):
url = env.mkurl("http", "test1", "/alive.json")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -20,7 +20,7 @@ class TestStore:
assert "test1" == r.response["json"]["host"]
# check that we see the correct documents when using the test1 server name over https:
- def test_002_02(self, env):
+ def test_h2_002_02(self, env):
url = env.mkurl("https", "test1", "/alive.json")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -29,21 +29,21 @@ class TestStore:
assert "application/json" == r.response["header"]["content-type"]
# enforce HTTP/1.1
- def test_002_03(self, env):
+ def test_h2_002_03(self, env):
url = env.mkurl("https", "test1", "/alive.json")
r = env.curl_get(url, 5, [ "--http1.1" ])
assert 200 == r.response["status"]
assert "HTTP/1.1" == r.response["protocol"]
# enforce HTTP/2
- def test_002_04(self, env):
+ def test_h2_002_04(self, env):
url = env.mkurl("https", "test1", "/alive.json")
r = env.curl_get(url, 5, [ "--http2" ])
assert 200 == r.response["status"]
assert "HTTP/2" == r.response["protocol"]
# default is HTTP/2 on this host
- def test_002_04b(self, env):
+ def test_h2_002_04b(self, env):
url = env.mkurl("https", "test1", "/alive.json")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -51,7 +51,7 @@ class TestStore:
assert "test1" == r.response["json"]["host"]
# although, without ALPN, we cannot select it
- def test_002_05(self, env):
+ def test_h2_002_05(self, env):
url = env.mkurl("https", "test1", "/alive.json")
r = env.curl_get(url, 5, [ "--no-alpn" ])
assert 200 == r.response["status"]
@@ -59,7 +59,7 @@ class TestStore:
assert "test1" == r.response["json"]["host"]
# default is HTTP/1.1 on the other
- def test_002_06(self, env):
+ def test_h2_002_06(self, env):
url = env.mkurl("https", "test2", "/alive.json")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
diff --git a/test/modules/http2/test_003_get.py b/test/modules/http2/test_003_get.py
index ea7c9fb39d..f8b41fc1b9 100644
--- a/test/modules/http2/test_003_get.py
+++ b/test/modules/http2/test_003_get.py
@@ -1,14 +1,14 @@
import re
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_cgi(
+ H2Conf(env).add_vhost_cgi(
proxy_self=True, h2proxy_self=True
).add_vhost_test1(
proxy_self=True, h2proxy_self=True
@@ -16,7 +16,7 @@ class TestStore:
assert env.apache_restart() == 0
# check SSL environment variables from CGI script
- def test_003_01(self, env):
+ def test_h2_003_01(self, env):
url = env.mkurl("https", "cgi", "/hello.py")
r = env.curl_get(url, 5, ["--tlsv1.2"])
assert 200 == r.response["status"]
@@ -37,8 +37,8 @@ class TestStore:
assert "" == r.response["json"]["h2push"]
# retrieve a html file from the server and compare it to its source
- def test_003_02(self, env):
- with open(env.test_src("htdocs/test1/index.html"), mode='rb') as file:
+ def test_h2_003_02(self, env):
+ with open(env.htdocs_src("test1/index.html"), mode='rb') as file:
src = file.read()
url = env.mkurl("https", "test1", "/index.html")
@@ -63,23 +63,23 @@ class TestStore:
exp += text + "\n"
assert exp == r.response["body"].decode('utf-8')
- def test_003_10(self, env):
+ def test_h2_003_10(self, env):
self.check_necho(env, 10, "0123456789")
- def test_003_11(self, env):
+ def test_h2_003_11(self, env):
self.check_necho(env, 100, "0123456789")
- def test_003_12(self, env):
+ def test_h2_003_12(self, env):
self.check_necho(env, 1000, "0123456789")
- def test_003_13(self, env):
+ def test_h2_003_13(self, env):
self.check_necho(env, 10000, "0123456789")
- def test_003_14(self, env):
+ def test_h2_003_14(self, env):
self.check_necho(env, 100000, "0123456789")
# github issue #126
- def test_003_20(self, env):
+ def test_h2_003_20(self, env):
url = env.mkurl("https", "test1", "/006/")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -111,7 +111,7 @@ class TestStore:
s = re.sub(r'^vary:.*\n', '', s, flags=re.MULTILINE)
return re.sub(r'^accept-ranges:.*\n', '', s, flags=re.MULTILINE)
- def test_003_21(self, env):
+ def test_h2_003_21(self, env):
url = env.mkurl("https", "test1", "/index.html")
r = env.curl_get(url, 5, ["-I"])
assert 200 == r.response["status"]
@@ -141,7 +141,7 @@ content-type: text/html
@pytest.mark.parametrize("path", [
"/004.html", "/proxy/004.html", "/h2proxy/004.html"
])
- def test_003_30(self, env, path):
+ def test_h2_003_30(self, env, path):
url = env.mkurl("https", "test1", path)
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -156,7 +156,7 @@ content-type: text/html
@pytest.mark.parametrize("path", [
"/004.html", "/proxy/004.html", "/h2proxy/004.html"
])
- def test_003_31(self, env, path):
+ def test_h2_003_31(self, env, path):
url = env.mkurl("https", "test1", path)
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -168,7 +168,7 @@ content-type: text/html
assert 304 == r.response["status"]
# test various response body lengths to work correctly
- def test_003_40(self, env):
+ def test_h2_003_40(self, env):
n = 1001
while n <= 1025024:
url = env.mkurl("https", "cgi", f"/mnot164.py?count={n}&text=X")
@@ -182,7 +182,7 @@ content-type: text/html
@pytest.mark.parametrize("n", [
0, 1, 1291, 1292, 80000, 80123, 81087, 98452
])
- def test_003_41(self, env, n):
+ def test_h2_003_41(self, env, n):
url = env.mkurl("https", "cgi", f"/mnot164.py?count={n}&text=X")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -193,7 +193,7 @@ content-type: text/html
@pytest.mark.parametrize("path", [
"/004.html", "/proxy/004.html", "/h2proxy/004.html"
])
- def test_003_50(self, env, path):
+ def test_h2_003_50(self, env, path):
# check that the resource supports ranges and we see its raw content-length
url = env.mkurl("https", "test1", path)
r = env.curl_get(url, 5)
diff --git a/test/modules/http2/test_004_post.py b/test/modules/http2/test_004_post.py
index 16d1c7679c..ef3ff7925c 100644
--- a/test/modules/http2/test_004_post.py
+++ b/test/modules/http2/test_004_post.py
@@ -4,7 +4,7 @@ import os
import re
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@@ -12,7 +12,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- HttpdConf(env).add_vhost_cgi().install()
+ H2Conf(env).add_vhost_cgi().install()
assert env.apache_restart() == 0
# upload and GET again using curl, compare to original content
@@ -26,32 +26,32 @@ class TestStore:
r2 = env.curl_get(r.response["header"]["location"])
assert r2.exit_code == 0
assert r2.response["status"] == 200
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r2.response["body"]
- def test_004_01(self, env):
+ def test_h2_004_01(self, env):
self.curl_upload_and_verify(env, "data-1k", ["--http1.1"])
self.curl_upload_and_verify(env, "data-1k", ["--http2"])
- def test_004_02(self, env):
+ def test_h2_004_02(self, env):
self.curl_upload_and_verify(env, "data-10k", ["--http1.1"])
self.curl_upload_and_verify(env, "data-10k", ["--http2"])
- def test_004_03(self, env):
+ def test_h2_004_03(self, env):
self.curl_upload_and_verify(env, "data-100k", ["--http1.1"])
self.curl_upload_and_verify(env, "data-100k", ["--http2"])
- def test_004_04(self, env):
+ def test_h2_004_04(self, env):
self.curl_upload_and_verify(env, "data-1m", ["--http1.1"])
self.curl_upload_and_verify(env, "data-1m", ["--http2"])
- def test_004_05(self, env):
+ def test_h2_004_05(self, env):
self.curl_upload_and_verify(env, "data-1k", ["-v", "--http1.1", "-H", "Expect: 100-continue"])
self.curl_upload_and_verify(env, "data-1k", ["-v", "--http2", "-H", "Expect: 100-continue"])
@pytest.mark.skipif(True, reason="python3 regresses in chunked inputs to cgi")
- def test_004_06(self, env):
+ def test_h2_004_06(self, env):
self.curl_upload_and_verify(env, "data-1k", ["--http1.1", "-H", "Content-Length: "])
self.curl_upload_and_verify(env, "data-1k", ["--http2", "-H", "Content-Length: "])
@@ -63,7 +63,7 @@ class TestStore:
("H2_STREAM_ID", "1"),
("H2_STREAM_TAG", r'\d+-1'),
])
- def test_004_07(self, env, name, value):
+ def test_h2_004_07(self, env, name, value):
url = env.mkurl("https", "cgi", "/env.py")
r = env.curl_post_value(url, "name", name)
assert r.exit_code == 0
@@ -74,20 +74,20 @@ class TestStore:
# verify that we parse nghttp output correctly
def check_nghttp_body(self, env, ref_input, nghttp_output):
- with open(env.test_src(os.path.join(env.gen_dir, ref_input)), mode='rb') as f:
+ with open(env.local_src(os.path.join(env.gen_dir, ref_input)), mode='rb') as f:
refbody = f.read()
- with open(env.test_src(nghttp_output), mode='rb') as f:
+ with open(env.local_src(nghttp_output), mode='rb') as f:
text = f.read()
o = env.nghttp().parse_output(text)
assert "response" in o
assert "body" in o["response"]
if refbody != o["response"]["body"]:
- with open(env.test_src(os.path.join(env.gen_dir, '%s.parsed' % ref_input)), mode='bw') as f:
+ with open(env.local_src(os.path.join(env.gen_dir, '%s.parsed' % ref_input)), mode='bw') as f:
f.write(o["response"]["body"])
assert len(refbody) == len(o["response"]["body"])
assert refbody == o["response"]["body"]
- def test_004_20(self, env):
+ def test_h2_004_20(self, env):
self.check_nghttp_body(env, 'data-1k', 'data/nghttp-output-1k-1.txt')
self.check_nghttp_body(env, 'data-10k', 'data/nghttp-output-10k-1.txt')
self.check_nghttp_body(env, 'data-100k', 'data/nghttp-output-100k-1.txt')
@@ -101,20 +101,20 @@ class TestStore:
assert r.exit_code == 0
assert r.response["status"] >= 200 and r.response["status"] < 300
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r.response["body"]
@pytest.mark.parametrize("name", [
"data-1k", "data-10k", "data-100k", "data-1m"
])
- def test_004_21(self, env, name):
+ def test_h2_004_21(self, env, name):
self.nghttp_post_and_verify(env, name, [])
@pytest.mark.parametrize("name", [
"data-1k", "data-10k", "data-100k", "data-1m"
])
- def test_004_22(self, env, name, repeat):
+ def test_h2_004_22(self, env, name, repeat):
self.nghttp_post_and_verify(env, name, ["--no-content-length"])
# upload and GET again using nghttp, compare to original content
@@ -130,29 +130,29 @@ class TestStore:
r2 = env.nghttp().get(r.response["header"]["location"])
assert r2.exit_code == 0
assert r2.response["status"] == 200
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r2.response["body"]
@pytest.mark.parametrize("name", [
"data-1k", "data-10k", "data-100k", "data-1m"
])
- def test_004_23(self, env, name, repeat):
+ def test_h2_004_23(self, env, name, repeat):
self.nghttp_upload_and_verify(env, name, [])
@pytest.mark.parametrize("name", [
"data-1k", "data-10k", "data-100k", "data-1m"
])
- def test_004_24(self, env, name, repeat):
+ def test_h2_004_24(self, env, name, repeat):
self.nghttp_upload_and_verify(env, name, ["--expect-continue"])
@pytest.mark.parametrize("name", [
"data-1k", "data-10k", "data-100k", "data-1m"
])
- def test_004_25(self, env, name, repeat):
+ def test_h2_004_25(self, env, name, repeat):
self.nghttp_upload_and_verify(env, name, ["--no-content-length"])
- def test_004_30(self, env):
+ def test_h2_004_30(self, env):
# issue: #203
resource = "data-1k"
full_length = 1000
@@ -161,7 +161,7 @@ class TestStore:
logfile = os.path.join(env.server_logs_dir, "test_004_30")
if os.path.isfile(logfile):
os.remove(logfile)
- HttpdConf(env).add("""
+ H2Conf(env).add("""
LogFormat "{ \\"request\\": \\"%r\\", \\"status\\": %>s, \\"bytes_resp_B\\": %B, \\"bytes_tx_O\\": %O, \\"bytes_rx_I\\": %I, \\"bytes_rx_tx_S\\": %S }" issue_203
CustomLog logs/test_004_30 issue_203
""").add_vhost_cgi().install()
@@ -190,7 +190,7 @@ CustomLog logs/test_004_30 issue_203
assert log_h2['bytes_resp_B'] == chunk
assert log_h2['bytes_tx_O'] > chunk
- def test_004_40(self, env):
+ def test_h2_004_40(self, env):
# echo content using h2test_module "echo" handler
def post_and_verify(fname, options=None):
url = env.mkurl("https", "cgi", "/h2test/echo")
@@ -211,7 +211,7 @@ CustomLog logs/test_004_30 issue_203
if fname == part.get_filename():
filepart = part
assert filepart
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == filepart.get_payload(decode=True)
diff --git a/test/modules/http2/test_005_files.py b/test/modules/http2/test_005_files.py
index 4969a6c6c9..91eacf3b10 100644
--- a/test/modules/http2/test_005_files.py
+++ b/test/modules/http2/test_005_files.py
@@ -1,7 +1,7 @@
import os
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
def mk_text_file(fpath: str, lines: int):
@@ -33,14 +33,14 @@ class TestFiles:
mk_text_file(os.path.join(docs_a, fname), 8 * fsize)
self.URI_PATHS.append(f"/files/{fname}")
- HttpdConf(env).add_vhost_cgi(
+ H2Conf(env).add_vhost_cgi(
proxy_self=True, h2proxy_self=True
).add_vhost_test1(
proxy_self=True, h2proxy_self=True
).install()
assert env.apache_restart() == 0
- def test_005_01(self, env):
+ def test_h2_005_01(self, env):
url = env.mkurl("https", "cgi", self.URI_PATHS[2])
r = env.curl_get(url)
assert r.response, r.stderr + r.stdout
diff --git a/test/modules/http2/test_006_assets.py b/test/modules/http2/test_006_assets.py
index 339364ee58..44558da81e 100644
--- a/test/modules/http2/test_006_assets.py
+++ b/test/modules/http2/test_006_assets.py
@@ -1,17 +1,17 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_test1().install()
+ H2Conf(env).add_vhost_test1().install()
assert env.apache_restart() == 0
# single page without any assets
- def test_006_01(self, env):
+ def test_h2_006_01(self, env):
url = env.mkurl("https", "test1", "/001.html")
r = env.nghttp().assets(url, options=["-Haccept-encoding: none"])
assert 0 == r.exit_code
@@ -21,7 +21,7 @@ class TestStore:
]
# single image without any assets
- def test_006_02(self, env):
+ def test_h2_006_02(self, env):
url = env.mkurl("https", "test1", "/002.jpg")
r = env.nghttp().assets(url, options=["-Haccept-encoding: none"])
assert 0 == r.exit_code
@@ -31,7 +31,7 @@ class TestStore:
]
# gophertiles, yea!
- def test_006_03(self, env):
+ def test_h2_006_03(self, env):
# create the tiles files we originally had checked in
exp_assets = [
{"status": 200, "size": "10K", "path": "/004.html"},
@@ -51,7 +51,7 @@ class TestStore:
assert r.assets == exp_assets
# page with js and css
- def test_006_04(self, env):
+ def test_h2_006_04(self, env):
url = env.mkurl("https", "test1", "/006.html")
r = env.nghttp().assets(url, options=["-Haccept-encoding: none"])
assert 0 == r.exit_code
@@ -63,7 +63,7 @@ class TestStore:
]
# page with image, try different window size
- def test_006_05(self, env):
+ def test_h2_006_05(self, env):
url = env.mkurl("https", "test1", "/003.html")
r = env.nghttp().assets(url, options=["--window-bits=24", "-Haccept-encoding: none"])
assert 0 == r.exit_code
diff --git a/test/modules/http2/test_100_conn_reuse.py b/test/modules/http2/test_100_conn_reuse.py
index cef2f9d07b..763288e396 100644
--- a/test/modules/http2/test_100_conn_reuse.py
+++ b/test/modules/http2/test_100_conn_reuse.py
@@ -1,17 +1,17 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_noh2().add_vhost_test1().add_vhost_cgi().install()
+ H2Conf(env).add_vhost_noh2().add_vhost_test1().add_vhost_cgi().install()
assert env.apache_restart() == 0
# make sure the protocol selection on the different hosts work as expected
- def test_100_01(self, env):
+ def test_h2_100_01(self, env):
# this host defaults to h2, but we can request h1
url = env.mkurl("https", "cgi", "/hello.py")
assert "2" == env.curl_protocol_version( url )
@@ -23,7 +23,7 @@ class TestStore:
assert "1.1" == env.curl_protocol_version( url, options=[ "--http2" ] )
# access a ServerAlias, after using ServerName in SNI
- def test_100_02(self, env):
+ def test_h2_100_02(self, env):
url = env.mkurl("https", "cgi", "/hello.py")
hostname = ("cgi-alias.%s" % env.http_tld)
r = env.curl_get(url, 5, [ "-H", "Host:%s" % hostname ])
@@ -32,7 +32,7 @@ class TestStore:
assert hostname == r.response["json"]["host"]
# access another vhost, after using ServerName in SNI, that uses same SSL setup
- def test_100_03(self, env):
+ def test_h2_100_03(self, env):
url = env.mkurl("https", "cgi", "/")
hostname = ("test1.%s" % env.http_tld)
r = env.curl_get(url, 5, [ "-H", "Host:%s" % hostname ])
@@ -42,14 +42,14 @@ class TestStore:
# access another vhost, after using ServerName in SNI,
# that has different SSL certificate. This triggers a 421 (misdirected request) response.
- def test_100_04(self, env):
+ def test_h2_100_04(self, env):
url = env.mkurl("https", "cgi", "/hello.py")
hostname = ("noh2.%s" % env.http_tld)
r = env.curl_get(url, 5, [ "-H", "Host:%s" % hostname ])
assert 421 == r.response["status"]
# access an unknown vhost, after using ServerName in SNI
- def test_100_05(self, env):
+ def test_h2_100_05(self, env):
url = env.mkurl("https", "cgi", "/hello.py")
hostname = ("unknown.%s" % env.http_tld)
r = env.curl_get(url, 5, [ "-H", "Host:%s" % hostname ])
diff --git a/test/modules/http2/test_101_ssl_reneg.py b/test/modules/http2/test_101_ssl_reneg.py
index 22bfa50baa..de748292b0 100644
--- a/test/modules/http2/test_101_ssl_reneg.py
+++ b/test/modules/http2/test_101_ssl_reneg.py
@@ -1,14 +1,14 @@
import re
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add(
+ H2Conf(env).add(
f"""
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384
<Directory \"{env.server_dir}/htdocs/ssl-client-verify\">
@@ -46,7 +46,7 @@ class TestStore:
assert env.apache_restart() == 0
# access a resource with SSL renegotiation, using HTTP/1.1
- def test_101_01(self, env):
+ def test_h2_101_01(self, env):
url = env.mkurl("https", "ssl", "/renegotiate/cipher/")
r = env.curl_get(url, options=["-v", "--http1.1", "--tlsv1.2", "--tls-max", "1.2"])
assert 0 == r.exit_code
@@ -54,7 +54,7 @@ class TestStore:
assert 403 == r.response["status"]
# try to renegotiate the cipher, should fail with correct code
- def test_101_02(self, env):
+ def test_h2_101_02(self, env):
url = env.mkurl("https", "ssl", "/renegotiate/cipher/")
r = env.curl_get(url, options=[
"-vvv", "--tlsv1.2", "--tls-max", "1.2", "--ciphers", "ECDHE-RSA-AES256-GCM-SHA384"
@@ -65,7 +65,7 @@ class TestStore:
# try to renegotiate a client certificate from Location
# needs to fail with correct code
- def test_101_03(self, env):
+ def test_h2_101_03(self, env):
url = env.mkurl("https", "ssl", "/renegotiate/verify/")
r = env.curl_get(url, options=["-vvv", "--tlsv1.2", "--tls-max", "1.2"])
assert 0 != r.exit_code
@@ -74,7 +74,7 @@ class TestStore:
# try to renegotiate a client certificate from Directory
# needs to fail with correct code
- def test_101_04(self, env):
+ def test_h2_101_04(self, env):
url = env.mkurl("https", "ssl", "/ssl-client-verify/index.html")
r = env.curl_get(url, options=["-vvv", "--tlsv1.2", "--tls-max", "1.2"])
assert 0 != r.exit_code
@@ -83,7 +83,7 @@ class TestStore:
# make 10 requests on the same connection, none should produce a status code
# reported by erki@example.ee
- def test_101_05(self, env):
+ def test_h2_101_05(self, env):
r = env.run([env.h2load, "-n", "10", "-c", "1", "-m", "1", "-vvvv",
f"{env.https_base_url}/ssl-client-verify/index.html"])
assert 0 == r.exit_code
@@ -99,7 +99,7 @@ class TestStore:
# Check that "SSLRequireSSL" works on h2 connections
# See <https://bz.apache.org/bugzilla/show_bug.cgi?id=62654>
- def test_101_10a(self, env):
+ def test_h2_101_10a(self, env):
url = env.mkurl("https", "ssl", "/sslrequire/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -108,7 +108,7 @@ class TestStore:
# Check that "require ssl" works on h2 connections
# See <https://bz.apache.org/bugzilla/show_bug.cgi?id=62654>
- def test_101_10b(self, env):
+ def test_h2_101_10b(self, env):
url = env.mkurl("https", "ssl", "/requiressl/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -116,7 +116,7 @@ class TestStore:
assert 404 == r.response["status"]
# Check that status works with ErrorDoc, see pull #174, fixes #172
- def test_101_11(self, env):
+ def test_h2_101_11(self, env):
url = env.mkurl("https", "ssl", "/renegotiate/err-doc-cipher")
r = env.curl_get(url, options=[
"-vvv", "--tlsv1.2", "--tls-max", "1.2", "--ciphers", "ECDHE-RSA-AES256-GCM-SHA384"
diff --git a/test/modules/http2/test_102_require.py b/test/modules/http2/test_102_require.py
index e8e2593c9c..9751136f59 100644
--- a/test/modules/http2/test_102_require.py
+++ b/test/modules/http2/test_102_require.py
@@ -1,13 +1,13 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- conf = HttpdConf(env).start_vhost(env.https_port, "ssl", with_ssl=True)
+ conf = H2Conf(env).start_vhost(env.https_port, "ssl", with_ssl=True)
conf.add("""
Protocols h2 http/1.1
SSLOptions +StdEnvVars
@@ -23,14 +23,14 @@ class TestStore:
env.mkpath("%s/htdocs/ssl-client-verify" % env.server_dir)
assert env.apache_restart() == 0
- def test_102_01(self, env):
+ def test_h2_102_01(self, env):
url = env.mkurl("https", "ssl", "/h2only.html")
r = env.curl_get(url)
assert 0 == r.exit_code
assert r.response
assert 404 == r.response["status"]
- def test_102_02(self, env):
+ def test_h2_102_02(self, env):
url = env.mkurl("https", "ssl", "/noh2.html")
r = env.curl_get(url)
assert 0 == r.exit_code
diff --git a/test/modules/http2/test_103_upgrade.py b/test/modules/http2/test_103_upgrade.py
index 28ed7370d2..8dfe4a1d21 100644
--- a/test/modules/http2/test_103_upgrade.py
+++ b/test/modules/http2/test_103_upgrade.py
@@ -1,13 +1,13 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_test1().add_vhost_test2().add_vhost_noh2(
+ H2Conf(env).add_vhost_test1().add_vhost_test2().add_vhost_noh2(
).start_vhost(
env.https_port, "test3", doc_root="htdocs/test1", with_ssl=True
).add(
@@ -29,7 +29,7 @@ class TestStore:
assert env.apache_restart() == 0
# accessing http://test1, will not try h2 and advertise h2 in the response
- def test_103_01(self, env):
+ def test_h2_103_01(self, env):
url = env.mkurl("http", "test1", "/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -38,7 +38,7 @@ class TestStore:
assert "h2c" == r.response["header"]["upgrade"]
# accessing http://noh2, will not advertise, because noh2 host does not have it enabled
- def test_103_02(self, env):
+ def test_h2_103_02(self, env):
url = env.mkurl("http", "noh2", "/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -46,7 +46,7 @@ class TestStore:
assert "upgrade" not in r.response["header"]
# accessing http://test2, will not advertise, because h2 has less preference than http/1.1
- def test_103_03(self, env):
+ def test_h2_103_03(self, env):
url = env.mkurl("http", "test2", "/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -54,7 +54,7 @@ class TestStore:
assert "upgrade" not in r.response["header"]
# accessing https://noh2, will not advertise, because noh2 host does not have it enabled
- def test_103_04(self, env):
+ def test_h2_103_04(self, env):
url = env.mkurl("https", "noh2", "/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -62,7 +62,7 @@ class TestStore:
assert "upgrade" not in r.response["header"]
# accessing https://test2, will not advertise, because h2 has less preference than http/1.1
- def test_103_05(self, env):
+ def test_h2_103_05(self, env):
url = env.mkurl("https", "test2", "/index.html")
r = env.curl_get(url)
assert 0 == r.exit_code
@@ -70,7 +70,7 @@ class TestStore:
assert "upgrade" not in r.response["header"]
# accessing https://test1, will advertise h2 in the response
- def test_103_06(self, env):
+ def test_h2_103_06(self, env):
url = env.mkurl("https", "test1", "/index.html")
r = env.curl_get(url, options=["--http1.1"])
assert 0 == r.exit_code
@@ -79,7 +79,7 @@ class TestStore:
assert "h2" == r.response["header"]["upgrade"]
# accessing https://test3, will not send Upgrade since it is suppressed
- def test_103_07(self, env):
+ def test_h2_103_07(self, env):
url = env.mkurl("https", "test3", "/index.html")
r = env.curl_get(url, options=["--http1.1"])
assert 0 == r.exit_code
@@ -87,33 +87,33 @@ class TestStore:
assert "upgrade" not in r.response["header"]
# upgrade to h2c for a request, where h2c is preferred
- def test_103_20(self, env):
+ def test_h2_103_20(self, env):
url = env.mkurl("http", "test1", "/index.html")
r = env.nghttp().get(url, options=["-u"])
assert 200 == r.response["status"]
# upgrade to h2c for a request where http/1.1 is preferred, but the clients upgrade
# wish is honored nevertheless
- def test_103_21(self, env):
+ def test_h2_103_21(self, env):
url = env.mkurl("http", "test2", "/index.html")
r = env.nghttp().get(url, options=["-u"])
assert 404 == r.response["status"]
# ugrade to h2c on a host where h2c is not enabled will fail
- def test_103_22(self, env):
+ def test_h2_103_22(self, env):
url = env.mkurl("http", "noh2", "/index.html")
r = env.nghttp().get(url, options=["-u"])
assert not r.response
# ugrade to h2c on a host where h2c is preferred, but Upgrade is disabled
- def test_103_23(self, env):
+ def test_h2_103_23(self, env):
url = env.mkurl("http", "test1b", "/index.html")
r = env.nghttp().get(url, options=["-u"])
assert not r.response
# ugrade to h2c on a host where h2c is preferred, but Upgrade is disabled on the server,
# but allowed for a specific location
- def test_103_24(self, env):
+ def test_h2_103_24(self, env):
url = env.mkurl("http", "test1b", "/006.html")
r = env.nghttp().get(url, options=["-u"])
assert 200 == r.response["status"]
diff --git a/test/modules/http2/test_104_padding.py b/test/modules/http2/test_104_padding.py
index f5a481207d..976935e8e8 100644
--- a/test/modules/http2/test_104_padding.py
+++ b/test/modules/http2/test_104_padding.py
@@ -1,6 +1,6 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
def frame_padding(payload, padbits):
@@ -12,8 +12,11 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- conf = HttpdConf(env)
- conf.add_vhost_cgi()
+ conf = H2Conf(env)
+ conf.start_vhost(env.https_port, "ssl", doc_root="htdocs/cgi", with_ssl=True)
+ conf.add("Protocols h2 http/1.1")
+ conf.add("AddHandler cgi-script .py")
+ conf.end_vhost()
conf.start_vhost(env.https_port, "pad0", doc_root="htdocs/cgi", with_ssl=True)
conf.add("Protocols h2 http/1.1")
conf.add("H2Padding 0")
@@ -43,8 +46,8 @@ class TestStore:
assert env.apache_restart() == 0
# default paddings settings: 0 bits
- def test_104_01(self, env):
- url = env.mkurl("https", "cgi", "/echo.py")
+ def test_h2_104_01(self, env):
+ url = env.mkurl("https", "ssl", "/echo.py")
# we get 2 frames back: one with data and an empty one with EOF
# check the number of padding bytes is as expected
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
@@ -56,7 +59,7 @@ class TestStore:
]
# 0 bits of padding
- def test_104_02(self, env):
+ def test_h2_104_02(self, env):
url = env.mkurl("https", "pad0", "/echo.py")
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
r = env.nghttp().post_data(url, data, 5)
@@ -64,7 +67,7 @@ class TestStore:
assert r.results["paddings"] == [0, 0]
# 1 bit of padding
- def test_104_03(self, env):
+ def test_h2_104_03(self, env):
url = env.mkurl("https", "pad1", "/echo.py")
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
r = env.nghttp().post_data(url, data, 5)
@@ -73,7 +76,7 @@ class TestStore:
assert i in range(0, 2)
# 2 bits of padding
- def test_104_04(self, env):
+ def test_h2_104_04(self, env):
url = env.mkurl("https", "pad2", "/echo.py")
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
r = env.nghttp().post_data(url, data, 5)
@@ -82,7 +85,7 @@ class TestStore:
assert i in range(0, 4)
# 3 bits of padding
- def test_104_05(self, env):
+ def test_h2_104_05(self, env):
url = env.mkurl("https", "pad3", "/echo.py")
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
r = env.nghttp().post_data(url, data, 5)
@@ -91,7 +94,7 @@ class TestStore:
assert i in range(0, 8)
# 8 bits of padding
- def test_104_06(self, env):
+ def test_h2_104_06(self, env):
url = env.mkurl("https", "pad8", "/echo.py")
for data in ["x", "xx", "xxx", "xxxx", "xxxxx", "xxxxxx", "xxxxxxx", "xxxxxxxx"]:
r = env.nghttp().post_data(url, data, 5)
diff --git a/test/modules/http2/test_105_timeout.py b/test/modules/http2/test_105_timeout.py
index 88a609376b..d8e7036310 100644
--- a/test/modules/http2/test_105_timeout.py
+++ b/test/modules/http2/test_105_timeout.py
@@ -3,15 +3,15 @@ import time
import pytest
-from h2_conf import HttpdConf
-from h2_curl import CurlPiper
+from .env import H2Conf
+from pyhttpd.curl import CurlPiper
class TestStore:
# Check that base servers 'Timeout' setting is observed on SSL handshake
- def test_105_01(self, env):
- conf = HttpdConf(env)
+ def test_h2_105_01(self, env):
+ conf = H2Conf(env)
conf.add("""
AcceptFilter http none
Timeout 1.5
@@ -44,8 +44,8 @@ class TestStore:
sock.close()
# Check that mod_reqtimeout handshake setting takes effect
- def test_105_02(self, env):
- conf = HttpdConf(env)
+ def test_h2_105_02(self, env):
+ conf = H2Conf(env)
conf.add("""
AcceptFilter http none
Timeout 10
@@ -80,8 +80,8 @@ class TestStore:
# Check that mod_reqtimeout handshake setting do no longer apply to handshaked
# connections. See <https://github.com/icing/mod_h2/issues/196>.
- def test_105_03(self, env):
- conf = HttpdConf(env)
+ def test_h2_105_03(self, env):
+ conf = H2Conf(env)
conf.add("""
Timeout 10
RequestReadTimeout handshake=1 header=5 body=10
@@ -98,9 +98,9 @@ class TestStore:
])
assert 200 == r.response["status"]
- def test_105_10(self, env):
+ def test_h2_105_10(self, env):
# just a check without delays if all is fine
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi()
conf.install()
assert env.apache_restart() == 0
@@ -112,10 +112,10 @@ class TestStore:
assert len("".join(stdout)) == 3 * 8192
@pytest.mark.skipif(True, reason="new feature in upcoming http2")
- def test_105_11(self, env):
+ def test_h2_105_11(self, env):
# short connection timeout, longer stream delay
# receiving the first response chunk, then timeout
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi()
conf.add("Timeout 1")
conf.install()
@@ -127,10 +127,10 @@ class TestStore:
assert len("".join(stdout)) == 8192
@pytest.mark.skipif(True, reason="new feature in upcoming http2")
- def test_105_12(self, env):
+ def test_h2_105_12(self, env):
# long connection timeout, short stream timeout
# sending a slow POST
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi()
conf.add("Timeout 10")
conf.add("H2StreamTimeout 1")
diff --git a/test/modules/http2/test_106_shutdown.py b/test/modules/http2/test_106_shutdown.py
index 37471d26ca..9f88b5caee 100644
--- a/test/modules/http2/test_106_shutdown.py
+++ b/test/modules/http2/test_106_shutdown.py
@@ -7,20 +7,20 @@ from threading import Thread
import pytest
-from h2_conf import HttpdConf
-from h2_result import ExecResult
+from .env import H2Conf
+from pyhttpd.result import ExecResult
class TestShutdown:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi()
conf.install()
assert env.apache_restart() == 0
- def test_106_01(self, env):
+ def test_h2_106_01(self, env):
url = env.mkurl("https", "cgi", "/necho.py")
lines = 100000
text = "123456789"
diff --git a/test/modules/http2/test_200_header_invalid.py b/test/modules/http2/test_200_header_invalid.py
index f0fe377272..fbaa111739 100644
--- a/test/modules/http2/test_200_header_invalid.py
+++ b/test/modules/http2/test_200_header_invalid.py
@@ -1,19 +1,19 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_cgi().install()
+ H2Conf(env).add_vhost_cgi().install()
assert env.apache_restart() == 0
# let the hecho.py CGI echo chars < 0x20 in field name
# for almost all such characters, the stream gets aborted with a h2 error and
# there will be no http status, cr and lf are handled special
- def test_200_01(self, env):
+ def test_h2_200_01(self, env):
url = env.mkurl("https", "cgi", "/hecho.py")
for x in range(1, 32):
r = env.curl_post_data(url, "name=x%%%02xx&value=yz" % x)
@@ -29,7 +29,7 @@ class TestStore:
# let the hecho.py CGI echo chars < 0x20 in field value
# for almost all such characters, the stream gets aborted with a h2 error and
# there will be no http status, cr and lf are handled special
- def test_200_02(self, env):
+ def test_h2_200_02(self, env):
url = env.mkurl("https", "cgi", "/hecho.py")
for x in range(1, 32):
if 9 != x:
@@ -41,7 +41,7 @@ class TestStore:
assert 0 != r.exit_code, "unexpected exit code for char 0x%02x" % x
# let the hecho.py CGI echo 0x10 and 0x7f in field name and value
- def test_200_03(self, env):
+ def test_h2_200_03(self, env):
url = env.mkurl("https", "cgi", "/hecho.py")
for h in ["10", "7f"]:
r = env.curl_post_data(url, "name=x%%%s&value=yz" % h)
@@ -50,7 +50,7 @@ class TestStore:
assert 0 != r.exit_code
# test header field lengths check, LimitRequestLine (default 8190)
- def test_200_10(self, env):
+ def test_h2_200_10(self, env):
url = env.mkurl("https", "cgi", "/")
val = "1234567890" # 10 chars
for i in range(3): # make a 10000 char string
@@ -67,7 +67,7 @@ class TestStore:
assert 431 == r.response["status"]
# test header field lengths check, LimitRequestFieldSize (default 8190)
- def test_200_11(self, env):
+ def test_h2_200_11(self, env):
url = env.mkurl("https", "cgi", "/")
val = "1234567890" # 10 chars
for i in range(3): # make a 10000 char string
@@ -83,7 +83,7 @@ class TestStore:
# test header field count, LimitRequestFields (default 100)
# see #201: several headers with same name are mered and count only once
- def test_200_12(self, env):
+ def test_h2_200_12(self, env):
url = env.mkurl("https", "cgi", "/")
opt = []
for i in range(98): # curl sends 2 headers itself (user-agent and accept)
@@ -95,7 +95,7 @@ class TestStore:
# test header field count, LimitRequestFields (default 100)
# different header names count each
- def test_200_13(self, env):
+ def test_h2_200_13(self, env):
url = env.mkurl("https", "cgi", "/")
opt = []
for i in range(98): # curl sends 2 headers itself (user-agent and accept)
@@ -106,8 +106,8 @@ class TestStore:
assert 431 == r.response["status"]
# test "LimitRequestFields 0" setting, see #200
- def test_200_14(self, env):
- conf = HttpdConf(env)
+ def test_h2_200_14(self, env):
+ conf = H2Conf(env)
conf.add("""
LimitRequestFields 20
""")
@@ -120,7 +120,7 @@ class TestStore:
opt += ["-H", "x{0}: 1".format(i)]
r = env.curl_get(url, options=opt)
assert 431 == r.response["status"]
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add("""
LimitRequestFields 0
""")
@@ -135,8 +135,8 @@ class TestStore:
assert 200 == r.response["status"]
# the uri limits
- def test_200_15(self, env):
- conf = HttpdConf(env)
+ def test_h2_200_15(self, env):
+ conf = H2Conf(env)
conf.add("""
LimitRequestLine 48
""")
@@ -159,8 +159,8 @@ class TestStore:
assert not r.response
# invalid chars in method
- def test_200_16(self, env):
- conf = HttpdConf(env)
+ def test_h2_200_16(self, env):
+ conf = H2Conf(env)
conf.add_vhost_cgi()
conf.install()
assert env.apache_restart() == 0
diff --git a/test/modules/http2/test_201_header_conditional.py b/test/modules/http2/test_201_header_conditional.py
index 85047422cb..755e70e9ee 100644
--- a/test/modules/http2/test_201_header_conditional.py
+++ b/test/modules/http2/test_201_header_conditional.py
@@ -1,13 +1,13 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add(
+ H2Conf(env).add(
"""
KeepAlive on
MaxKeepAliveRequests 30
@@ -16,7 +16,7 @@ class TestStore:
assert env.apache_restart() == 0
# check handling of 'if-modified-since' header
- def test_201_01(self, env):
+ def test_h2_201_01(self, env):
url = env.mkurl("https", "test1", "/006/006.css")
r = env.curl_get(url)
assert 200 == r.response["status"]
@@ -28,7 +28,7 @@ class TestStore:
assert 200 == r.response["status"]
# check handling of 'if-none-match' header
- def test_201_02(self, env):
+ def test_h2_201_02(self, env):
url = env.mkurl("https", "test1", "/006/006.css")
r = env.curl_get(url)
assert 200 == r.response["status"]
@@ -40,7 +40,7 @@ class TestStore:
assert 200 == r.response["status"]
@pytest.mark.skipif(True, reason="304 misses the Vary header in trunk and 2.4.x")
- def test_201_03(self, env):
+ def test_h2_201_03(self, env):
url = env.mkurl("https", "test1", "/006.html")
r = env.curl_get(url, options=["-H", "Accept-Encoding: gzip"])
assert 200 == r.response["status"]
@@ -59,7 +59,7 @@ class TestStore:
assert "vary" in r.response["header"]
# Check if "Keep-Alive" response header is removed in HTTP/2.
- def test_201_04(self, env):
+ def test_h2_201_04(self, env):
url = env.mkurl("https", "test1", "/006.html")
r = env.curl_get(url, options=["--http1.1", "-H", "Connection: keep-alive"])
assert 200 == r.response["status"]
diff --git a/test/modules/http2/test_202_trailer.py b/test/modules/http2/test_202_trailer.py
index f43aa85080..c9081e00d4 100644
--- a/test/modules/http2/test_202_trailer.py
+++ b/test/modules/http2/test_202_trailer.py
@@ -1,7 +1,7 @@
import os
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
def setup_data(env):
@@ -18,11 +18,11 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
setup_data(env)
- HttpdConf(env).add_vhost_cgi(h2proxy_self=True).install()
+ H2Conf(env).add_vhost_cgi(h2proxy_self=True).install()
assert env.apache_restart() == 0
# check if the server survives a trailer or two
- def test_202_01(self, env):
+ def test_h2_202_01(self, env):
url = env.mkurl("https", "cgi", "/echo.py")
fpath = os.path.join(env.gen_dir, "data-1k")
r = env.nghttp().upload(url, fpath, options=["--trailer", "test: 1"])
@@ -34,7 +34,7 @@ class TestStore:
assert 1000 == len(r.response["body"])
# check if the server survives a trailer without content-length
- def test_202_02(self, env):
+ def test_h2_202_02(self, env):
url = env.mkurl("https", "cgi", "/echo.py")
fpath = os.path.join(env.gen_dir, "data-1k")
r = env.nghttp().upload(url, fpath, options=["--trailer", "test: 2", "--no-content-length"])
@@ -42,14 +42,14 @@ class TestStore:
assert 1000 == len(r.response["body"])
# check if echoing request headers in response from GET works
- def test_202_03(self, env):
+ def test_h2_202_03(self, env):
url = env.mkurl("https", "cgi", "/echohd.py?name=X")
r = env.nghttp().get(url, options=["--header", "X: 3"])
assert 300 > r.response["status"]
assert b"X: 3\n" == r.response["body"]
# check if echoing request headers in response from POST works
- def test_202_03b(self, env):
+ def test_h2_202_03b(self, env):
url = env.mkurl("https", "cgi", "/echohd.py?name=X")
r = env.nghttp().post_name(url, "Y", options=["--header", "X: 3b"])
assert 300 > r.response["status"]
@@ -57,7 +57,7 @@ class TestStore:
# check if echoing request headers in response from POST works, but trailers are not seen
# This is the way CGI invocation works.
- def test_202_04(self, env):
+ def test_h2_202_04(self, env):
url = env.mkurl("https", "cgi", "/echohd.py?name=X")
r = env.nghttp().post_name(url, "Y", options=["--header", "X: 4a", "--trailer", "X: 4b"])
assert 300 > r.response["status"]
diff --git a/test/modules/http2/test_300_interim.py b/test/modules/http2/test_300_interim.py
index b0c591d6f0..b3b38835ba 100644
--- a/test/modules/http2/test_300_interim.py
+++ b/test/modules/http2/test_300_interim.py
@@ -1,13 +1,13 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_test1().add_vhost_cgi().install()
+ H2Conf(env).add_vhost_test1().add_vhost_cgi().install()
assert env.apache_restart() == 0
def setup_method(self, method):
@@ -17,14 +17,14 @@ class TestStore:
print("teardown_method: %s" % method.__name__)
# check that we normally do not see an interim response
- def test_300_01(self, env):
+ def test_h2_300_01(self, env):
url = env.mkurl("https", "test1", "/index.html")
r = env.curl_post_data(url, 'XYZ')
assert 200 == r.response["status"]
assert "previous" not in r.response
# check that we see an interim response when we ask for it
- def test_300_02(self, env):
+ def test_h2_300_02(self, env):
url = env.mkurl("https", "cgi", "/echo.py")
r = env.curl_post_data(url, 'XYZ', options=["-H", "expect: 100-continue"])
assert 200 == r.response["status"]
@@ -32,7 +32,7 @@ class TestStore:
assert 100 == r.response["previous"]["status"]
# check proper answer on unexpected
- def test_300_03(self, env):
+ def test_h2_300_03(self, env):
url = env.mkurl("https", "cgi", "/echo.py")
r = env.curl_post_data(url, 'XYZ', options=["-H", "expect: the-unexpected"])
assert 417 == r.response["status"]
diff --git a/test/modules/http2/test_400_push.py b/test/modules/http2/test_400_push.py
index 9e2e853971..564c87ddc3 100644
--- a/test/modules/http2/test_400_push.py
+++ b/test/modules/http2/test_400_push.py
@@ -1,7 +1,7 @@
import os
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
# The push tests depend on "nghttp"
@@ -9,7 +9,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).start_vhost(
+ H2Conf(env).start_vhost(
env.https_port, "push", doc_root="htdocs/test1", with_ssl=True
).add(r""" Protocols h2 http/1.1"
RewriteEngine on
@@ -61,7 +61,7 @@ class TestStore:
# Link: header handling, various combinations
# plain resource without configured pushes
- def test_400_00(self, env):
+ def test_h2_400_00(self, env):
url = env.mkurl("https", "push", "/006.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -69,7 +69,7 @@ class TestStore:
assert 0 == len(promises)
# 2 link headers configured, only 1 triggers push
- def test_400_01(self, env):
+ def test_h2_400_01(self, env):
url = env.mkurl("https", "push", "/006-push.html")
r = env.nghttp().get(url, options=["-Haccept-encoding: none"])
assert 200 == r.response["status"]
@@ -79,7 +79,7 @@ class TestStore:
assert 216 == len(promises[0]["response"]["body"])
# Same as 400_01, but with single header line configured
- def test_400_02(self, env):
+ def test_h2_400_02(self, env):
url = env.mkurl("https", "push", "/006-push2.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -88,7 +88,7 @@ class TestStore:
assert '/006/006.js' == promises[0]["request"]["header"][":path"]
# 2 Links, only one with correct rel attribue
- def test_400_03(self, env):
+ def test_h2_400_03(self, env):
url = env.mkurl("https", "push", "/006-push3.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -97,7 +97,7 @@ class TestStore:
assert '/006/006.js' == promises[0]["request"]["header"][":path"]
# Missing > in Link header, PUSH not triggered
- def test_400_04(self, env):
+ def test_h2_400_04(self, env):
url = env.mkurl("https", "push", "/006-push4.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -105,7 +105,7 @@ class TestStore:
assert 0 == len(promises)
# More than one value in "rel" parameter
- def test_400_05(self, env):
+ def test_h2_400_05(self, env):
url = env.mkurl("https", "push", "/006-push5.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -114,7 +114,7 @@ class TestStore:
assert '/006/006.css' == promises[0]["request"]["header"][":path"]
# Another "rel" parameter variation
- def test_400_06(self, env):
+ def test_h2_400_06(self, env):
url = env.mkurl("https", "push", "/006-push6.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -123,7 +123,7 @@ class TestStore:
assert '/006/006.css' == promises[0]["request"]["header"][":path"]
# Another "rel" parameter variation
- def test_400_07(self, env):
+ def test_h2_400_07(self, env):
url = env.mkurl("https", "push", "/006-push7.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -132,7 +132,7 @@ class TestStore:
assert '/006/006.css' == promises[0]["request"]["header"][":path"]
# Pushable link header with "nopush" attribute
- def test_400_08(self, env):
+ def test_h2_400_08(self, env):
url = env.mkurl("https", "push", "/006-push8.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -140,7 +140,7 @@ class TestStore:
assert 0 == len(promises)
# 2 H2PushResource config trigger on GET, but not on POST
- def test_400_20(self, env):
+ def test_h2_400_20(self, env):
url = env.mkurl("https", "push", "/006-push20.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -156,7 +156,7 @@ class TestStore:
assert 0 == len(promises)
# H2Push configured Off in location
- def test_400_30(self, env):
+ def test_h2_400_30(self, env):
url = env.mkurl("https", "push", "/006-push30.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -164,7 +164,7 @@ class TestStore:
assert 0 == len(promises)
# - suppress PUSH
- def test_400_50(self, env):
+ def test_h2_400_50(self, env):
url = env.mkurl("https", "push", "/006-push.html")
r = env.nghttp().get(url, options=['-H', 'accept-push-policy: none'])
assert 200 == r.response["status"]
@@ -172,7 +172,7 @@ class TestStore:
assert 0 == len(promises)
# - default pushes desired
- def test_400_51(self, env):
+ def test_h2_400_51(self, env):
url = env.mkurl("https", "push", "/006-push.html")
r = env.nghttp().get(url, options=['-H', 'accept-push-policy: default'])
assert 200 == r.response["status"]
@@ -180,7 +180,7 @@ class TestStore:
assert 1 == len(promises)
# - HEAD pushes desired
- def test_400_52(self, env):
+ def test_h2_400_52(self, env):
url = env.mkurl("https", "push", "/006-push.html")
r = env.nghttp().get(url, options=['-H', 'accept-push-policy: head'])
assert 200 == r.response["status"]
@@ -191,7 +191,7 @@ class TestStore:
assert 0 == len(promises[0]["response"]["body"])
# - fast-load pushes desired
- def test_400_53(self, env):
+ def test_h2_400_53(self, env):
url = env.mkurl("https", "push", "/006-push.html")
r = env.nghttp().get(url, options=['-H', 'accept-push-policy: fast-load'])
assert 200 == r.response["status"]
diff --git a/test/modules/http2/test_401_early_hints.py b/test/modules/http2/test_401_early_hints.py
index 1e7a028a82..984a460c72 100644
--- a/test/modules/http2/test_401_early_hints.py
+++ b/test/modules/http2/test_401_early_hints.py
@@ -1,6 +1,6 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
# The push tests depend on "nghttp"
@@ -8,7 +8,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).start_vhost(
+ H2Conf(env).start_vhost(
env.https_port, "hints", doc_root="htdocs/test1", with_ssl=True
).add(""" Protocols h2 http/1.1"
H2EarlyHints on
@@ -25,7 +25,7 @@ class TestStore:
assert env.apache_restart() == 0
# H2EarlyHints enabled in general, check that it works for H2PushResource
- def test_401_31(self, env):
+ def test_h2_401_31(self, env):
url = env.mkurl("https", "hints", "/006-hints.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
@@ -37,7 +37,7 @@ class TestStore:
assert early["header"]["link"]
# H2EarlyHints enabled in general, but does not trigger on added response headers
- def test_401_32(self, env):
+ def test_h2_401_32(self, env):
url = env.mkurl("https", "hints", "/006-nohints.html")
r = env.nghttp().get(url)
assert 200 == r.response["status"]
diff --git a/test/modules/http2/test_500_proxy.py b/test/modules/http2/test_500_proxy.py
index 00d9b7f21e..32c9b01438 100644
--- a/test/modules/http2/test_500_proxy.py
+++ b/test/modules/http2/test_500_proxy.py
@@ -2,7 +2,7 @@ import os
import re
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@@ -10,7 +10,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- HttpdConf(env).add_vhost_cgi(proxy_self=True).install()
+ H2Conf(env).add_vhost_cgi(proxy_self=True).install()
assert env.apache_restart() == 0
def setup_method(self, method):
@@ -19,7 +19,7 @@ class TestStore:
def teardown_method(self, method):
print("teardown_method: %s" % method.__name__)
- def test_500_01(self, env):
+ def test_h2_500_01(self, env):
url = env.mkurl("https", "cgi", "/proxy/hello.py")
r = env.curl_get(url, 5)
assert 200 == r.response["status"]
@@ -41,11 +41,11 @@ class TestStore:
r2 = env.curl_get(re.sub(r'http:', 'https:', r.response["header"]["location"]))
assert r2.exit_code == 0
assert r2.response["status"] == 200
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r2.response["body"]
- def test_500_10(self, env):
+ def test_h2_500_10(self, env):
self.curl_upload_and_verify(env, "data-1k", ["--http2"])
self.curl_upload_and_verify(env, "data-10k", ["--http2"])
self.curl_upload_and_verify(env, "data-100k", ["--http2"])
@@ -58,17 +58,17 @@ class TestStore:
r = env.nghttp().upload(url, fpath, options=options)
assert r.exit_code == 0
assert 200 <= r.response["status"] < 300
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r.response["body"]
- def test_500_20(self, env):
+ def test_h2_500_20(self, env):
self.nghttp_post_and_verify(env, "data-1k", [])
self.nghttp_post_and_verify(env, "data-10k", [])
self.nghttp_post_and_verify(env, "data-100k", [])
self.nghttp_post_and_verify(env, "data-1m", [])
- def test_500_21(self, env):
+ def test_h2_500_21(self, env):
self.nghttp_post_and_verify(env, "data-1k", ["--no-content-length"])
self.nghttp_post_and_verify(env, "data-10k", ["--no-content-length"])
self.nghttp_post_and_verify(env, "data-100k", ["--no-content-length"])
@@ -88,17 +88,17 @@ class TestStore:
r2 = env.nghttp().get(re.sub(r'http:', 'https:', r.response["header"]["location"]))
assert r2.exit_code == 0
assert r2.response["status"] == 200
- with open(env.test_src(fpath), mode='rb') as file:
+ with open(env.local_src(fpath), mode='rb') as file:
src = file.read()
assert src == r2.response["body"]
- def test_500_22(self, env):
+ def test_h2_500_22(self, env):
self.nghttp_upload_and_verify(env, "data-1k", [])
self.nghttp_upload_and_verify(env, "data-10k", [])
self.nghttp_upload_and_verify(env, "data-100k", [])
self.nghttp_upload_and_verify(env, "data-1m", [])
- def test_500_23(self, env):
+ def test_h2_500_23(self, env):
self.nghttp_upload_and_verify(env, "data-1k", ["--no-content-length"])
self.nghttp_upload_and_verify(env, "data-10k", ["--no-content-length"])
self.nghttp_upload_and_verify(env, "data-100k", ["--no-content-length"])
@@ -114,6 +114,6 @@ class TestStore:
assert 200 <= r.response["status"] < 300
assert r.response["header"]["location"]
- def test_500_24(self, env):
+ def test_h2_500_24(self, env):
for i in range(100):
self.nghttp_upload_stat(env, "data-1k", ["--no-content-length"])
diff --git a/test/modules/http2/test_600_h2proxy.py b/test/modules/http2/test_600_h2proxy.py
index be56d04e31..1741858025 100644
--- a/test/modules/http2/test_600_h2proxy.py
+++ b/test/modules/http2/test_600_h2proxy.py
@@ -1,6 +1,6 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@@ -8,14 +8,14 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi(h2proxy_self=True)
if env.verbosity > 1:
conf.add("LogLevel proxy:trace2 proxy_http2:trace2")
conf.install()
assert env.apache_restart() == 0
- def test_600_01(self, env):
+ def test_h2_600_01(self, env):
url = env.mkurl("https", "cgi", "/h2proxy/hello.py")
r = env.curl_get(url, 5)
assert r.response["status"] == 200
diff --git a/test/modules/http2/test_700_load_get.py b/test/modules/http2/test_700_load_get.py
index 3773bf6764..e3127d58b9 100644
--- a/test/modules/http2/test_700_load_get.py
+++ b/test/modules/http2/test_700_load_get.py
@@ -1,13 +1,13 @@
import pytest
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
- HttpdConf(env).add_vhost_cgi().add_vhost_test1().install()
+ H2Conf(env).add_vhost_cgi().add_vhost_test1().install()
assert env.apache_restart() == 0
def check_h2load_ok(self, env, r, n):
@@ -26,7 +26,7 @@ class TestStore:
@pytest.mark.parametrize("start", [
1000, 80000
])
- def test_700_10(self, env, start):
+ def test_h2_700_10(self, env, start):
text = "X"
chunk = 32
for n in range(0, 5):
@@ -41,7 +41,7 @@ class TestStore:
@pytest.mark.parametrize("conns", [
1, 2, 16, 32
])
- def test_700_11(self, env, conns):
+ def test_h2_700_11(self, env, conns):
text = "X"
start = 1200
chunk = 64
diff --git a/test/modules/http2/test_710_load_post_static.py b/test/modules/http2/test_710_load_post_static.py
index 2b85b0f5eb..aa7081cf64 100644
--- a/test/modules/http2/test_710_load_post_static.py
+++ b/test/modules/http2/test_710_load_post_static.py
@@ -1,7 +1,7 @@
import pytest
import os
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@@ -9,7 +9,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- HttpdConf(env).add_vhost_test1().install()
+ H2Conf(env).add_vhost_test1().install()
assert env.apache_restart() == 0
def check_h2load_ok(self, env, r, n):
@@ -25,7 +25,7 @@ class TestStore:
assert 0 == r.results["h2load"]["status"]["5xx"]
# test POST on static file, slurped in by server
- def test_710_00(self, env):
+ def test_h2_710_00(self, env):
url = env.mkurl("https", "test1", "/index.html")
n = 10
m = 1
@@ -37,7 +37,7 @@ class TestStore:
r = env.run(args)
self.check_h2load_ok(env, r, n)
- def test_710_01(self, env):
+ def test_h2_710_01(self, env):
url = env.mkurl("https", "test1", "/index.html")
n = 1000
m = 100
@@ -49,7 +49,7 @@ class TestStore:
r = env.run(args)
self.check_h2load_ok(env, r, n)
- def test_710_02(self, env):
+ def test_h2_710_02(self, env):
url = env.mkurl("https", "test1", "/index.html")
n = 100
m = 50
diff --git a/test/modules/http2/test_711_load_post_cgi.py b/test/modules/http2/test_711_load_post_cgi.py
index 187abea30d..94cfec3d9d 100644
--- a/test/modules/http2/test_711_load_post_cgi.py
+++ b/test/modules/http2/test_711_load_post_cgi.py
@@ -1,7 +1,7 @@
import pytest
import os
-from h2_conf import HttpdConf
+from .env import H2Conf
class TestStore:
@@ -9,7 +9,7 @@ class TestStore:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- HttpdConf(env).add_vhost_cgi(proxy_self=True, h2proxy_self=True).install()
+ H2Conf(env).add_vhost_cgi(proxy_self=True, h2proxy_self=True).install()
assert env.apache_restart() == 0
def check_h2load_ok(self, env, r, n):
@@ -25,7 +25,7 @@ class TestStore:
assert 0 == r.results["h2load"]["status"]["5xx"]
# test POST on cgi, where input is read
- def test_711_10(self, env):
+ def test_h2_711_10(self, env):
url = env.mkurl("https", "test1", "/echo.py")
n = 100
m = 5
@@ -40,7 +40,7 @@ class TestStore:
self.check_h2load_ok(env, r, n)
# test POST on cgi via http/1.1 proxy, where input is read
- def test_711_11(self, env):
+ def test_h2_711_11(self, env):
url = env.mkurl("https", "test1", "/proxy/echo.py")
n = 100
m = 5
@@ -55,7 +55,7 @@ class TestStore:
self.check_h2load_ok(env, r, n)
# test POST on cgi via h2proxy, where input is read
- def test_711_12(self, env):
+ def test_h2_711_12(self, env):
url = env.mkurl("https", "test1", "/h2proxy/echo.py")
n = 100
m = 5
diff --git a/test/modules/http2/test_712_buffering.py b/test/modules/http2/test_712_buffering.py
index ebf43239b5..12a06c8bb8 100644
--- a/test/modules/http2/test_712_buffering.py
+++ b/test/modules/http2/test_712_buffering.py
@@ -2,8 +2,8 @@ from datetime import timedelta
import pytest
-from h2_conf import HttpdConf
-from h2_curl import CurlPiper
+from .env import H2Conf
+from pyhttpd.curl import CurlPiper
class TestBuffering:
@@ -11,12 +11,12 @@ class TestBuffering:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
env.setup_data_1k_1m()
- conf = HttpdConf(env)
+ conf = H2Conf(env)
conf.add_vhost_cgi(h2proxy_self=True).install()
assert env.apache_restart() == 0
@pytest.mark.skip(reason="this test shows unreliable jitter")
- def test_712_01(self, env):
+ def test_h2_712_01(self, env):
# test gRPC like requests that do not end, but give answers, see #207
#
# this test works like this:
@@ -38,7 +38,7 @@ class TestBuffering:
piper.stutter_check(chunks, stutter)
@pytest.mark.skipif(True, reason="new feature in upcoming http2")
- def test_712_02(self, env):
+ def test_h2_712_02(self, env):
# same as 712_01 but via mod_proxy_http2
#
url = env.mkurl("https", "cgi", "/h2proxy/h2test/echo")
@@ -49,7 +49,7 @@ class TestBuffering:
piper.stutter_check(chunks, stutter)
@pytest.mark.skipif(True, reason="new feature in upcoming http2")
- def test_712_03(self, env):
+ def test_h2_712_03(self, env):
# same as 712_02 but with smaller chunks
#
url = env.mkurl("https", "cgi", "/h2proxy/h2test/echo")
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/cse.js b/test/pyhttpd/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/cse.js
+++ b/test/pyhttpd/__init__.py
diff --git a/test/modules/http2/h2_certs.py b/test/pyhttpd/certs.py
index 82c6b5020a..2ce93c07b2 100644
--- a/test/modules/http2/h2_certs.py
+++ b/test/pyhttpd/certs.py
@@ -148,8 +148,8 @@ class Credentials:
creds = self._store.load_credentials(name=spec.name, key_type=key_type, single_file=spec.single_file) \
if self._store else None
if creds is None:
- creds = H2TestCA.create_credentials(spec=spec, issuer=self, key_type=key_type,
- valid_from=spec.valid_from, valid_to=spec.valid_to)
+ creds = HttpdTestCA.create_credentials(spec=spec, issuer=self, key_type=key_type,
+ valid_from=spec.valid_from, valid_to=spec.valid_to)
if self._store:
self._store.save(creds, single_file=spec.single_file)
@@ -234,14 +234,14 @@ class CertStore:
return None
-class H2TestCA:
+class HttpdTestCA:
@classmethod
def create_root(cls, name: str, store_dir: str, key_type: str = "rsa2048") -> Credentials:
store = CertStore(fpath=store_dir)
creds = store.load_credentials(name="ca", key_type=key_type)
if creds is None:
- creds = H2TestCA._make_ca_credentials(name=name, key_type=key_type)
+ creds = HttpdTestCA._make_ca_credentials(name=name, key_type=key_type)
store.save(creds, name="ca")
creds.set_store(store)
return creds
@@ -255,17 +255,17 @@ class H2TestCA:
:returns: the certificate and private key PEM file paths
"""
if spec.domains and len(spec.domains):
- creds = H2TestCA._make_server_credentials(name=spec.name, domains=spec.domains,
- issuer=issuer, valid_from=valid_from,
- valid_to=valid_to, key_type=key_type)
+ creds = HttpdTestCA._make_server_credentials(name=spec.name, domains=spec.domains,
+ issuer=issuer, valid_from=valid_from,
+ valid_to=valid_to, key_type=key_type)
elif spec.client:
- creds = H2TestCA._make_client_credentials(name=spec.name, issuer=issuer,
- email=spec.email, valid_from=valid_from,
- valid_to=valid_to, key_type=key_type)
+ creds = HttpdTestCA._make_client_credentials(name=spec.name, issuer=issuer,
+ email=spec.email, valid_from=valid_from,
+ valid_to=valid_to, key_type=key_type)
elif spec.name:
- creds = H2TestCA._make_ca_credentials(name=spec.name, issuer=issuer,
- valid_from=valid_from, valid_to=valid_to,
- key_type=key_type)
+ creds = HttpdTestCA._make_ca_credentials(name=spec.name, issuer=issuer,
+ valid_from=valid_from, valid_to=valid_to,
+ key_type=key_type)
else:
raise Exception(f"unrecognized certificate specification: {spec}")
return creds
@@ -397,11 +397,11 @@ class H2TestCA:
else:
issuer_subject = None
issuer_key = pkey
- subject = H2TestCA._make_x509_name(org_name=name, parent=issuer.subject if issuer else None)
- csr = H2TestCA._make_csr(subject=subject,
- issuer_subject=issuer_subject, pkey=pkey,
- valid_from_delta=valid_from, valid_until_delta=valid_to)
- csr = H2TestCA._add_ca_usages(csr)
+ subject = HttpdTestCA._make_x509_name(org_name=name, parent=issuer.subject if issuer else None)
+ csr = HttpdTestCA._make_csr(subject=subject,
+ issuer_subject=issuer_subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = HttpdTestCA._add_ca_usages(csr)
cert = csr.sign(private_key=issuer_key,
algorithm=hashes.SHA256(),
backend=default_backend())
@@ -415,11 +415,11 @@ class H2TestCA:
) -> Credentials:
name = name
pkey = _private_key(key_type=key_type)
- subject = H2TestCA._make_x509_name(common_name=name, parent=issuer.subject)
- csr = H2TestCA._make_csr(subject=subject,
- issuer_subject=issuer.certificate.subject, pkey=pkey,
- valid_from_delta=valid_from, valid_until_delta=valid_to)
- csr = H2TestCA._add_leaf_usages(csr, domains=domains, issuer=issuer)
+ subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer.subject)
+ csr = HttpdTestCA._make_csr(subject=subject,
+ issuer_subject=issuer.certificate.subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = HttpdTestCA._add_leaf_usages(csr, domains=domains, issuer=issuer)
cert = csr.sign(private_key=issuer.private_key,
algorithm=hashes.SHA256(),
backend=default_backend())
@@ -433,11 +433,11 @@ class H2TestCA:
valid_to: timedelta = timedelta(days=89),
) -> Credentials:
pkey = _private_key(key_type=key_type)
- subject = H2TestCA._make_x509_name(common_name=name, parent=issuer.subject)
- csr = H2TestCA._make_csr(subject=subject,
- issuer_subject=issuer.certificate.subject, pkey=pkey,
- valid_from_delta=valid_from, valid_until_delta=valid_to)
- csr = H2TestCA._add_client_usages(csr, issuer=issuer, rfc82name=email)
+ subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer.subject)
+ csr = HttpdTestCA._make_csr(subject=subject,
+ issuer_subject=issuer.certificate.subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = HttpdTestCA._add_client_usages(csr, issuer=issuer, rfc82name=email)
cert = csr.sign(private_key=issuer.private_key,
algorithm=hashes.SHA256(),
backend=default_backend())
diff --git a/test/modules/http2/h2_conf.py b/test/pyhttpd/conf.py
index 4edfaa2dd0..1229929cb8 100644
--- a/test/modules/http2/h2_conf.py
+++ b/test/pyhttpd/conf.py
@@ -1,9 +1,9 @@
-import os
+from pyhttpd.env import HttpdTestEnv
class HttpdConf(object):
- def __init__(self, env, path=None):
+ def __init__(self, env: HttpdTestEnv, path=None):
self.env = env
self._lines = []
self._has_ssl_vhost = False
@@ -64,6 +64,13 @@ class HttpdConf(object):
""")
return self
+ def add_proxy_setup(self):
+ self.add("ProxyStatus on")
+ self.add("ProxyTimeout 5")
+ self.add("SSLProxyEngine on")
+ self.add("SSLProxyVerify none")
+ return self
+
def add_vhost_test1(self, proxy_self=False, h2proxy_self=False, extras=None):
domain = f"test1.{self.env.http_tld}"
if extras and 'base' in extras:
@@ -86,7 +93,7 @@ class HttpdConf(object):
self.add_proxies("test1", proxy_self, h2proxy_self)
self.end_vhost()
return self
-
+
def add_vhost_test2(self, extras=None):
domain = f"test2.{self.env.http_tld}"
if extras and 'base' in extras:
@@ -142,22 +149,3 @@ class HttpdConf(object):
self.add(" LogLevel proxy:info")
self.add(" LogLevel proxy_http:info")
return self
-
- def add_vhost_noh2(self):
- self.start_vhost(self.env.https_port, "noh2", aliases=["noh2-alias"], doc_root="htdocs/noh2", with_ssl=True)
- self.add(f"""
- Protocols http/1.1
- SSLOptions +StdEnvVars""")
- self.end_vhost()
- self.start_vhost(self.env.http_port, "noh2", aliases=["noh2-alias"], doc_root="htdocs/noh2", with_ssl=False)
- self.add(" Protocols http/1.1")
- self.add(" SSLOptions +StdEnvVars")
- self.end_vhost()
- return self
-
- def add_proxy_setup(self):
- self.add("ProxyStatus on")
- self.add("ProxyTimeout 5")
- self.add("SSLProxyEngine on")
- self.add("SSLProxyVerify none")
- return self
diff --git a/test/modules/http2/conf/httpd.conf.template b/test/pyhttpd/conf/httpd.conf.template
index bd0606b402..bd0606b402 100644
--- a/test/modules/http2/conf/httpd.conf.template
+++ b/test/pyhttpd/conf/httpd.conf.template
diff --git a/test/modules/http2/conf/mime.types b/test/pyhttpd/conf/mime.types
index b90b165876..b90b165876 100644
--- a/test/modules/http2/conf/mime.types
+++ b/test/pyhttpd/conf/mime.types
diff --git a/test/modules/http2/conf/test.conf b/test/pyhttpd/conf/test.conf
index 7534af6c87..7534af6c87 100644
--- a/test/modules/http2/conf/test.conf
+++ b/test/pyhttpd/conf/test.conf
diff --git a/test/modules/http2/config.ini.in b/test/pyhttpd/config.ini.in
index 3135a7ec81..da89451a7a 100644
--- a/test/modules/http2/config.ini.in
+++ b/test/pyhttpd/config.ini.in
@@ -23,7 +23,6 @@ name = @progname@
http_port = 40001
https_port = 40002
http_tld = tests.httpd.apache.org
-test_dir = @abs_srcdir@
-test_src_dir = @abs_srcdir@
-server_dir = @abs_srcdir@/gen/apache
-gen_dir = @abs_srcdir@/gen
+test_dir = @abs_srcdir@/..
+server_dir = @abs_srcdir@/../gen/apache
+gen_dir = @abs_srcdir@/../gen
diff --git a/test/modules/http2/h2_curl.py b/test/pyhttpd/curl.py
index fcabe7632a..338e82ce44 100644
--- a/test/modules/http2/h2_curl.py
+++ b/test/pyhttpd/curl.py
@@ -5,12 +5,12 @@ import sys
import time
from threading import Thread
-from h2_env import H2TestEnv
+from .env import HttpdTestEnv
class CurlPiper:
- def __init__(self, env: H2TestEnv, url: str):
+ def __init__(self, env: HttpdTestEnv, url: str):
self.env = env
self.url = url
self.proc = None
diff --git a/test/modules/http2/h2_env.py b/test/pyhttpd/env.py
index 7f879870e7..1efff98c6f 100644
--- a/test/modules/http2/h2_env.py
+++ b/test/pyhttpd/env.py
@@ -16,9 +16,9 @@ import requests
from configparser import ConfigParser, ExtendedInterpolation
from urllib.parse import urlparse
-from h2_certs import Credentials
-from h2_nghttp import Nghttp
-from h2_result import ExecResult
+from .certs import Credentials, HttpdTestCA, CertificateSpec
+from .nghttp import Nghttp
+from .result import ExecResult
log = logging.getLogger(__name__)
@@ -28,7 +28,7 @@ class Dummy:
pass
-class H2TestSetup:
+class HttpdTestSetup:
# the modules we want to load
MODULES = [
@@ -70,15 +70,17 @@ class H2TestSetup:
"proxy_hcheck",
]
- def __init__(self, env: 'H2TestEnv'):
+ def __init__(self, env: 'HttpdTestEnv'):
self.env = env
- def make(self):
+ def make(self, modules: List[str] = None, add_modules: List[str] = None):
self._make_dirs()
self._make_conf()
+ mod_names = modules.copy() if modules else self.MODULES.copy()
+ if add_modules:
+ mod_names.extend(add_modules)
+ self._make_modules_conf(modules=mod_names)
self._make_htdocs()
- self._make_h2test()
- self._make_modules_conf()
def _make_dirs(self):
if os.path.exists(self.env.gen_dir):
@@ -88,7 +90,8 @@ class H2TestSetup:
os.makedirs(self.env.server_logs_dir)
def _make_conf(self):
- conf_src_dir = os.path.join(self.env.test_dir, 'conf')
+ our_dir = os.path.dirname(inspect.getfile(Dummy))
+ conf_src_dir = os.path.join(our_dir, 'conf')
conf_dest_dir = os.path.join(self.env.server_dir, 'conf')
if not os.path.exists(conf_dest_dir):
os.makedirs(conf_dest_dir)
@@ -102,17 +105,27 @@ class H2TestSetup:
def _make_template(self, src, dest):
var_map = dict()
- for name, value in self.env.__class__.__dict__.items():
+ for name, value in HttpdTestEnv.__dict__.items():
if isinstance(value, property):
var_map[name] = value.fget(self.env)
t = Template(''.join(open(src).readlines()))
with open(dest, 'w') as fd:
fd.write(t.substitute(var_map))
+ def _make_modules_conf(self, modules: List[str]):
+ modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
+ with open(modules_conf, 'w') as fd:
+ # issue load directives for all modules we want that are shared
+ for m in modules:
+ mod_path = os.path.join(self.env.libexec_dir, f"mod_{m}.so")
+ if os.path.isfile(mod_path):
+ fd.write(f"LoadModule {m}_module \"{mod_path}\"\n")
+
def _make_htdocs(self):
+ our_dir = os.path.dirname(inspect.getfile(Dummy))
if not os.path.exists(self.env.server_docs_dir):
os.makedirs(self.env.server_docs_dir)
- shutil.copytree(os.path.join(self.env.test_dir, 'htdocs'),
+ shutil.copytree(os.path.join(our_dir, 'htdocs'),
os.path.join(self.env.server_dir, 'htdocs'),
dirs_exist_ok=True)
cgi_dir = os.path.join(self.env.server_dir, 'htdocs/cgi')
@@ -122,35 +135,16 @@ class H2TestSetup:
st = os.stat(cgi_file)
os.chmod(cgi_file, st.st_mode | stat.S_IEXEC)
- def _make_h2test(self):
- p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'],
- capture_output=True,
- cwd=os.path.join(self.env.test_dir, 'mod_h2test'))
- rv = p.returncode
- if rv != 0:
- log.error(f"compiling md_h2test failed: {p.stderr}")
- raise Exception(f"compiling md_h2test failed: {p.stderr}")
- def _make_modules_conf(self):
- modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
- with open(modules_conf, 'w') as fd:
- # issue load directives for all modules we want that are shared
- for m in self.MODULES:
- mod_path = os.path.join(self.env.libexec_dir, f"mod_{m}.so")
- if os.path.isfile(mod_path):
- fd.write(f"LoadModule {m}_module \"{mod_path}\"\n")
- for m in ["http2", "proxy_http2"]:
- fd.write(f"LoadModule {m}_module \"{self.env.libexec_dir}/mod_{m}.so\"\n")
- # load our test module which is not installed
- fd.write(f"LoadModule h2test_module \"{self.env.test_dir}/mod_h2test/.libs/mod_h2test.so\"\n")
-
-
-class H2TestEnv:
+class HttpdTestEnv:
- def __init__(self, pytestconfig=None, setup_dirs=True):
- our_dir = os.path.dirname(inspect.getfile(Dummy))
+ def __init__(self, pytestconfig=None,
+ local_dir=None, add_base_conf: str = None,
+ interesting_modules: List[str] = None):
+ self._our_dir = os.path.dirname(inspect.getfile(Dummy))
+ self._local_dir = local_dir if local_dir else self._our_dir
self.config = ConfigParser(interpolation=ExtendedInterpolation())
- self.config.read(os.path.join(our_dir, 'config.ini'))
+ self.config.read(os.path.join(self._our_dir, 'config.ini'))
self._apxs = self.config.get('global', 'apxs')
self._prefix = self.config.get('global', 'prefix')
@@ -160,13 +154,11 @@ class H2TestEnv:
self._curl = self.config.get('global', 'curl_bin')
self._nghttp = self.config.get('global', 'nghttp')
self._h2load = self.config.get('global', 'h2load')
- self._ca = None
self._http_port = int(self.config.get('test', 'http_port'))
self._https_port = int(self.config.get('test', 'https_port'))
self._http_tld = self.config.get('test', 'http_tld')
self._test_dir = self.config.get('test', 'test_dir')
- self._test_src_dir = self.config.get('test', 'test_src_dir')
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")
@@ -176,23 +168,6 @@ class H2TestEnv:
self._server_error_log = os.path.join(self._server_logs_dir, "error_log")
self._dso_modules = self.config.get('global', 'dso_modules').split(' ')
- self._domains = [
- f"test1.{self._http_tld}",
- f"test2.{self._http_tld}",
- f"test3.{self._http_tld}",
- f"cgi.{self._http_tld}",
- f"push.{self._http_tld}",
- f"hints.{self._http_tld}",
- f"ssl.{self._http_tld}",
- f"pad0.{self._http_tld}",
- f"pad1.{self._http_tld}",
- f"pad2.{self._http_tld}",
- f"pad3.{self._http_tld}",
- f"pad8.{self._http_tld}",
- ]
- self._domains_noh2 = [
- f"noh2.{self._http_tld}",
- ]
self._mpm_type = os.environ['MPM'] if 'MPM' in os.environ else 'event'
self._httpd_addr = "127.0.0.1"
@@ -202,25 +177,38 @@ class H2TestEnv:
self._test_conf = os.path.join(self._server_conf_dir, "test.conf")
self._httpd_base_conf = f"""
LoadModule mpm_{self.mpm_type}_module \"{self.libexec_dir}/mod_mpm_{self.mpm_type}.so\"
- H2MinWorkers 1
- H2MaxWorkers 64
- SSLSessionCache "shmcb:ssl_gcache_data(32000)"
+ <IfModule mod_ssl.c>
+ SSLSessionCache "shmcb:ssl_gcache_data(32000)"
+ </IfModule>
"""
+ if add_base_conf:
+ self._httpd_base_conf += f"\n{add_base_conf}"
+
self._verbosity = pytestconfig.option.verbose if pytestconfig is not None else 0
if self._verbosity >= 2:
+ log_level = "trace2"
self._httpd_base_conf += f"""
- LogLevel http2:trace2 proxy_http2:info h2test:trace2
LogLevel core:trace5 mpm_{self.mpm_type}:trace5
"""
elif self._verbosity >= 1:
- self._httpd_base_conf += "LogLevel http2:debug proxy_http2:debug h2test:debug"
+ log_level = "debug"
else:
- self._httpd_base_conf += "LogLevel http2:info proxy_http2:info"
+ log_level = "info"
+ if interesting_modules:
+ self._httpd_base_conf += "\nLogLevel"
+ for name in interesting_modules:
+ self._httpd_base_conf += f" {name}:{log_level}"
+ self._httpd_base_conf += "\n"
+
+ self._ca = None
+ self._cert_specs = [CertificateSpec(domains=[
+ f"test1.{self._http_tld}",
+ f"test2.{self._http_tld}",
+ f"test3.{self._http_tld}",
+ f"cgi.{self._http_tld}",
+ ], key_type='rsa4096')]
self._verify_certs = False
- if setup_dirs:
- self._setup = H2TestSetup(env=self)
- self._setup.make()
@property
def apxs(self) -> str:
@@ -251,18 +239,6 @@ class H2TestEnv:
return self._http_tld
@property
- def domain_test1(self) -> str:
- return self._domains[0]
-
- @property
- def domains(self) -> List[str]:
- return self._domains
-
- @property
- def domains_noh2(self) -> List[str]:
- return self._domains_noh2
-
- @property
def http_base_url(self) -> str:
return self._http_base
@@ -275,12 +251,12 @@ class H2TestEnv:
return self._gen_dir
@property
- def test_dir(self) -> str:
- return self._test_dir
+ def local_dir(self) -> str:
+ return self._local_dir
@property
- def test_src_dir(self) -> str:
- return self._test_src_dir
+ def test_dir(self) -> str:
+ return self._test_dir
@property
def server_dir(self) -> str:
@@ -310,6 +286,12 @@ class H2TestEnv:
def httpd_base_conf(self) -> str:
return self._httpd_base_conf
+ def local_src(self, path):
+ return os.path.join(self.local_dir, path)
+
+ def htdocs_src(self, path):
+ return os.path.join(self._our_dir, 'htdocs', path)
+
@property
def h2load(self) -> str:
return self._h2load
@@ -318,13 +300,19 @@ class H2TestEnv:
def ca(self) -> Credentials:
return self._ca
- def set_ca(self, ca: Credentials):
- self._ca = ca
+ def add_cert_specs(self, specs: List[CertificateSpec]):
+ self._cert_specs.extend(specs)
+
+ def issue_certs(self):
+ if self._ca is None:
+ self._ca = HttpdTestCA.create_root(name=self.http_tld,
+ store_dir=os.path.join(self.server_dir, 'ca'), key_type="rsa4096")
+ self._ca.issue_certs(self._cert_specs)
def get_credentials_for_name(self, dns_name) -> List['Credentials']:
- for domains in [self._domains, self._domains_noh2]:
- if dns_name in domains:
- return self.ca.get_credentials_for_name(domains[0])
+ for spec in self._cert_specs:
+ if dns_name in spec.domains:
+ return self.ca.get_credentials_for_name(spec.domains[0])
return []
def has_h2load(self):
@@ -356,9 +344,6 @@ class H2TestEnv:
if not os.path.exists(path):
return os.makedirs(path)
- def test_src(self, path):
- return os.path.join(self._test_src_dir, path)
-
def run(self, args) -> ExecResult:
log.debug("execute: %s", " ".join(args))
start = datetime.now()
@@ -615,18 +600,3 @@ class H2TestEnv:
}
run.add_results({"h2load": stats})
return run
-
- def setup_data_1k_1m(self):
- s100 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n"
- with open(os.path.join(self.gen_dir, "data-1k"), 'w') as f:
- for i in range(10):
- f.write(s100)
- with open(os.path.join(self.gen_dir, "data-10k"), 'w') as f:
- for i in range(100):
- f.write(s100)
- with open(os.path.join(self.gen_dir, "data-100k"), 'w') as f:
- for i in range(1000):
- f.write(s100)
- with open(os.path.join(self.gen_dir, "data-1m"), 'w') as f:
- for i in range(10000):
- f.write(s100)
diff --git a/test/modules/http2/htdocs/alive.json b/test/pyhttpd/htdocs/alive.json
index 2239ee2ee7..2239ee2ee7 100644
--- a/test/modules/http2/htdocs/alive.json
+++ b/test/pyhttpd/htdocs/alive.json
diff --git a/test/modules/http2/htdocs/cgi/echo.py b/test/pyhttpd/htdocs/cgi/echo.py
index 5ffe6ed823..5ffe6ed823 100644
--- a/test/modules/http2/htdocs/cgi/echo.py
+++ b/test/pyhttpd/htdocs/cgi/echo.py
diff --git a/test/modules/http2/htdocs/cgi/echohd.py b/test/pyhttpd/htdocs/cgi/echohd.py
index 371ae8b0f7..371ae8b0f7 100644
--- a/test/modules/http2/htdocs/cgi/echohd.py
+++ b/test/pyhttpd/htdocs/cgi/echohd.py
diff --git a/test/modules/http2/htdocs/cgi/env.py b/test/pyhttpd/htdocs/cgi/env.py
index 5c9c0b1adb..5c9c0b1adb 100644
--- a/test/modules/http2/htdocs/cgi/env.py
+++ b/test/pyhttpd/htdocs/cgi/env.py
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/css.css b/test/pyhttpd/htdocs/cgi/files/empty.txt
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/css.css
+++ b/test/pyhttpd/htdocs/cgi/files/empty.txt
diff --git a/test/modules/http2/htdocs/cgi/hecho.py b/test/pyhttpd/htdocs/cgi/hecho.py
index 5c1f79a302..5c1f79a302 100644
--- a/test/modules/http2/htdocs/cgi/hecho.py
+++ b/test/pyhttpd/htdocs/cgi/hecho.py
diff --git a/test/modules/http2/htdocs/cgi/hello.py b/test/pyhttpd/htdocs/cgi/hello.py
index 191acb2fed..191acb2fed 100644
--- a/test/modules/http2/htdocs/cgi/hello.py
+++ b/test/pyhttpd/htdocs/cgi/hello.py
diff --git a/test/modules/http2/htdocs/cgi/mnot164.py b/test/pyhttpd/htdocs/cgi/mnot164.py
index 949b0f195b..949b0f195b 100644
--- a/test/modules/http2/htdocs/cgi/mnot164.py
+++ b/test/pyhttpd/htdocs/cgi/mnot164.py
diff --git a/test/modules/http2/htdocs/cgi/necho.py b/test/pyhttpd/htdocs/cgi/necho.py
index b9249b8969..b9249b8969 100644
--- a/test/modules/http2/htdocs/cgi/necho.py
+++ b/test/pyhttpd/htdocs/cgi/necho.py
diff --git a/test/modules/http2/htdocs/cgi/upload.py b/test/pyhttpd/htdocs/cgi/upload.py
index 2c8d63aa10..2c8d63aa10 100644
--- a/test/modules/http2/htdocs/cgi/upload.py
+++ b/test/pyhttpd/htdocs/cgi/upload.py
diff --git a/test/modules/http2/htdocs/forbidden.html b/test/pyhttpd/htdocs/forbidden.html
index e186310c73..e186310c73 100644
--- a/test/modules/http2/htdocs/forbidden.html
+++ b/test/pyhttpd/htdocs/forbidden.html
diff --git a/test/modules/http2/htdocs/index.html b/test/pyhttpd/htdocs/index.html
index 3c07626144..3c07626144 100644
--- a/test/modules/http2/htdocs/index.html
+++ b/test/pyhttpd/htdocs/index.html
diff --git a/test/modules/http2/htdocs/noh2/alive.json b/test/pyhttpd/htdocs/noh2/alive.json
index 7b54893ee5..7b54893ee5 100644
--- a/test/modules/http2/htdocs/noh2/alive.json
+++ b/test/pyhttpd/htdocs/noh2/alive.json
diff --git a/test/modules/http2/htdocs/noh2/index.html b/test/pyhttpd/htdocs/noh2/index.html
index 696068e9dc..696068e9dc 100644
--- a/test/modules/http2/htdocs/noh2/index.html
+++ b/test/pyhttpd/htdocs/noh2/index.html
diff --git a/test/modules/http2/htdocs/test1/001.html b/test/pyhttpd/htdocs/test1/001.html
index 184952d28c..184952d28c 100644
--- a/test/modules/http2/htdocs/test1/001.html
+++ b/test/pyhttpd/htdocs/test1/001.html
diff --git a/test/modules/http2/htdocs/test1/002.jpg b/test/pyhttpd/htdocs/test1/002.jpg
index 3feefb070a..3feefb070a 100644
--- a/test/modules/http2/htdocs/test1/002.jpg
+++ b/test/pyhttpd/htdocs/test1/002.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/003.html b/test/pyhttpd/htdocs/test1/003.html
index d5b08c52bb..d5b08c52bb 100644
--- a/test/modules/http2/htdocs/test1/003.html
+++ b/test/pyhttpd/htdocs/test1/003.html
diff --git a/test/modules/http2/htdocs/test1/003/003_img.jpg b/test/pyhttpd/htdocs/test1/003/003_img.jpg
index 3feefb070a..3feefb070a 100644
--- a/test/modules/http2/htdocs/test1/003/003_img.jpg
+++ b/test/pyhttpd/htdocs/test1/003/003_img.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/004.html b/test/pyhttpd/htdocs/test1/004.html
index 768cb825b4..768cb825b4 100644
--- a/test/modules/http2/htdocs/test1/004.html
+++ b/test/pyhttpd/htdocs/test1/004.html
diff --git a/test/modules/http2/htdocs/test1/004/gophertiles.jpg b/test/pyhttpd/htdocs/test1/004/gophertiles.jpg
index e45ac3b02b..e45ac3b02b 100644
--- a/test/modules/http2/htdocs/test1/004/gophertiles.jpg
+++ b/test/pyhttpd/htdocs/test1/004/gophertiles.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/006.html b/test/pyhttpd/htdocs/test1/006.html
index 6b730255a1..6b730255a1 100644
--- a/test/modules/http2/htdocs/test1/006.html
+++ b/test/pyhttpd/htdocs/test1/006.html
diff --git a/test/modules/http2/htdocs/test1/006/006.css b/test/pyhttpd/htdocs/test1/006/006.css
index de6aa5fd18..de6aa5fd18 100644
--- a/test/modules/http2/htdocs/test1/006/006.css
+++ b/test/pyhttpd/htdocs/test1/006/006.css
diff --git a/test/modules/http2/htdocs/test1/006/006.js b/test/pyhttpd/htdocs/test1/006/006.js
index b450067b53..b450067b53 100644
--- a/test/modules/http2/htdocs/test1/006/006.js
+++ b/test/pyhttpd/htdocs/test1/006/006.js
diff --git a/test/modules/http2/htdocs/test1/006/header.html b/test/pyhttpd/htdocs/test1/006/header.html
index bace20ee88..bace20ee88 100644
--- a/test/modules/http2/htdocs/test1/006/header.html
+++ b/test/pyhttpd/htdocs/test1/006/header.html
diff --git a/test/modules/http2/htdocs/test1/007.html b/test/pyhttpd/htdocs/test1/007.html
index 4db93e4c5a..4db93e4c5a 100644
--- a/test/modules/http2/htdocs/test1/007.html
+++ b/test/pyhttpd/htdocs/test1/007.html
diff --git a/test/modules/http2/htdocs/test1/007/007.py b/test/pyhttpd/htdocs/test1/007/007.py
index 02b5466f96..02b5466f96 100644
--- a/test/modules/http2/htdocs/test1/007/007.py
+++ b/test/pyhttpd/htdocs/test1/007/007.py
diff --git a/test/modules/http2/htdocs/test1/009.py b/test/pyhttpd/htdocs/test1/009.py
index 8fd9095af3..8fd9095af3 100644
--- a/test/modules/http2/htdocs/test1/009.py
+++ b/test/pyhttpd/htdocs/test1/009.py
diff --git a/test/modules/http2/htdocs/test1/alive.json b/test/pyhttpd/htdocs/test1/alive.json
index 93e7f95972..93e7f95972 100644
--- a/test/modules/http2/htdocs/test1/alive.json
+++ b/test/pyhttpd/htdocs/test1/alive.json
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/ant.jpg b/test/pyhttpd/htdocs/test1/apache.org-files/ant.jpg
index 2ebd7ad717..2ebd7ad717 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/ant.jpg
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/ant.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/asf_logo.png b/test/pyhttpd/htdocs/test1/apache.org-files/asf_logo.png
index 07c0113c7b..07c0113c7b 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/asf_logo.png
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/asf_logo.png
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/async-ads.js b/test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js
index eee04abfaf..eee04abfaf 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/async-ads.js
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/async-ads.js.br b/test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js.br
index 6dc14a36f9..6dc14a36f9 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/async-ads.js.br
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/async-ads.js.br
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/jsapi.js b/test/pyhttpd/htdocs/test1/apache.org-files/cse.js
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/jsapi.js
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/cse.js
diff --git a/test/modules/http2/htdocs/test2/10%abnormal.txt b/test/pyhttpd/htdocs/test1/apache.org-files/css.css
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/test2/10%abnormal.txt
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/css.css
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/default.css b/test/pyhttpd/htdocs/test1/apache.org-files/default.css
index 6e2e2c4dad..6e2e2c4dad 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/default.css
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/default.css
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/defaulten.css b/test/pyhttpd/htdocs/test1/apache.org-files/defaulten.css
index cd2c1c6264..cd2c1c6264 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/defaulten.css
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/defaulten.css
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/defaulten.js b/test/pyhttpd/htdocs/test1/apache.org-files/defaulten.js
index 1afe448ec5..1afe448ec5 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/defaulten.js
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/defaulten.js
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/jquery-2.js b/test/pyhttpd/htdocs/test1/apache.org-files/jquery-2.js
index dc93a13e88..dc93a13e88 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/jquery-2.js
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/jquery-2.js
diff --git a/test/modules/http2/htdocs/test2/x%2f.test b/test/pyhttpd/htdocs/test1/apache.org-files/jsapi.js
index e69de29bb2..e69de29bb2 100644
--- a/test/modules/http2/htdocs/test2/x%2f.test
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/jsapi.js
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/min.css b/test/pyhttpd/htdocs/test1/apache.org-files/min.css
index 908a2e8b8c..908a2e8b8c 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/min.css
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/min.css
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/min.css.br b/test/pyhttpd/htdocs/test1/apache.org-files/min.css.br
index a58ad52f3d..a58ad52f3d 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/min.css.br
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/min.css.br
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/mrunit.jpg b/test/pyhttpd/htdocs/test1/apache.org-files/mrunit.jpg
index 7e5093da53..7e5093da53 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/mrunit.jpg
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/mrunit.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/search_box_icon.png b/test/pyhttpd/htdocs/test1/apache.org-files/search_box_icon.png
index bae336a45a..bae336a45a 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/search_box_icon.png
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/search_box_icon.png
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/small-logo.png b/test/pyhttpd/htdocs/test1/apache.org-files/small-logo.png
index b2d6ebb807..b2d6ebb807 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/small-logo.png
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/small-logo.png
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/styles.css b/test/pyhttpd/htdocs/test1/apache.org-files/styles.css
index a5e5565c63..a5e5565c63 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/styles.css
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/styles.css
diff --git a/test/modules/http2/htdocs/test1/apache.org-files/synapse.jpg b/test/pyhttpd/htdocs/test1/apache.org-files/synapse.jpg
index fb2f4570ff..fb2f4570ff 100644
--- a/test/modules/http2/htdocs/test1/apache.org-files/synapse.jpg
+++ b/test/pyhttpd/htdocs/test1/apache.org-files/synapse.jpg
Binary files differ
diff --git a/test/modules/http2/htdocs/test1/apache.org.html b/test/pyhttpd/htdocs/test1/apache.org.html
index 0265fcc174..0265fcc174 100644
--- a/test/modules/http2/htdocs/test1/apache.org.html
+++ b/test/pyhttpd/htdocs/test1/apache.org.html
diff --git a/test/modules/http2/htdocs/test1/index.html b/test/pyhttpd/htdocs/test1/index.html
index 9f752b52f0..9f752b52f0 100644
--- a/test/modules/http2/htdocs/test1/index.html
+++ b/test/pyhttpd/htdocs/test1/index.html
diff --git a/test/modules/http2/htdocs/test2/006/006.css b/test/pyhttpd/htdocs/test2/006/006.css
index de6aa5fd18..de6aa5fd18 100755
--- a/test/modules/http2/htdocs/test2/006/006.css
+++ b/test/pyhttpd/htdocs/test2/006/006.css
diff --git a/test/pyhttpd/htdocs/test2/10%abnormal.txt b/test/pyhttpd/htdocs/test2/10%abnormal.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/pyhttpd/htdocs/test2/10%abnormal.txt
diff --git a/test/modules/http2/htdocs/test2/alive.json b/test/pyhttpd/htdocs/test2/alive.json
index 6a742235fa..6a742235fa 100644
--- a/test/modules/http2/htdocs/test2/alive.json
+++ b/test/pyhttpd/htdocs/test2/alive.json
diff --git a/test/pyhttpd/htdocs/test2/x%2f.test b/test/pyhttpd/htdocs/test2/x%2f.test
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/pyhttpd/htdocs/test2/x%2f.test
diff --git a/test/modules/http2/h2_nghttp.py b/test/pyhttpd/nghttp.py
index d06798e868..362b2fdd49 100644
--- a/test/modules/http2/h2_nghttp.py
+++ b/test/pyhttpd/nghttp.py
@@ -6,7 +6,7 @@ from typing import Dict
from urllib.parse import urlparse
-from h2_result import ExecResult
+from .result import ExecResult
def _get_path(x):
diff --git a/test/modules/http2/h2_result.py b/test/pyhttpd/result.py
index 06fc9e5300..06fc9e5300 100644
--- a/test/modules/http2/h2_result.py
+++ b/test/pyhttpd/result.py