tests: merge clients into libtests, drop duplicate code

libtests and clients were built the same way after recent overhauls.
libtests are used by runtests, clients by pytests.

Merge clients into libtests, aligning their entry function signature,
dropping common utility functions, and simplifying the build.

Note: After this patch `CURLDEBUG` applies to cli tests, when enabled.

Also:
- lib552: drop local copy-paste debug callback in favor of testtrace.
- lib552: drop local copy-paste dump function in favor of testtrace.
- clients: use `long` for HTTP version, drop casts.
- clients: replace local dump function in favor of testrace clone.
- sync cli test entry function prototype with libtests'.
- h2_serverpush: replace local trace callback with testtrace.
- de-duplicate 3 websocket close, ping, ping, functions. Kept the pong
  iteration from `ws_pingpong`. Note: the pong clone in `lib2304` was
  returning an error when `curl_ws_recv()` returned non-zero and
  the payload matched the expected one anyway. After this patch, this
  case returns success, as it does in `ws_pingpong`.
  `lib2304` keeps passing, but I'm not sure if the previous behavior
  was intentional.
- display full value in websocket close, ping, pong, drop casts.

Closes #18079
This commit is contained in:
Viktor Szakats 2025-07-29 09:53:14 +02:00
parent 952c929bdf
commit 00887aee8c
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
48 changed files with 541 additions and 1041 deletions

View file

@ -72,7 +72,7 @@ clean-local:
rm -rf *.pyc __pycache__
rm -rf gen
check: clients
check: libtests
clients:
@(cd ../client; $(MAKE) check)
libtests:
@(cd ../libtests; $(MAKE) check)

View file

