pytest: skip specific tests for no-verbose builds

Detect via curlinfo if curl has verbose strings disabled, and skip
tests that require it.

Also:
- cmake: make pytests depend on curlinfo.

Cherry-picked from #18797
Closes #18801
This commit is contained in:
Viktor Szakats 2025-10-01 23:27:45 +02:00
parent 632c5ee897
commit 34dc762cef
No known key found for this signature in database
GPG Key ID: B5ABD165E2AEF201
12 changed files with 48 additions and 3 deletions

View File

@ -31,7 +31,7 @@ configure_file("config.in" "${CMAKE_CURRENT_BINARY_DIR}/config" @ONLY)
add_custom_target(testdeps)
if(BUILD_CURL_EXE)
add_dependencies(testdeps curlinfo)
add_dependencies(testdeps "curlinfo")
endif()
if(CURL_CLANG_TIDY)
@ -57,7 +57,7 @@ function(curl_add_runtests _targetname _test_flags)
# skipping them, MSBuild doing a re-evaluation, and actually rebuilding them.
if(NOT _targetname STREQUAL "test-ci")
if(BUILD_CURL_EXE)
list(APPEND _depends ${EXE_NAME})
list(APPEND _depends "${EXE_NAME}")
endif()
list(APPEND _depends "testdeps")
endif()
@ -86,7 +86,7 @@ function(curl_add_pytests _targetname _test_flags)
set(_depends "")
if(NOT _targetname STREQUAL "pytest-ci")
if(BUILD_CURL_EXE)
list(APPEND _depends ${EXE_NAME})
list(APPEND _depends "${EXE_NAME}" "curlinfo")
endif()
list(APPEND _depends "libtests")
endif()

View File

@ -600,6 +600,7 @@ class TestDownload:
# nghttpx is the only server we have that supports TLS early data
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_02_32_earlydata(self, env: Env, httpd, nghttpx, proto):
if not env.curl_can_early_data():
@ -654,6 +655,8 @@ class TestDownload:
def test_02_33_max_host_conns(self, env: Env, httpd, nghttpx, proto, max_host_conns):
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
count = 50
@ -692,6 +695,8 @@ class TestDownload:
def test_02_34_max_total_conns(self, env: Env, httpd, nghttpx, proto, max_total_conns):
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
count = 50

View File

@ -105,6 +105,7 @@ class TestEyeballs:
# check timers when trying 3 unresponsive addresses
@pytest.mark.skipif(condition=not Env.curl_has_feature('IPv6'),
reason='curl lacks ipv6 support')
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_06_13_timers(self, env: Env):
curl = CurlClient(env=env)
# ipv6 0100::/64 is supposed to go into the void (rfc6666)

View File

@ -151,6 +151,7 @@ class TestProxy:
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_06_proxytunnel_https(self, env: Env, httpd, nghttpx_fwd, proto, tunnel):
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
pytest.skip('only supported with nghttp2')
@ -169,6 +170,7 @@ class TestProxy:
# download many https: with proto via https: proxytunnel
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason="curl without SSL")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
@pytest.mark.parametrize("fname, fcount", [
@ -209,6 +211,7 @@ class TestProxy:
['data-1m', 5]
])
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
def test_10_08_upload_seq_large(self, env: Env, httpd, nghttpx, proto,
tunnel, fname, fcount):
@ -236,6 +239,7 @@ class TestProxy:
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_09_reuse_server(self, env: Env, httpd, nghttpx_fwd, tunnel):
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
pytest.skip('only supported with nghttp2')
@ -259,6 +263,7 @@ class TestProxy:
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_10_reuse_proxy(self, env: Env, httpd, nghttpx_fwd, tunnel):
# url twice via https: proxy separated with '--next', will reuse
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
@ -287,6 +292,7 @@ class TestProxy:
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_11_noreuse_proxy_https(self, env: Env, httpd, nghttpx_fwd, tunnel):
# different --proxy-tls13-ciphers, no reuse of connection for https:
curl = CurlClient(env=env)
@ -313,6 +319,7 @@ class TestProxy:
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_12_noreuse_proxy_http(self, env: Env, httpd, nghttpx_fwd, tunnel):
# different --proxy-tls13-ciphers, no reuse of connection for http:
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
@ -339,6 +346,7 @@ class TestProxy:
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_10_13_noreuse_https(self, env: Env, httpd, nghttpx_fwd, tunnel):
# different --tls13-ciphers on https: same proxy config
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):

View File

@ -120,6 +120,7 @@ class TestProxyAuth:
@pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
reason='curl lacks HTTPS-proxy support')
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
def test_13_07_tunnels_no_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd, proto, tunnel):
@ -139,6 +140,7 @@ class TestProxyAuth:
@pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
reason='curl lacks HTTPS-proxy support')
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
def test_13_08_tunnels_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd, proto, tunnel):

View File

