From: Daniel Stenberg Date: Thu, 7 Nov 2024 09:22:32 +0000 (+0100) Subject: curl: --test-duphandle in debug builds runs "duphandled" X-Git-Tag: curl-8_11_1~102 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cbafcec50bc99ba0dd0490e6725351791255abc1;p=thirdparty%2Fcurl.git curl: --test-duphandle in debug builds runs "duphandled" Using this option (only available in debug builds) makes curl always call curl_easy_duphandle() on the handle before using it. To help us catch curl_easy_duphandle() mistakes better. Add a CI job using this. Bonus: the previous runtests option -e is now also supported as --test-event Closes #15504 --- diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 24257b8ef0..d00b731ebe 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -248,7 +248,12 @@ jobs: - name: event-based install_packages: libssh-dev configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl - tflags: -n -e '!TLS-SRP' + tflags: -n --test-event '!TLS-SRP' + + - name: duphandle + install_packages: libssh-dev + configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl + tflags: -n --test-duphandle '!TLS-SRP' - name: rustls valgrind install_packages: valgrind diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 40f6602941..816c801be8 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -136,7 +136,7 @@ jobs: compiler: clang configure: --enable-debug --with-openssl=$(brew --prefix openssl) macos-version-min: '10.9' - tflags: -e + tflags: --test-event - name: 'OpenSSL libssh2 !ldap 10.15' compiler: clang configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix openssl) diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 46f47670d6..09ea9edd19 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -330,6 +330,7 @@ struct GlobalConfig { long ms_per_transfer; /* start next transfer after (at least) this many milliseconds */ #ifdef DEBUGBUILD + bool test_duphandle; bool test_event_based; #endif bool parallel; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 1231b3bd60..447046f72f 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -312,7 +312,10 @@ static const struct LongShort aliases[]= { {"tcp-fastopen", ARG_BOOL, ' ', C_TCP_FASTOPEN}, {"tcp-nodelay", ARG_BOOL, ' ', C_TCP_NODELAY}, {"telnet-option", ARG_STRG, 't', C_TELNET_OPTION}, +#ifdef DEBUGBUILD + {"test-duphandle", ARG_BOOL, ' ', C_TEST_DUPHANDLE}, {"test-event", ARG_BOOL, ' ', C_TEST_EVENT}, +#endif {"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE}, {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS}, {"time-cond", ARG_STRG, 'z', C_TIME_COND}, @@ -1653,13 +1656,14 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_SASL_IR: /* --sasl-ir */ config->sasl_ir = toggle; break; - case C_TEST_EVENT: /* --test-event */ #ifdef DEBUGBUILD + case C_TEST_DUPHANDLE: /* --test-duphandle */ + global->test_duphandle = toggle; + break; + case C_TEST_EVENT: /* --test-event */ global->test_event_based = toggle; -#else - warnf(global, "--test-event is ignored unless a debug build"); -#endif break; +#endif case C_UNIX_SOCKET: /* --unix-socket */ config->abstract_unix_socket = FALSE; err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK); diff --git a/src/tool_getparam.h b/src/tool_getparam.h index c42f686a48..7d9abbd141 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -267,6 +267,7 @@ typedef enum { C_TCP_FASTOPEN, C_TCP_NODELAY, C_TELNET_OPTION, + C_TEST_DUPHANDLE, C_TEST_EVENT, C_TFTP_BLKSIZE, C_TFTP_NO_OPTIONS, diff --git a/src/tool_operate.c b/src/tool_operate.c index a1212c9dde..354ecdedd7 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -2885,6 +2885,17 @@ static CURLcode serial_transfers(struct GlobalConfig *global, if(getenv("CURL_FORBID_REUSE")) (void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L); + if(global->test_duphandle) { + CURL *dup = curl_easy_duphandle(per->curl); + curl_easy_cleanup(per->curl); + per->curl = dup; + if(!dup) { + result = CURLE_OUT_OF_MEMORY; + break; + } + /* a duplicate needs the share re-added */ + (void)curl_easy_setopt(per->curl, CURLOPT_SHARE, share); + } if(global->test_event_based) result = curl_easy_perform_ev(per->curl); else diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md index aa80b81687..b15274e17a 100644 --- a/tests/FILEFORMAT.md +++ b/tests/FILEFORMAT.md @@ -522,6 +522,7 @@ the `unit/` directory (if the tool name starts with `unit`). Brief test case description, shown when the test runs. ### `` + variable1=contents1 variable2=contents2 variable3 @@ -606,6 +607,11 @@ Pass this given data on stdin to the tool. If `nonewline` is set, we cut off the trailing newline of this given data before comparing with the one actually received by the client +## `` + +If `test-duphandle` is a listed item here, this is not run when +`--test-duphandle` is used. + ## `` ### `` numerical error code curl is supposed to return. Specify a list of accepted diff --git a/tests/data/test440 b/tests/data/test440 index a77ef606d9..ce9892967c 100644 --- a/tests/data/test440 +++ b/tests/data/test440 @@ -44,6 +44,10 @@ HSTS with trailing-dot host name in URL but none in hsts file -x http://%HOSTIP:%HTTPPORT http://this.hsts.example./%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n' + + +test-duphandle + diff --git a/tests/data/test441 b/tests/data/test441 index 29b990b891..02aca4d0e0 100644 --- a/tests/data/test441 +++ b/tests/data/test441 @@ -44,6 +44,9 @@ HSTS with no t-dot host name in URL but t-dot in file -x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n' + +test-duphandle + diff --git a/tests/data/test493 b/tests/data/test493 index 1a677d3295..d157f0355f 100644 --- a/tests/data/test493 +++ b/tests/data/test493 @@ -43,6 +43,9 @@ HSTS and %{url_effective} after upgrade -x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n' + +test-duphandle + diff --git a/tests/data/test780 b/tests/data/test780 index cdb8b711f7..567b6684d0 100644 --- a/tests/data/test780 +++ b/tests/data/test780 @@ -55,6 +55,9 @@ HSTS with updated expiry in response -x http://%HOSTIP:%PROXYPORT http://this.hsts.example:%HTTPSPORT/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -k + +test-duphandle + diff --git a/tests/data/test781 b/tests/data/test781 index e931da4f5e..4892415bf4 100644 --- a/tests/data/test781 +++ b/tests/data/test781 @@ -57,6 +57,9 @@ HSTS update expiry, with parent includeSubDomains domain present -x http://%HOSTIP:%PROXYPORT http://this.hsts.example:%HTTPSPORT/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -k + +test-duphandle + diff --git a/tests/data/test782 b/tests/data/test782 index ae0d747470..6a53081ab6 100644 --- a/tests/data/test782 +++ b/tests/data/test782 @@ -57,6 +57,9 @@ HSTS update expiry, with two includeSubDomains domains present -x http://%HOSTIP:%PROXYPORT http://this.hsts.example:%HTTPSPORT/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -k + +test-duphandle + diff --git a/tests/data/test783 b/tests/data/test783 index dc58fa4fb3..f12cc4507d 100644 --- a/tests/data/test783 +++ b/tests/data/test783 @@ -57,6 +57,9 @@ HSTS update expiry, removing includesubdomains in update -x http://%HOSTIP:%PROXYPORT http://this.hsts.example:%HTTPSPORT/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -k + +test-duphandle + diff --git a/tests/globalconfig.pm b/tests/globalconfig.pm index dec828e018..08aff0ff3e 100644 --- a/tests/globalconfig.pm +++ b/tests/globalconfig.pm @@ -54,6 +54,7 @@ BEGIN { $PROXYIN $pwd $randseed + $run_duphandle $run_event_based $SERVERCMD $SERVERIN @@ -83,6 +84,7 @@ our $verbose; # 1 to show verbose test output our $torture; # 1 to enable torture testing our $proxy_address; # external HTTP proxy address our $listonly; # only list the tests +our $run_duphandle; # run curl with --test-duphandle to verify handle duplication our $run_event_based; # run curl with --test-event to test the event API our $automakestyle; # use automake-like test status output format our $anyway; # continue anyway, even if a test fail diff --git a/tests/runner.pm b/tests/runner.pm index deb7920e79..3372eda8b7 100644 --- a/tests/runner.pm +++ b/tests/runner.pm @@ -894,6 +894,18 @@ sub singletest_run { $cmdargs .= "--test-event "; $fail_due_event_based--; } + if($run_duphandle) { + $cmdargs .= "--test-duphandle "; + my @dis = getpart("client", "disable"); + if(@dis) { + chomp $dis[0] if($dis[0]); + if($dis[0] eq "test-duphandle") { + # marked to not run with duphandle + logmsg "test $testnum: IGNORED: can't run test-duphandle\n"; + return (-1, 0, 0, "", "", 0); + } + } + } $cmdargs .= $cmd; if ($proxy_address) { $cmdargs .= " --proxy $proxy_address "; diff --git a/tests/runtests.md b/tests/runtests.md index e836911b91..4ac52a4460 100644 --- a/tests/runtests.md +++ b/tests/runtests.md @@ -118,7 +118,7 @@ exclusion, the second field contains a pattern and the final field contains the reason why matching tests should be skipped. The exclusion types are *keyword*, *test*, and *tool*. -## `-e` +## `-e` or `--test-event` Run the test event-based (if possible). This makes runtests invoke curl with --test-event option. This option only works if both curl and libcurl were @@ -263,6 +263,19 @@ the allocation with that number to be set to fail at once instead of looping through everyone, which is handy when debugging and then often in combination with *-g*. +## `--test-duphandle` + +Passes the `--test-duphandle` option to curl when invoked. This command line +option only exists in debug builds and runs curl normally, but duplicates the +easy handle before the transfer and use the duplicate instead of the original +handle. This verifies that the duplicate works exactly as good as the original +handle. + +Because of how the curl tool uses a share object to store and keep some data, +not everything is however perfectly copied in the duplicate. In particular +HSTS data is not. A specific test case can be set to avoid using +`--test-duphandle` by disabling it on a per test basis. + ## `-u` Error instead of warning on server unexpectedly alive. diff --git a/tests/runtests.pl b/tests/runtests.pl index c02655b07e..4d4785b50b 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -871,7 +871,8 @@ sub checksystemfeatures { "*\n"); } - logmsg sprintf("* Env: %s%s%s%s", $valgrind?"Valgrind ":"", + logmsg sprintf("* Env: %s%s%s%s%s", $valgrind?"Valgrind ":"", + $run_duphandle?"test-duphandle ":"", $run_event_based?"event-based ":"", $bundle?"bundle ":"", $nghttpx_h3); @@ -2270,10 +2271,14 @@ while(@ARGV) { # have the servers display protocol output $debugprotocol=1; } - elsif($ARGV[0] eq "-e") { + elsif(($ARGV[0] eq "-e") || ($ARGV[0] eq "--test-event")) { # run the tests cases event based if possible $run_event_based=1; } + elsif($ARGV[0] eq "--test-duphandle") { + # run the tests with --test-duphandle + $run_duphandle=1; + } elsif($ARGV[0] eq "-f") { # force - run the test case even if listed in DISABLED $run_disabled=1; diff --git a/tests/test1139.pl b/tests/test1139.pl index 6ecab78ece..0c99ab6f3a 100755 --- a/tests/test1139.pl +++ b/tests/test1139.pl @@ -180,6 +180,7 @@ my %opts = ( '--include' => 6, # for tests and debug only, can remain hidden + '--test-duphandle' => 6, '--test-event' => 6, '--wdebug' => 6, );