diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/data/Makefile.am | 16 | ||||
-rw-r--r-- | tests/data/test1549 | 59 | ||||
-rw-r--r-- | tests/data/test2307 | 60 | ||||
-rw-r--r-- | tests/data/test758 | 53 | ||||
-rwxr-xr-x | tests/ftpserver.pl | 7 | ||||
-rw-r--r-- | tests/libtest/Makefile.inc | 4 | ||||
-rw-r--r-- | tests/libtest/lib1549.c | 76 | ||||
-rw-r--r-- | tests/libtest/lib758.c | 515 | ||||
-rw-r--r-- | tests/processhelp.pm | 47 | ||||
-rw-r--r-- | tests/runner.pm | 8 | ||||
-rwxr-xr-x | tests/runtests.pl | 3 | ||||
-rw-r--r-- | tests/serverhelp.pm | 27 | ||||
-rw-r--r-- | tests/servers.pm | 2 |
13 files changed, 797 insertions, 80 deletions
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 1c0258e17..71fc94860 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -108,7 +108,7 @@ test718 test719 test720 test721 test722 test723 test724 test725 test726 \ test727 test728 test729 test730 test731 test732 test733 test734 test735 \ test736 test737 test738 test739 test740 test741 test742 test743 test744 \ test745 test746 test747 test748 test749 test750 test751 test752 test753 \ -test754 test755 test756 test757 \ +test754 test755 test756 test757 test758 \ test780 test781 test782 test783 test784 test785 test786 test787 test788 \ test789 test790 test791 test792 test793 test794 test796 test797 \ \ @@ -203,11 +203,11 @@ test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \ test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \ test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \ test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 \ -test1548 \ -test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \ -test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \ -test1566 test1567 test1568 test1569 test1570 test1571 test1572 test1573 \ -test1574 test1575 test1576 test1577 test1578 test1579 test1580 test1581 \ +test1548 test1549 test1550 test1551 test1552 test1553 test1554 test1555 \ +test1556 test1557 test1558 test1559 test1560 test1561 test1562 test1563 \ +test1564 test1565 test1566 test1567 test1568 test1569 test1570 test1571 \ +test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 \ +test1580 test1581 \ \ test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \ test1598 test1599 test1600 test1601 test1602 test1603 test1604 test1605 \ @@ -256,8 +256,8 @@ test2100 test2101 test2102 test2103 test2104 \ \ test2200 test2201 test2202 test2203 test2204 test2205 \ \ -test2300 test2301 test2302 test2303 test2304 test2306 \ -test2308 test2309 \ +test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 \ +test2309 \ \ test2400 test2401 test2402 test2403 test2404 test2405 test2406 \ \ diff --git a/tests/data/test1549 b/tests/data/test1549 new file mode 100644 index 000000000..bc821e5eb --- /dev/null +++ b/tests/data/test1549 @@ -0,0 +1,59 @@ +<testcase> +<info> +<keywords> +HTTP +cookies +</keywords> +</info> + +# +# Server-side +<reply> +<data crlf="yes"> +HTTP/1.1 200 OK +Content-Length: 6 +Content-Type: text/plain +Set-Cookie: c1=123; Path=/; Expires=Thu, 12 Feb 2000 00:00:00 GMT +Set-Cookie: c2=456; Path=/; Expires=Thu, 12 Feb 2000 00:00:00 GMT; + +hello +</data> +</reply> + +# +# Client-side +<client> +<server> +http +</server> +<features> +http +cookies +</features> +<name> +Receive expired cookies and CURLINFO_COOKIELIST +</name> +<tool> +lib%TESTNUMBER +</tool> +<command> +http://%HOSTIP:%HTTPPORT/%TESTNUMBER +</command> +</client> + +# +# Verify data after the test has been "shot" +<verify> +<protocol crlf="yes"> +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* + +</protocol> +<stderr mode="text"> +URL: http://%HOSTIP:%HTTPPORT/%TESTNUMBER +0 cookies +Test ended with result 0 +</stderr> +</verify> +</testcase> diff --git a/tests/data/test2307 b/tests/data/test2307 new file mode 100644 index 000000000..cbb581a4a --- /dev/null +++ b/tests/data/test2307 @@ -0,0 +1,60 @@ +<testcase> +<info> +<keywords> +FTP +EPSV +RETR +Range +</keywords> +</info> +# Server-side +<reply> +<data> +0123456789abcdef +0123456789abcdef +0123456789abcdef +0123456789abcdef +</data> +<datacheck nonewline="yes"> +0123456789abcdef +0123456789abcdef +0123456789abcdef +012345678 +</datacheck> +<size> +64 +</size> +</reply> + +# Client-side +<client> +<server> +ftp +</server> +<name> +FTP retrieve a byte-range with end larger than file +</name> +<command> +-r 4-1000 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<strip> +QUIT +</strip> +<protocol crlf="yes"> +USER anonymous +PASS ftp@example.com +PWD +EPSV +TYPE I +SIZE %TESTNUMBER +REST 4 +RETR %TESTNUMBER +ABOR +QUIT +</protocol> +</verify> +</testcase> diff --git a/tests/data/test758 b/tests/data/test758 new file mode 100644 index 000000000..a807ae9c8 --- /dev/null +++ b/tests/data/test758 @@ -0,0 +1,53 @@ +<testcase> +<info> +<keywords> +multi +HTTPS +</keywords> +</info> + +# Server-side +<reply> +<data nocheck="yes"> +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6007 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- +%repeat[1000 x foobar]% +</data> +</reply> + +<features> +OpenSSL +</features> + +# Client-side +<client> +<server> +https +</server> +<tool> +lib%TESTNUMBER +</tool> +<name> +multi_socket interface transfer with callbacks returning error +</name> +<command> +https://localhost:%HTTPSPORT/file%TESTNUMBER +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<protocol> +</protocol> +</verify> +</testcase> diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl index 927d4c66a..71d6774fd 100755 --- a/tests/ftpserver.pl +++ b/tests/ftpserver.pl @@ -51,6 +51,7 @@ BEGIN { use IPC::Open2; use Digest::MD5; use File::Basename; +use Time::HiRes; use directories; @@ -484,7 +485,7 @@ sub sendcontrol { for(@a) { sockfilt $_; - portable_sleep($ctrldelay); + Time::HiRes::sleep($ctrldelay); } } my $log; @@ -521,7 +522,7 @@ sub senddata { # pause between each byte for (split(//,$l)) { sockfiltsecondary $_; - portable_sleep($datadelay); + Time::HiRes::sleep($datadelay); } } } @@ -3292,7 +3293,7 @@ while(1) { logmsg("Sleep for $delay seconds\n"); my $twentieths = $delay * 20; while($twentieths--) { - portable_sleep(0.05) unless($got_exit_signal); + Time::HiRes::sleep(0.05) unless($got_exit_signal); } } diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index 5e1462108..40ec0d155 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -71,7 +71,7 @@ TESTS_C = \ lib661.c lib666.c lib667.c lib668.c \ lib670.c lib674.c lib676.c lib677.c lib678.c \ lib694.c lib695.c \ - lib751.c lib753.c \ + lib751.c lib753.c lib758.c \ lib757.c \ lib1156.c \ lib1301.c lib1308.c \ @@ -82,7 +82,7 @@ TESTS_C = \ lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c \ lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c \ lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c \ - lib1545.c lib1550.c lib1551.c \ + lib1545.c lib1549.c lib1550.c lib1551.c \ lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c \ lib1559.c lib1560.c lib1564.c lib1565.c \ lib1567.c lib1568.c lib1569.c lib1571.c \ diff --git a/tests/libtest/lib1549.c b/tests/libtest/lib1549.c new file mode 100644 index 000000000..b7bf01061 --- /dev/null +++ b/tests/libtest/lib1549.c @@ -0,0 +1,76 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "first.h" + +#include "testtrace.h" +#include "memdebug.h" + +static CURLcode test_lib1549(const char *URL) +{ + CURLcode res; + CURL *curl; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + curl_mfprintf(stderr, "curl_global_init() failed\n"); + return TEST_ERR_MAJOR_BAD; + } + + curl = curl_easy_init(); + if(!curl) { + curl_mfprintf(stderr, "curl_easy_init() failed\n"); + curl_global_cleanup(); + return TEST_ERR_MAJOR_BAD; + } + + test_setopt(curl, CURLOPT_URL, URL); + test_setopt(curl, CURLOPT_HEADER, 1L); + test_setopt(curl, CURLOPT_COOKIEFILE, ""); + + res = curl_easy_perform(curl); + + if(!res) { + /* extract all known cookies */ + struct curl_slist *cookies = NULL; + int num = 0; + res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); + if(!res && cookies) { + /* a linked list of cookies in cookie file format */ + struct curl_slist *each = cookies; + while(each) { + printf("%s\n", each->data); + each = each->next; + num++; + } + /* we must free these cookies when we are done */ + curl_slist_free_all(cookies); + } + fprintf(stderr, "%d cookies\n", num); + } +test_cleanup: + + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return res; +} diff --git a/tests/libtest/lib758.c b/tests/libtest/lib758.c new file mode 100644 index 000000000..dfcbaebb3 --- /dev/null +++ b/tests/libtest/lib758.c @@ -0,0 +1,515 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * The purpose of this test is to make sure that if CURLMOPT_SOCKETFUNCTION or + * CURLMOPT_TIMERFUNCTION returns error, the associated transfer should be + * aborted correctly. + */ + +#include "first.h" + +#include "testtrace.h" +#include "memdebug.h" + +#ifdef USE_OPENSSL + +#include <openssl/x509.h> +#include <openssl/ssl.h> + +#if ((OPENSSL_VERSION_NUMBER >= 0x30000000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL)) +#define T578_ENABLED +#endif +#endif + +#ifdef T578_ENABLED + +static struct t758_ctx { + int socket_calls; + int max_socket_calls; + int timer_calls; + int max_timer_calls; + int fake_async_cert_verification_pending; + int fake_async_cert_verification_finished; + int number_of_cert_verify_callbacks; + char buf[1024]; +} t758_ctx; + +static const char *t758_tag(void) +{ + curl_msnprintf(t758_ctx.buf, sizeof(t758_ctx.buf), + "[T758-%d-%d] [%d/%d]", + t758_ctx.max_socket_calls, t758_ctx.max_timer_calls, + t758_ctx.socket_calls, t758_ctx.timer_calls); + return t758_ctx.buf; +} + +static void t758_msg(const char *msg) +{ + curl_mfprintf(stderr, "%s %s\n", t758_tag(), msg); +} + + +struct t758_Sockets { + curl_socket_t *sockets; + int count; /* number of sockets actually stored in array */ + int max_count; /* max number of sockets that fit in allocated array */ +}; + +struct t758_ReadWriteSockets { + struct t758_Sockets read, write; +}; + +/** + * Remove a file descriptor from a sockets array. + */ +static void t758_removeFd(struct t758_Sockets *sockets, curl_socket_t fd, + int mention) +{ + int i; + + if(mention) + curl_mfprintf(stderr, "%s remove socket fd %" FMT_SOCKET_T "\n", + t758_tag(), fd); + + for(i = 0; i < sockets->count; ++i) { + if(sockets->sockets[i] == fd) { + if(i < sockets->count - 1) + memmove(&sockets->sockets[i], &sockets->sockets[i + 1], + sizeof(curl_socket_t) * (sockets->count - (i + 1))); + --sockets->count; + } + } +} + +/** + * Add a file descriptor to a sockets array. + * Return 0 on success, 1 on error. + */ +static int t758_addFd(struct t758_Sockets *sockets, curl_socket_t fd, + const char *what) +{ + /** + * To ensure we only have each file descriptor once, we remove it then add + * it again. + */ + curl_mfprintf(stderr, "%s add socket fd %" FMT_SOCKET_T " for %s\n", + t758_tag(), fd, what); + t758_removeFd(sockets, fd, 0); + /* + * Allocate array storage when required. + */ + if(!sockets->sockets) { + sockets->sockets = malloc(sizeof(curl_socket_t) * 20U); + if(!sockets->sockets) + return 1; + sockets->max_count = 20; + } + else if(sockets->count + 1 > sockets->max_count) { + curl_socket_t *ptr = realloc(sockets->sockets, sizeof(curl_socket_t) * + (sockets->max_count + 20)); + if(!ptr) + /* cleanup in test_cleanup */ + return 1; + sockets->sockets = ptr; + sockets->max_count += 20; + } + /* + * Add file descriptor to array. + */ + sockets->sockets[sockets->count] = fd; + ++sockets->count; + return 0; +} + +/** + * Callback invoked by curl to poll reading / writing of a socket. + */ +static int t758_curlSocketCallback(CURL *easy, curl_socket_t s, int action, + void *userp, void *socketp) +{ + struct t758_ReadWriteSockets *sockets = userp; + + (void)easy; + (void)socketp; + + t758_ctx.socket_calls++; + t758_msg("-> CURLMOPT_SOCKETFUNCTION"); + if(t758_ctx.socket_calls == t758_ctx.max_socket_calls) { + t758_msg("<- CURLMOPT_SOCKETFUNCTION returns error"); + return -1; + } + + if(action == CURL_POLL_IN || action == CURL_POLL_INOUT) + if(t758_addFd(&sockets->read, s, "read")) + return -1; /* bail out */ + + if(action == CURL_POLL_OUT || action == CURL_POLL_INOUT) + if(t758_addFd(&sockets->write, s, "write")) + return -1; + + if(action == CURL_POLL_REMOVE) { + t758_removeFd(&sockets->read, s, 1); + t758_removeFd(&sockets->write, s, 0); + } + + return 0; +} + +/** + * Callback invoked by curl to set a timeout. + */ +static int t758_curlTimerCallback(CURLM *multi, long timeout_ms, void *userp) +{ + struct curltime *timeout = userp; + + (void)multi; /* unused */ + t758_ctx.timer_calls++; + t758_msg("-> CURLMOPT_TIMERFUNCTION"); + if(t758_ctx.timer_calls == t758_ctx.max_timer_calls) { + t758_msg("<- CURLMOPT_TIMERFUNCTION returns error"); + return -1; + } + if(timeout_ms != -1) { + *timeout = curlx_now(); + timeout->tv_usec += (int)timeout_ms * 1000; + } + else { + timeout->tv_sec = -1; + } + return 0; +} + +static int t758_cert_verify_callback(X509_STORE_CTX *ctx, void *arg) +{ + SSL * ssl; + (void)arg; /* unused */ + ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + t758_ctx.number_of_cert_verify_callbacks++; + if(!t758_ctx.fake_async_cert_verification_pending) { + t758_ctx.fake_async_cert_verification_pending = 1; + t758_msg(" initial t758_cert_verify_callback"); + return SSL_set_retry_verify(ssl); + } + else if(t758_ctx.fake_async_cert_verification_finished) { + t758_msg(" final t758_cert_verify_callback"); + return 1; /* success */ + } + else { + t758_msg(" pending t758_cert_verify_callback"); + return SSL_set_retry_verify(ssl); + } +} + +static CURLcode +t758_set_ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp) +{ + SSL_CTX *ctx = (SSL_CTX *) ssl_ctx; + (void)curl; /* unused */ + SSL_CTX_set_cert_verify_callback(ctx, t758_cert_verify_callback, clientp); + return CURLE_OK; +} + +/** + * Check for curl completion. + */ +static int t758_checkForCompletion(CURLM *curl, int *success) +{ + int result = 0; + *success = 0; + while(1) { + int numMessages; + CURLMsg *message = curl_multi_info_read(curl, &numMessages); + if(!message) + break; + if(message->msg == CURLMSG_DONE) { + result = 1; + if(message->data.result == CURLE_OK) + *success = 1; + else + *success = 0; + } + else { + curl_mfprintf(stderr, "%s got an unexpected message from curl: %i\n", + t758_tag(), message->msg); + result = 1; + *success = 0; + } + } + return result; +} + +static ssize_t t758_getMicroSecondTimeout(struct curltime *timeout) +{ + struct curltime now; + ssize_t result; + now = curlx_now(); + result = (ssize_t)((timeout->tv_sec - now.tv_sec) * 1000000 + + timeout->tv_usec - now.tv_usec); + if(result < 0) + result = 0; + + return result; +} + +/** + * Update a fd_set with all of the sockets in use. + */ +static void t758_updateFdSet(struct t758_Sockets *sockets, fd_set* fdset, + curl_socket_t *maxFd) +{ + int i; + for(i = 0; i < sockets->count; ++i) { +#ifdef __DJGPP__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warith-conversion" +#endif + FD_SET(sockets->sockets[i], fdset); +#ifdef __DJGPP__ +#pragma GCC diagnostic pop +#endif + if(*maxFd < sockets->sockets[i] + 1) { + *maxFd = sockets->sockets[i] + 1; + } + } +} + +static CURLMcode t758_saction(CURLM *curl, curl_socket_t s, + int evBitmask, const char *info) +{ + int numhandles = 0; + CURLMcode result = curl_multi_socket_action(curl, s, evBitmask, &numhandles); + if(result != CURLM_OK) { + curl_mfprintf(stderr, "%s Curl error on %s (%i) %s\n", + t758_tag(), info, result, curl_multi_strerror(result)); + } + return result; +} + +/** + * Invoke curl when a file descriptor is set. + */ +static CURLMcode t758_checkFdSet(CURLM *curl, struct t758_Sockets *sockets, + fd_set *fdset, int evBitmask, + const char *name) +{ + int i; + CURLMcode result = CURLM_OK; + for(i = 0; i < sockets->count; ++i) { + if(FD_ISSET(sockets->sockets[i], fdset)) { + result = t758_saction(curl, sockets->sockets[i], evBitmask, name); + if(result) + break; + } + } + return result; +} + +static CURLcode t758_one(const char *URL, int timer_fail_at, + int socket_fail_at) +{ + CURLcode res = CURLE_OK; + CURL *curl = NULL; CURLM *m = NULL; + struct t758_ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}}; + int success = 0; + struct curltime timeout = {0}; + timeout.tv_sec = (time_t)-1; + + /* set the limits */ + memset(&t758_ctx, 0, sizeof(t758_ctx)); + t758_ctx.max_timer_calls = timer_fail_at; + t758_ctx.max_socket_calls = socket_fail_at; + + t758_msg("start"); + start_test_timing(); + + if(curl_global_sslset(CURLSSLBACKEND_OPENSSL, NULL, NULL) != CURLSSLSET_OK) { + t758_msg("could not set OpenSSL as backend"); + res = CURLE_FAILED_INIT; + return res; + } + + res_global_init(CURL_GLOBAL_ALL); + if(res != CURLE_OK) + return res; + + curl_global_trace("all"); + + + easy_init(curl); + debug_config.nohex = TRUE; + debug_config.tracetime = TRUE; + test_setopt(curl, CURLOPT_DEBUGDATA, &debug_config); + easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb); + easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + /* specify target */ + easy_setopt(curl, CURLOPT_URL, URL); + + /* go verbose */ + easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, t758_set_ssl_ctx_callback); + + multi_init(m); + + multi_setopt(m, CURLMOPT_SOCKETFUNCTION, t758_curlSocketCallback); + multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets); + + multi_setopt(m, CURLMOPT_TIMERFUNCTION, t758_curlTimerCallback); + multi_setopt(m, CURLMOPT_TIMERDATA, &timeout); + + multi_add_handle(m, curl); + + if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) { + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + while(!t758_checkForCompletion(m, &success)) { + fd_set readSet, writeSet; + curl_socket_t maxFd = 0; + struct timeval tv = {0}; + tv.tv_sec = 10; + + if(t758_ctx.fake_async_cert_verification_pending && + !t758_ctx.fake_async_cert_verification_finished) { + if(sockets.read.count || sockets.write.count) { + t758_msg("during verification there should be no sockets scheduled"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + if(t758_ctx.number_of_cert_verify_callbacks != 1) { + t758_msg("expecting exactly one cert verify callback here"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + t758_ctx.fake_async_cert_verification_finished = 1; + if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) { + t758_msg("spurious retry cert action"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + curl_easy_pause(curl, CURLPAUSE_CONT); + if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) { + t758_msg("unblocking transfer after cert verification finished"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + if(t758_ctx.number_of_cert_verify_callbacks != 2) { + t758_msg("this should have triggered the callback again, right?"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + t758_msg("TEST: all fine?"); + } + FD_ZERO(&readSet); + FD_ZERO(&writeSet); + t758_updateFdSet(&sockets.read, &readSet, &maxFd); + t758_updateFdSet(&sockets.write, &writeSet, &maxFd); + + if(timeout.tv_sec != (time_t)-1) { + int usTimeout = curlx_sztosi(t758_getMicroSecondTimeout(&timeout)); + tv.tv_sec = usTimeout / 1000000; + tv.tv_usec = usTimeout % 1000000; + } + else if(maxFd <= 0) { + tv.tv_sec = 0; + tv.tv_usec = 100000; + } + + select_test((int)maxFd, &readSet, &writeSet, NULL, &tv); + + /* Check the sockets for reading / writing */ + if(t758_checkFdSet(m, &sockets.read, &readSet, CURL_CSELECT_IN, + "read")) { + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + if(t758_checkFdSet(m, &sockets.write, &writeSet, CURL_CSELECT_OUT, + "write")) { + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + + if(timeout.tv_sec != (time_t)-1 && + t758_getMicroSecondTimeout(&timeout) == 0) { + /* Curl's timer has elapsed. */ + if(t758_saction(m, CURL_SOCKET_TIMEOUT, 0, "timeout")) { + res = TEST_ERR_BAD_TIMEOUT; + goto test_cleanup; + } + } + + abort_on_test_timeout(); + } + if(success && t758_ctx.number_of_cert_verify_callbacks != 2) { + t758_msg("unexpected invocations of cert verify callback"); + res = TEST_ERR_MAJOR_BAD; + goto test_cleanup; + } + + if(!success) { + t758_msg("Error getting file."); + res = TEST_ERR_MAJOR_BAD; + } + +test_cleanup: + + /* proper cleanup sequence */ + t758_msg("cleanup"); + curl_multi_remove_handle(m, curl); + curl_easy_cleanup(curl); + curl_multi_cleanup(m); + curl_global_cleanup(); + + /* free local memory */ + free(sockets.read.sockets); + free(sockets.write.sockets); + t758_msg("done"); + + return res; +} + +static CURLcode test_lib758(const char *URL) +{ + CURLcode rc; + /* rerun the same transfer multiple times and make it fail in different + callback calls */ + rc = t758_one(URL, 0, 0); /* no callback fails */ + if(rc) + curl_mfprintf(stderr, "%s FAILED: %d\n", t758_tag(), rc); + + return rc; +} + +#else /* T578_ENABLED */ +static CURLcode test_lib758(const char *URL) +{ + (void)URL; + return CURLE_OK; +} +#endif diff --git a/tests/processhelp.pm b/tests/processhelp.pm index 571ed5b34..43513aae0 100644 --- a/tests/processhelp.pm +++ b/tests/processhelp.pm @@ -27,11 +27,12 @@ package processhelp; use strict; use warnings; +use Time::HiRes; + BEGIN { use base qw(Exporter); our @EXPORT = qw( - portable_sleep pidfromfile pidexists pidwait @@ -42,17 +43,6 @@ BEGIN { set_advisor_read_lock clear_advisor_read_lock ); - - # portable sleeping needs Time::HiRes - eval { - no warnings "all"; - require Time::HiRes; - }; - # portable sleeping falls back to native Sleep on Windows - eval { - no warnings "all"; - require Win32; - } } use serverhelp qw( @@ -65,26 +55,9 @@ use pathhelp qw( os_is_win ); -####################################################################### -# portable_sleep uses Time::HiRes::sleep if available and falls back -# to the classic approach of using select(undef, undef, undef, ...). -# even though that one is not portable due to being implemented using -# select on Windows: https://perldoc.perl.org/perlport.html#select -# Therefore it uses Win32::Sleep on Windows systems instead. -# -sub portable_sleep { - my ($seconds) = @_; - - if($Time::HiRes::VERSION) { - Time::HiRes::sleep($seconds); - } - elsif(os_is_win()) { - Win32::Sleep($seconds*1000); - } - else { - select(undef, undef, undef, $seconds); - } -} +use globalconfig qw( + $dev_null + ); ####################################################################### # pidfromfile returns the pid stored in the given pidfile. The value @@ -143,7 +116,7 @@ sub pidexists { if($^O ne 'MSWin32') { my $filter = "PID eq $pid"; # https://ss64.com/nt/tasklist.html - my $result = `tasklist -fi \"$filter\" 2>nul`; + my $result = `tasklist -fi \"$filter\" 2>$dev_null`; if(index($result, "$pid") != -1) { return -$pid; } @@ -173,7 +146,7 @@ sub pidterm { $pid -= 4194304; if($^O ne 'MSWin32') { # https://ss64.com/nt/taskkill.html - my $cmd = "taskkill -f -t -pid $pid >nul 2>&1"; + my $cmd = "taskkill -f -t -pid $pid >$dev_null 2>&1"; print "Executing: '$cmd'\n"; system($cmd); return; @@ -198,7 +171,7 @@ sub pidkill { $pid -= 4194304; if($^O ne 'MSWin32') { # https://ss64.com/nt/taskkill.html - my $cmd = "taskkill -f -t -pid $pid >nul 2>&1"; + my $cmd = "taskkill -f -t -pid $pid >$dev_null 2>&1"; print "Executing: '$cmd'\n"; system($cmd); return; @@ -234,7 +207,7 @@ sub pidwait { last; } } - portable_sleep(0.2); + Time::HiRes::sleep(0.2); } return $pid; } @@ -342,7 +315,7 @@ sub killpid { last if(not scalar(@signalled)); # give any zombies of us a chance to move on to the afterlife pidwait(0, &WNOHANG); - portable_sleep(0.05); + Time::HiRes::sleep(0.05); } } diff --git a/tests/runner.pm b/tests/runner.pm index a208eba3a..18f3c5098 100644 --- a/tests/runner.pm +++ b/tests/runner.pm @@ -39,6 +39,7 @@ use warnings; use 5.006; use File::Basename; +use Time::HiRes; BEGIN { use base qw(Exporter); @@ -84,9 +85,6 @@ use Storable qw( use pathhelp qw( exe_ext ); -use processhelp qw( - portable_sleep - ); use servers qw( checkcmd initserverconfig @@ -419,7 +417,7 @@ sub waitlockunlock { my $lockretry = $serverlogslocktimeout * 20; my @locks; while((@locks = logslocked()) && $lockretry--) { - portable_sleep(0.05); + Time::HiRes::sleep(0.05); } if(($lockretry < 0) && ($serverlogslocktimeout >= $defserverlogslocktimeout)) { @@ -1092,7 +1090,7 @@ sub singletest_clean { } } - portable_sleep($postcommanddelay) if($postcommanddelay); + Time::HiRes::sleep($postcommanddelay) if($postcommanddelay); my @killtestservers = getpart("client", "killserver"); if(@killtestservers) { diff --git a/tests/runtests.pl b/tests/runtests.pl index 407a37946..a470597bf 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -92,9 +92,6 @@ use pathhelp qw( exe_ext sys_native_current_path ); -use processhelp qw( - portable_sleep - ); use appveyor; use azure; diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm index fd762935a..1a3c99775 100644 --- a/tests/serverhelp.pm +++ b/tests/serverhelp.pm @@ -29,6 +29,8 @@ package serverhelp; use strict; use warnings; +use Time::HiRes; + BEGIN { use base qw(Exporter); @@ -52,13 +54,6 @@ BEGIN { datasockf_pidfilename datasockf_logfilename ); - - # sub second timestamping needs Time::HiRes - eval { - no warnings "all"; - require Time::HiRes; - import Time::HiRes qw( gettimeofday ); - } } use globalconfig; @@ -81,20 +76,10 @@ our $logfile; # server log file name, for logmsg # logmsg is general message logging subroutine for our test servers. # sub logmsg { - my $now; - # sub second timestamping needs Time::HiRes - if($Time::HiRes::VERSION) { - my ($seconds, $usec) = gettimeofday(); - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = - localtime($seconds); - $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec); - } - else { - my $seconds = time(); - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = - localtime($seconds); - $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec); - } + my ($seconds, $usec) = Time::HiRes::gettimeofday(); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime($seconds); + my $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec); # we see warnings on Windows run that $logfile is used uninitialized # TODO: not found yet where this comes from $logfile = "serverhelp_uninitialized.log" if(!$logfile); diff --git a/tests/servers.pm b/tests/servers.pm index 02415c6ff..94809d3e7 100644 --- a/tests/servers.pm +++ b/tests/servers.pm @@ -380,7 +380,7 @@ sub startnew { logmsg "startnew: failed to write fake $pidfile with pid=$child\n"; } # could/should do a while connect fails sleep a bit and loop - portable_sleep($timeout); + Time::HiRes::sleep($timeout); if(checkdied($child)) { logmsg "startnew: child process has failed to start\n" if($verbose); return (-1,-1); |