@ -77,6 +77,8 @@ class TestTracing:
# trace all
def test_15_04_trace_all(self, env: Env, httpd):
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
curl = CurlClient(env=env)
url = f'http://{env.domain1}:{env.http_port}/data.json'
r = curl.http_get(url=url, def_tracing=False, extra_args=[

View File

@ -367,6 +367,7 @@ class TestSSLUse:
assert r.exit_code != 0, f'should fail, server={server_ver:04x}, curl=[{curl_min_ver:04x}, {curl_max_ver:04x}]\n{r.dump_logs()}'
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_17_10_h3_session_reuse(self, env: Env, httpd, nghttpx):
if not env.have_h3():
pytest.skip("h3 not supported")

View File

@ -90,6 +90,8 @@ class TestShutdown:
def test_19_03_shutdown_by_server(self, env: Env, httpd, proto):
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
count = 10
curl = CurlClient(env=env, run_env={
'CURL_GRACEFUL_SHUTDOWN': '2000',
@ -109,6 +111,8 @@ class TestShutdown:
def test_19_04_shutdown_by_curl(self, env: Env, httpd, proto):
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
count = 10
docname = 'data.json'
url = f'https://localhost:{env.https_port}/{docname}'
@ -132,6 +136,8 @@ class TestShutdown:
def test_19_05_event_shutdown_by_server(self, env: Env, httpd, proto):
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
count = 10
run_env = os.environ.copy()
# forbid connection reuse to trigger shutdowns after transfer
@ -162,6 +168,8 @@ class TestShutdown:
pytest.skip("h3 not supported")
if not env.curl_is_debug():
pytest.skip('only works for curl debug builds')
if not env.curl_is_verbose():
pytest.skip('only works for curl with verbose strings')
curl = CurlClient(env=env, run_env={
'CURL_GRACEFUL_SHUTDOWN': '2000',
'CURL_DEBUG': 'all'

View File

@ -141,6 +141,7 @@ class TestVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_30_06_shutdownh_download(self, env: Env, vsftpd: VsFTPD):
docname = 'data-1k'
curl = CurlClient(env=env)
@ -158,6 +159,7 @@ class TestVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_30_07_shutdownh_upload(self, env: Env, vsftpd: VsFTPD):
docname = 'upload-1k'
curl = CurlClient(env=env)

View File

@ -148,6 +148,7 @@ class TestVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_31_06_shutdownh_download(self, env: Env, vsftpds: VsFTPD):
docname = 'data-1k'
curl = CurlClient(env=env)
@ -164,6 +165,7 @@ class TestVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_31_07_shutdownh_upload(self, env: Env, vsftpds: VsFTPD):
docname = 'upload-1k'
curl = CurlClient(env=env)

View File

@ -160,6 +160,7 @@ class TestFtpsVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_32_06_shutdownh_download(self, env: Env, vsftpds: VsFTPD):
docname = 'data-1k'
curl = CurlClient(env=env)
@ -176,6 +177,7 @@ class TestFtpsVsFTPD:
# check with `tcpdump` if curl causes any TCP RST packets
@pytest.mark.skipif(condition=not Env.tcpdump(), reason="tcpdump not available")
@pytest.mark.skipif(condition=not Env.curl_is_debug(), reason="needs curl debug")
@pytest.mark.skipif(condition=not Env.curl_is_verbose(), reason="needs curl verbose strings")
def test_32_07_shutdownh_upload(self, env: Env, vsftpds: VsFTPD):
docname = 'upload-1k'
curl = CurlClient(env=env)

View File

@ -64,6 +64,7 @@ if not os.path.exists(CONFIG_PATH):
CONFIG_PATH = ALT_CONFIG_PATH
DEF_CONFIG = init_config_from(CONFIG_PATH)
CURL = os.path.join(TOP_PATH, 'src', 'curl')
CURLINFO = os.path.join(TOP_PATH, 'src', 'curlinfo')
class NghttpxUtil:
@ -110,6 +111,7 @@ class EnvConfig:
self.config = DEF_CONFIG
# check cur and its features
self.curl = CURL
self.curlinfo = CURLINFO
if 'CURL' in os.environ:
self.curl = os.environ['CURL']
self.curl_props = {
@ -157,6 +159,12 @@ class EnvConfig:
prot.lower() for prot in line[11:].split(' ')
}
p = subprocess.run(args=[self.curlinfo],
capture_output=True, text=True)
if p.returncode != 0:
raise RuntimeError(f'{self.curlinfo} failed with exit code: {p.returncode}')
self.curl_is_verbose = 'verbose-strings: ON' in p.stdout
self.ports = {}
self.httpd = self.config['httpd']['httpd']
@ -462,6 +470,10 @@ class Env:
def curl_is_debug() -> bool:
return Env.CONFIG.curl_is_debug
@staticmethod
def curl_is_verbose() -> bool:
return Env.CONFIG.curl_is_verbose
@staticmethod
def curl_can_early_data() -> bool:
if Env.curl_uses_lib('gnutls'):