@ -312,7 +312,7 @@ class TestDownload:
count = 2
docname = 'data-10m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -335,7 +335,7 @@ class TestDownload:
run_env['CURL_DEBUG'] = 'multi,http/2'
if swin_max > 0:
run_env['CURL_H2_STREAM_WIN_MAX'] = f'{swin_max}'
client = LocalClient(name='hx_download', env=env, run_env=run_env)
client = LocalClient(name='cli_hx_download', env=env, run_env=run_env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -355,7 +355,7 @@ class TestDownload:
max_parallel = 5
docname = 'data-10m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -383,7 +383,7 @@ class TestDownload:
pause_offset = 12 * 1024
docname = 'data-1m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -412,7 +412,7 @@ class TestDownload:
abort_offset = 12 * 1024
docname = 'data-1m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -441,7 +441,7 @@ class TestDownload:
fail_offset = 12 * 1024
docname = 'data-1m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -475,7 +475,7 @@ class TestDownload:
# before protocol switch has happened
def test_02_25_h2_upgrade_x(self, env: Env, httpd):
url = f'http://localhost:{env.http_port}/data-100k'
client = LocalClient(name='h2_upgrade_extreme', env=env, timeout=15)
client = LocalClient(name='cli_h2_upgrade_extreme', env=env, timeout=15)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[url])
@ -488,10 +488,10 @@ class TestDownload:
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
url = f'https://{env.authority_for(env.domain1, proto)}/data-100k'
client = LocalClient(name='tls_session_reuse', env=env)
client = LocalClient(name='cli_tls_session_reuse', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[proto, url])
r = client.run(args=[url, proto])
r.check_exit_code(0)
# test on paused transfers, based on issue #11982
@ -501,7 +501,7 @@ class TestDownload:
pytest.skip("h3 not supported")
url = f'https://{env.authority_for(env.domain1, proto)}' \
'/curltest/tweak/?&chunks=6&chunk_size=8000'
client = LocalClient(env=env, name='h2_pausing')
client = LocalClient(env=env, name='cli_h2_pausing')
r = client.run(args=['-V', proto, url])
r.check_exit_code(0)
@ -512,7 +512,7 @@ class TestDownload:
pytest.skip("h3 not supported")
url = f'https://{env.authority_for(env.domain1, proto)}' \
'/curltest/tweak/?error=502'
client = LocalClient(env=env, name='h2_pausing')
client = LocalClient(env=env, name='cli_h2_pausing')
r = client.run(args=['-V', proto, url])
r.check_exit_code(0)
@ -523,7 +523,7 @@ class TestDownload:
pytest.skip("h3 not supported")
url = f'https://{env.authority_for(env.domain1, proto)}' \
'/curltest/tweak/?status=200&chunks=1&chunk_size=100'
client = LocalClient(env=env, name='h2_pausing')
client = LocalClient(env=env, name='cli_h2_pausing')
r = client.run(args=['-V', proto, url])
r.check_exit_code(0)
@ -562,7 +562,7 @@ class TestDownload:
count = 2
docname = 'data-10m'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -617,7 +617,7 @@ class TestDownload:
if proto != 'h3':
port = env.nghttpx_https_port
url = f'https://{env.domain1}:{port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -663,7 +663,7 @@ class TestDownload:
url = f'https://{env.domain1}:{port}/{docname}'
run_env = os.environ.copy()
run_env['CURL_DEBUG'] = 'multi'
client = LocalClient(name='hx_download', env=env, run_env=run_env)
client = LocalClient(name='cli_hx_download', env=env, run_env=run_env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -701,7 +701,7 @@ class TestDownload:
url = f'https://{env.domain1}:{port}/{docname}'
run_env = os.environ.copy()
run_env['CURL_DEBUG'] = 'multi'
client = LocalClient(name='hx_download', env=env, run_env=run_env)
client = LocalClient(name='cli_hx_download', env=env, run_env=run_env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -743,7 +743,7 @@ class TestDownload:
pause_offset = 1024 * 1024
docname = 'bomb-100m.txt.var'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[

View file

@ -166,7 +166,7 @@ class TestUpload:
count = 2
upload_size = 128*1024
url = f'https://localhost:{env.https_port}/curltest/put'
client = LocalClient(name='hx_upload', env=env)
client = LocalClient(name='cli_hx_upload', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -182,7 +182,7 @@ class TestUpload:
count = 2
upload_size = 128*1024
url = f'https://localhost:{env.https_port}/curltest/put'
client = LocalClient(name='hx_upload', env=env)
client = LocalClient(name='cli_hx_upload', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -198,7 +198,7 @@ class TestUpload:
count = 2
upload_size = 128*1024
url = f'https://localhost:{env.https_port}/curltest/echo'
client = LocalClient(name='hx_upload', env=env)
client = LocalClient(name='cli_hx_upload', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -503,7 +503,7 @@ class TestUpload:
def test_07_42a_upload_disconnect(self, env: Env, httpd, nghttpx, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
client = LocalClient(name='upload_pausing', env=env, timeout=60)
client = LocalClient(name='cli_upload_pausing', env=env, timeout=60)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]&die_after=0'
@ -523,7 +523,7 @@ class TestUpload:
def test_07_42b_upload_disconnect(self, env: Env, httpd, nghttpx, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
client = LocalClient(name='upload_pausing', env=env, timeout=60)
client = LocalClient(name='cli_upload_pausing', env=env, timeout=60)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=0&just_die=1'
@ -538,7 +538,7 @@ class TestUpload:
def test_07_42c_upload_disconnect(self, env: Env, httpd, nghttpx, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
client = LocalClient(name='upload_pausing', env=env, timeout=60)
client = LocalClient(name='cli_upload_pausing', env=env, timeout=60)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=0&die_after_100=1'
@ -572,7 +572,7 @@ class TestUpload:
count = 1
upload_size = 128*1024
url = f'https://localhost:{env.https_port}/curltest/put-redir-{httpcode}'
client = LocalClient(name='hx_upload', env=env)
client = LocalClient(name='cli_hx_upload', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[
@ -700,7 +700,7 @@ class TestUpload:
if proto != 'h3':
port = env.nghttpx_https_port
url = f'https://{env.domain1}:{port}/curltest/put'
client = LocalClient(name='hx_upload', env=env)
client = LocalClient(name='cli_hx_upload', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[

View file

@ -199,7 +199,7 @@ class TestCaddy:
count = 2
docname = 'data10k.data'
url = f'https://{env.domain1}:{caddy.port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[

View file

@ -76,7 +76,7 @@ class TestPush:
self.httpd_configure(env, httpd)
# use localhost as we do not have resolve support in local client
url = f'https://localhost:{env.https_port}/push/data1'
client = LocalClient(name='h2_serverpush', env=env)
client = LocalClient(name='cli_h2_serverpush', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[url])

View file

@ -377,7 +377,7 @@ class TestSSLUse:
count = 2
docname = 'data-10k'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env)
client = LocalClient(name='cli_hx_download', env=env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
r = client.run(args=[

View file

@ -112,7 +112,7 @@ class TestShutdown:
count = 10
docname = 'data.json'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env, run_env={
client = LocalClient(name='cli_hx_download', env=env, run_env={
'CURL_GRACEFUL_SHUTDOWN': '2000',
'CURL_DEBUG': 'ssl,multi'
})
@ -185,7 +185,7 @@ class TestShutdown:
count = 500
docname = 'data.json'
url = f'https://localhost:{env.https_port}/{docname}'
client = LocalClient(name='hx_download', env=env, run_env={
client = LocalClient(name='cli_hx_download', env=env, run_env={
'CURL_GRACEFUL_SHUTDOWN': '2000',
'CURL_DEBUG': 'ssl,multi'
})

View file

@ -109,7 +109,7 @@ class TestWebsockets:
def test_20_02_pingpong_small(self, env: Env, ws_echo):
payload = 125 * "x"
client = LocalClient(env=env, name='ws_pingpong')
client = LocalClient(env=env, name='cli_ws_pingpong')
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -119,7 +119,7 @@ class TestWebsockets:
# the python websocket server does not like 'large' control frames
def test_20_03_pingpong_too_large(self, env: Env, ws_echo):
payload = 127 * "x"
client = LocalClient(env=env, name='ws_pingpong')
client = LocalClient(env=env, name='cli_ws_pingpong')
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -127,7 +127,7 @@ class TestWebsockets:
r.check_exit_code(100) # CURLE_TOO_LARGE
def test_20_04_data_small(self, env: Env, ws_echo):
client = LocalClient(env=env, name='ws_data')
client = LocalClient(env=env, name='cli_ws_data')
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -135,7 +135,7 @@ class TestWebsockets:
r.check_exit_code(0)
def test_20_05_data_med(self, env: Env, ws_echo):
client = LocalClient(env=env, name='ws_data')
client = LocalClient(env=env, name='cli_ws_data')
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -143,7 +143,7 @@ class TestWebsockets:
r.check_exit_code(0)
def test_20_06_data_large(self, env: Env, ws_echo):
client = LocalClient(env=env, name='ws_data')
client = LocalClient(env=env, name='cli_ws_data')
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -153,7 +153,7 @@ class TestWebsockets:
def test_20_07_data_large_small_recv(self, env: Env, ws_echo):
run_env = os.environ.copy()
run_env['CURL_WS_CHUNK_SIZE'] = '1024'
client = LocalClient(env=env, name='ws_data', run_env=run_env)
client = LocalClient(env=env, name='cli_ws_data', run_env=run_env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'
@ -165,7 +165,7 @@ class TestWebsockets:
def test_20_08_data_very_large(self, env: Env, ws_echo):
run_env = os.environ.copy()
run_env['CURL_WS_CHUNK_EAGAIN'] = '8192'
client = LocalClient(env=env, name='ws_data', run_env=run_env)
client = LocalClient(env=env, name='cli_ws_data', run_env=run_env)
if not client.exists():
pytest.skip(f'example client not built: {client.name}')
url = f'ws://localhost:{env.ws_port}/'

View file

@ -44,7 +44,7 @@ class LocalClient:
timeout: Optional[float] = None,
run_env: Optional[Dict[str,str]] = None):
self.name = name
self.path = os.path.join(env.build_dir, 'tests/client/clients')
self.path = os.path.join(env.build_dir, 'tests/libtest/libtests')
self.env = env
self._run_env = run_env
self._timeout = timeout if timeout else env.test_timeout