]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tests/http: fix HTTP/3 proxy pytest failures with h2o
authorAritra Basu <aritrbas+gh@cisco.com>
Thu, 28 May 2026 00:35:44 +0000 (20:35 -0400)
committerViktor Szakats <commit@vsz.me>
Thu, 28 May 2026 08:38:58 +0000 (10:38 +0200)
Fix pytest failures in HTTP/3 proxy tests when h2o is not installed,
misconfigured, or fails to start at runtime.

This prevents:
- FileNotFoundError when h2o document root does not exist
- Fixture setup errors when h2o is configured but cannot start
- Unused test data file creation when h2o is absent or broken
- CI aborts on systems where h2o exists but is not runnable

Bug: https://github.com/curl/curl/pull/21789#issuecomment-4559098879
Bug: https://github.com/curl/curl/pull/21789#issuecomment-4559161907

Follow-up to e78b1b3eccfa6a2e367a1225ea1b66dafcdac3c4 #21153

Closes #21791

tests/http/conftest.py
tests/http/test_60_h3_proxy.py
tests/http/testenv/env.py
tests/http/testenv/h2o.py

index 0de5c1a8b9e06e20ef18f3bd4d8720b293db6141..5275b91bf969298b4475a071b236909b1d12c249 100644 (file)
@@ -172,7 +172,9 @@ def h2o_server(env) -> Generator[Union[H2oServer, bool], None, None]:
     h2o = H2oServer(env=env)
     if env.have_h2o():
         h2o.clear_logs()
-        assert h2o.initial_start()
+        if not h2o.initial_start():
+            h2o_logs = "\n".join(h2o.dump_logs())
+            pytest.skip(f"h2o server failed to start\n{h2o_logs}")
         yield h2o
         h2o.stop()
     else:
@@ -184,7 +186,9 @@ def h2o_proxy(env) -> Generator[Union[H2oProxy, bool], None, None]:
     h2o = H2oProxy(env=env)
     if env.have_h2o():
         h2o.clear_logs()
-        assert h2o.initial_start()
+        if not h2o.initial_start():
+            h2o_logs = "\n".join(h2o.dump_logs())
+            pytest.skip(f"h2o proxy failed to start\n{h2o_logs}")
         yield h2o
         h2o.stop()
     else:
index def32a6fe7750a32a13c84eb3e00dbcd031c67ba..786c6e7bf274ab93e6df7f6635d5c9f9ab6fefd0 100644 (file)
@@ -359,10 +359,11 @@ class TestH3ProxyRobustness:
     pytestmark = H3_PROXY_COMMON_MARKS + [MARK_NEEDS_H2O]
 
     @pytest.fixture(autouse=True, scope="class")
-    def _class_scope(self, env):
-        doc_root = os.path.join(env.gen_dir, "docs")
+    def _class_scope(self, env, h2o_server):
+        if not env.have_h2o():
+            pytest.skip("h2o not available")
         env.make_data_file(
-            indir=doc_root, fname="proxy-drop-20m", fsize=20 * 1024 * 1024
+            indir=h2o_server.docs_dir, fname="proxy-drop-20m", fsize=20 * 1024 * 1024
         )
 
     def test_60_05_graceful_shutdown(
@@ -451,10 +452,11 @@ class TestH3ProxyDataTransfer:
     pytestmark = H3_PROXY_COMMON_MARKS + [MARK_NEEDS_H2O]
 
     @pytest.fixture(autouse=True, scope="class")
-    def _class_scope(self, env):
-        doc_root = os.path.join(env.gen_dir, "docs")
-        env.make_data_file(indir=doc_root, fname="download-1m", fsize=1 * 1024 * 1024)
-        env.make_data_file(indir=doc_root, fname="download-10m", fsize=10 * 1024 * 1024)
+    def _class_scope(self, env, h2o_server):
+        if not env.have_h2o():
+            pytest.skip("h2o not available")
+        env.make_data_file(indir=h2o_server.docs_dir, fname="download-1m", fsize=1 * 1024 * 1024)
+        env.make_data_file(indir=h2o_server.docs_dir, fname="download-10m", fsize=10 * 1024 * 1024)
         env.make_data_file(indir=env.gen_dir, fname="upload-2m", fsize=2 * 1024 * 1024)
 
     def test_60_07_large_download(self, env: Env, h2o_server, h2o_proxy):
@@ -558,11 +560,12 @@ class TestH3ProxyUdpTunnel:
     pytestmark = H3_PROXY_COMMON_MARKS
 
     @pytest.fixture(autouse=True, scope="class")
-    def _class_scope(self, env):
-        doc_root = os.path.join(env.gen_dir, "docs")
-        env.make_data_file(indir=doc_root, fname="download-1400", fsize=1400)
-        env.make_data_file(indir=doc_root, fname="download-1m", fsize=1 * 1024 * 1024)
-        env.make_data_file(indir=doc_root, fname="download-10m", fsize=10 * 1024 * 1024)
+    def _class_scope(self, env, h2o_server):
+        if not env.have_h2o():
+            return
+        env.make_data_file(indir=h2o_server.docs_dir, fname="download-1400", fsize=1400)
+        env.make_data_file(indir=h2o_server.docs_dir, fname="download-1m", fsize=1 * 1024 * 1024)
+        env.make_data_file(indir=h2o_server.docs_dir, fname="download-10m", fsize=10 * 1024 * 1024)
 
     @MARK_NEEDS_H2O
     @pytest.mark.parametrize(
index 3b43cfce0d10607d4c5f43f1545aa5ea9f42cf64..093092b4c5dea229f196c53c71479aff7b54362e 100644 (file)
@@ -909,6 +909,7 @@ class Env:
     ) -> str:
         if line_length < 11:
             raise RuntimeError("line_length less than 11 not supported")
+        os.makedirs(indir, exist_ok=True)
         fpath = os.path.join(indir, fname)
         s10 = "0123456789"
         s = round((line_length / 10) + 1) * s10
index 6a55f4882bf7f3856f2fbccb4981c8e0a8bf007e..c67aaf18886cd1df445d73d55e675e2c3809df9a 100644 (file)
@@ -241,6 +241,11 @@ class H2oServer(H2o):
         super().__init__(
             env=env, name="h2o-server", domain=env.domain1, cred_name=env.domain1
         )
+        self._docs_dir = os.path.join(self.env.gen_dir, "docs")
+
+    @property
+    def docs_dir(self):
+        return self._docs_dir
 
     def initial_start(self):
         super().initial_start()
@@ -261,11 +266,10 @@ class H2oServer(H2o):
     def write_config(self):
         creds = self.env.get_credentials(self._cred_name)
         assert creds  # convince pytype this is not None
-        doc_root = os.path.join(self.env.gen_dir, "docs")
-        self._mkpath(doc_root)
+        self._mkpath(self._docs_dir)
         self._mkpath(self._run_dir)
         # Create a simple test file
-        with open(os.path.join(doc_root, "data.json"), "w") as f:
+        with open(os.path.join(self._docs_dir, "data.json"), "w") as f:
             f.write('{"message": "Hello from h2o HTTP/3 server"}\n')
         with open(self._conf_file, "w") as fd:
             fd.write(f"""# h2o HTTP/3 server configuration
@@ -289,7 +293,7 @@ hosts:
   "{self._domain}":
     paths:
       "/":
-        file.dir: {doc_root}
+        file.dir: {self._docs_dir}
 
 http2-reprioritize-blocking-assets: ON