1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

multi tests: OOM handling fixes

Additionally, improved error checking and logging.
This commit is contained in:
Yang Tse 2011-10-21 16:26:18 +02:00
parent 90fcad63cb
commit 629d2e3450
22 changed files with 1053 additions and 1354 deletions

View File

@ -35,9 +35,10 @@ http://%HOSTIP:%HTTPSPORT/504 %HOSTIP:55555
</client> </client>
# Verify data after the test has been "shot" # Verify data after the test has been "shot"
# TEST_ERR_SUCCESS is errorcode 120
<verify> <verify>
<errorcode> <errorcode>
100 120
</errorcode> </errorcode>
</verify> </verify>
</testcase> </testcase>

View File

@ -32,11 +32,10 @@ ftp://%HOSTIP:%FTPPORT/538
</client> </client>
# Verify data after the test has been "shot" # Verify data after the test has been "shot"
# TEST_ERR_SUCCESS is errorcode 120
<verify> <verify>
# ok, the error code here is supposed to be 100 for the fine case since
# that's just how lib504.c is written
<errorcode> <errorcode>
100 120
</errorcode> </errorcode>
<protocol> <protocol>
USER anonymous USER anonymous

View File

@ -93,7 +93,7 @@ lib537_SOURCES = lib537.c $(SUPPORTFILES) $(WARNLESS)
lib539_SOURCES = lib539.c $(SUPPORTFILES) lib539_SOURCES = lib539.c $(SUPPORTFILES)
lib540_SOURCES = lib540.c $(SUPPORTFILES) $(WARNLESS) lib540_SOURCES = lib540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib541_SOURCES = lib541.c $(SUPPORTFILES) lib541_SOURCES = lib541.c $(SUPPORTFILES)
@ -125,11 +125,11 @@ lib556_SOURCES = lib556.c $(SUPPORTFILES)
lib557_SOURCES = lib557.c $(SUPPORTFILES) lib557_SOURCES = lib557.c $(SUPPORTFILES)
lib560_SOURCES = lib560.c $(SUPPORTFILES) $(WARNLESS) lib560_SOURCES = lib560.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib574_SOURCES = lib574.c $(SUPPORTFILES) lib574_SOURCES = lib574.c $(SUPPORTFILES)
lib575_SOURCES = lib575.c $(SUPPORTFILES) $(WARNLESS) lib575_SOURCES = lib575.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib576_SOURCES = lib576.c $(SUPPORTFILES) lib576_SOURCES = lib576.c $(SUPPORTFILES)

View File

@ -30,19 +30,25 @@
# include "memdebug.h" # include "memdebug.h"
#endif #endif
int select_test (int num_fds, fd_set *rd, fd_set *wr, fd_set *exc, int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
struct timeval *tv) struct timeval *tv)
{ {
if(nfds < 0) {
SET_SOCKERRNO(EINVAL);
return -1;
}
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
/* Winsock doesn't like no socket set in 'rd', 'wr' or 'exc'. This is /*
* case when 'num_fds <= 0. So sleep. * Winsock select() requires that at least one of the three fd_set
* pointers is not NULL and points to a non-empty fdset. IOW Winsock
* select() can not be used to sleep without a single fd_set.
*/ */
if (num_fds <= 0) { if(!nfds) {
Sleep(1000*tv->tv_sec + tv->tv_usec/1000); Sleep(1000*tv->tv_sec + tv->tv_usec/1000);
return 0; return 0;
} }
#endif #endif
return select(num_fds, rd, wr, exc, tv); return select(nfds, rd, wr, exc, tv);
} }
char *libtest_arg2=NULL; char *libtest_arg2=NULL;
@ -50,6 +56,8 @@ char *libtest_arg3=NULL;
int test_argc; int test_argc;
char **test_argv; char **test_argv;
struct timeval tv_test_start; /* for test timing */
#ifdef UNITTESTS #ifdef UNITTESTS
int unitfail; /* for unittests */ int unitfail; /* for unittests */
#endif #endif

View File

@ -25,8 +25,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
/* /*
* Get a single URL without select(). * Get a single URL without select().
@ -34,90 +33,57 @@
int test(char *URL) int test(char *URL)
{ {
CURL *c; CURL *c = NULL;
CURLM *m = NULL; CURLM *m = NULL;
int res = 0; int res = 0;
int running=1; int running;
struct timeval mp_start;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((c = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(c, CURLOPT_URL, URL); easy_init(c);
if ((m = curl_multi_init()) == NULL) { easy_setopt(c, CURLOPT_URL, URL);
fprintf(stderr, "curl_multi_init() failed\n");
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) { multi_init(m);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
mp_timedout = FALSE; multi_add_handle(m, c);
mp_start = tutil_tvnow();
while (running) { for(;;) {
static struct timeval timeout = /* 100 ms */ { 0, 100000L }; struct timeval timeout;
fd_set fdread, fdwrite, fdexcep; fd_set fdread, fdwrite, fdexcep;
int maxfd = -1; int maxfd = -99;
res = (int)curl_multi_perform(m, &running); timeout.tv_sec = 0;
if (tutil_tvdiff(tutil_tvnow(), mp_start) > timeout.tv_usec = 100000L; /* 100 ms */
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE; multi_perform(m, &running);
break;
} abort_on_test_timeout();
if (running <= 0) {
fprintf(stderr, "nothing left running.\n"); if(!running)
break; break; /* done */
}
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);
curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
res = ~CURLM_OK;
break;
}
}
if (mp_timedout) { select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
"that it would have run forever.\n"); abort_on_test_timeout();
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m); curl_multi_remove_handle(m, c);
} curl_multi_cleanup(m);
curl_easy_cleanup(c); curl_easy_cleanup(c);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -25,8 +25,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
/* /*
* Source code in here hugely as reported in bug report 651460 by * Source code in here hugely as reported in bug report 651460 by
@ -38,121 +37,62 @@
int test(char *URL) int test(char *URL)
{ {
CURL *c; CURL *c = NULL;
CURLM *m = NULL; CURLM *m = NULL;
int res = 0; int res = 0;
int running; int running;
char done = FALSE;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((c = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */ easy_init(c);
test_setopt(c, CURLOPT_URL, URL);
test_setopt(c, CURLOPT_USERPWD, "test:ing");
test_setopt(c, CURLOPT_PROXYUSERPWD, "test:ing");
test_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L);
test_setopt(c, CURLOPT_HEADER, 1L);
if ((m = curl_multi_init()) == NULL) { easy_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */
fprintf(stderr, "curl_multi_init() failed\n"); easy_setopt(c, CURLOPT_URL, URL);
curl_easy_cleanup(c); easy_setopt(c, CURLOPT_USERPWD, "test:ing");
curl_global_cleanup(); easy_setopt(c, CURLOPT_PROXYUSERPWD, "test:ing");
return TEST_ERR_MAJOR_BAD; easy_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L);
} easy_setopt(c, CURLOPT_HEADER, 1L);
if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) { multi_init(m);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; multi_add_handle(m, c);
ml_start = tutil_tvnow();
while(!done) { for(;;) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
done = TRUE;
break;
}
if (mp_timedout || done) if(!running)
break; break; /* done */
if (res != CURLM_OK) {
fprintf(stderr, "not okay???\n");
break;
}
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 89;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 95;
break;
}
} select_test(maxfd+1, &rd, &wr, &exc, &interval);
if (ml_timedout || mp_timedout) { abort_on_test_timeout();
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m); curl_multi_remove_handle(m, c);
} curl_multi_cleanup(m);
curl_easy_cleanup(c); curl_easy_cleanup(c);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -25,8 +25,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
/* /*
* Source code in here hugely as reported in bug report 651464 by * Source code in here hugely as reported in bug report 651464 by
@ -37,81 +36,41 @@
*/ */
int test(char *URL) int test(char *URL)
{ {
CURL *c; CURL *c = NULL;
int res = 0; int res = 0;
CURLM *m = NULL; CURLM *m = NULL;
fd_set rd, wr, exc; fd_set rd, wr, exc;
CURLMcode ret;
char done = FALSE;
int running; int running;
int max_fd;
int rc;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((c = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup(); easy_init(c);
return TEST_ERR_MAJOR_BAD;
}
/* The point here is that there must not be anything running on the given /* The point here is that there must not be anything running on the given
proxy port */ proxy port */
if (libtest_arg2) if (libtest_arg2)
test_setopt(c, CURLOPT_PROXY, libtest_arg2); easy_setopt(c, CURLOPT_PROXY, libtest_arg2);
test_setopt(c, CURLOPT_URL, URL); easy_setopt(c, CURLOPT_URL, URL);
test_setopt(c, CURLOPT_VERBOSE, 1L); easy_setopt(c, CURLOPT_VERBOSE, 1L);
if ((m = curl_multi_init()) == NULL) { multi_init(m);
fprintf(stderr, "curl_multi_init() failed\n");
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((ret = curl_multi_add_handle(m, c)) != CURLM_OK) { multi_add_handle(m, c);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", ret);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; for(;;) {
ml_start = tutil_tvnow();
while (!done) {
struct timeval interval; struct timeval interval;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) >
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
fprintf(stderr, "curl_multi_perform()\n"); fprintf(stderr, "curl_multi_perform()\n");
ret = curl_multi_perform(m, &running); multi_perform(m, &running);
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) { abort_on_test_timeout();
mp_timedout = TRUE;
break;
}
if (mp_timedout)
break;
if(!running) { if(!running) {
/* This is where this code is expected to reach */ /* This is where this code is expected to reach */
@ -119,47 +78,34 @@ int test(char *URL)
CURLMsg *msg = curl_multi_info_read(m, &numleft); CURLMsg *msg = curl_multi_info_read(m, &numleft);
fprintf(stderr, "Expected: not running\n"); fprintf(stderr, "Expected: not running\n");
if(msg && !numleft) if(msg && !numleft)
res = 100; /* this is where we should be */ res = TEST_ERR_SUCCESS; /* this is where we should be */
else else
res = 99; /* not correct */ res = TEST_ERR_FAILURE; /* not correct */
break; break; /* done */
}
fprintf(stderr, "running == %d, ret == %d\n", running, ret);
if (ret != CURLM_OK) {
res = 2;
break;
} }
fprintf(stderr, "running == %d\n", running);
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
fprintf(stderr, "curl_multi_fdset()\n"); fprintf(stderr, "curl_multi_fdset()\n");
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
fprintf(stderr, "unexpected failured of fdset.\n");
res = 3;
break;
}
rc = select_test(max_fd+1, &rd, &wr, &exc, &interval);
fprintf(stderr, "select returned %d\n", rc);
}
if (ml_timedout || mp_timedout) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n"); /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n"); select_test(maxfd+1, &rd, &wr, &exc, &interval);
res = TEST_ERR_RUNS_FOREVER;
abort_on_test_timeout();
} }
test_cleanup: test_cleanup:
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m); curl_multi_remove_handle(m, c);
} curl_multi_cleanup(m);
curl_easy_cleanup(c); curl_easy_cleanup(c);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -25,71 +25,40 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
int test(char *URL) int test(char *URL)
{ {
CURL* curls; CURL* curls = NULL;
CURLM* multi; CURLM* multi = NULL;
int still_running; int still_running;
int i = -1; int i = -1;
int res = 0; int res = 0;
CURLMsg *msg; CURLMsg *msg;
CURLMcode ret;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((multi = curl_multi_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_multi_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((curls = curl_easy_init()) == NULL) { multi_init(multi);
fprintf(stderr, "curl_easy_init() failed\n");
curl_multi_cleanup(multi);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curls, CURLOPT_URL, URL); easy_init(curls);
test_setopt(curls, CURLOPT_HEADER, 1L);
if ((ret = curl_multi_add_handle(multi, curls)) != CURLM_OK) { easy_setopt(curls, CURLOPT_URL, URL);
fprintf(stderr, "curl_multi_add_handle() failed, " easy_setopt(curls, CURLOPT_HEADER, 1L);
"with code %d\n", ret);
curl_easy_cleanup(curls);
curl_multi_cleanup(multi);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
mp_timedout = FALSE; multi_add_handle(multi, curls);
mp_start = tutil_tvnow();
ret = curl_multi_perform(multi, &still_running); multi_perform(multi, &still_running);
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT)
mp_timedout = TRUE;
ml_timedout = FALSE; abort_on_test_timeout();
ml_start = tutil_tvnow();
while ((!ml_timedout) && (!mp_timedout) && (still_running)) { while(still_running) {
struct timeval timeout; struct timeval timeout;
int rc;
fd_set fdread; fd_set fdread;
fd_set fdwrite; fd_set fdwrite;
fd_set fdexcep; fd_set fdexcep;
int maxfd; int maxfd = -99;
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
@ -97,47 +66,29 @@ int test(char *URL)
timeout.tv_sec = 1; timeout.tv_sec = 1;
timeout.tv_usec = 0; timeout.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); /* At this point, maxfd is guaranteed to be greater or equal than -1. */
rc = select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) { select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
case -1:
break; abort_on_test_timeout();
case 0:
default: multi_perform(multi, &still_running);
mp_timedout = FALSE;
mp_start = tutil_tvnow(); abort_on_test_timeout();
ret = curl_multi_perform(multi, &still_running);
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT)
mp_timedout = TRUE;
break;
}
}
if (ml_timedout || mp_timedout) {
if (ml_timedout)
fprintf(stderr, "ml_timedout\n");
if (mp_timedout)
fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
i = TEST_ERR_RUNS_FOREVER;
}
else {
msg = curl_multi_info_read(multi, &still_running);
if(msg)
/* this should now contain a result code from the easy handle,
get it */
i = msg->data.result;
} }
msg = curl_multi_info_read(multi, &still_running);
if(msg)
/* this should now contain a result code from the easy handle,
get it */
i = msg->data.result;
test_cleanup: test_cleanup:
/* undocumented cleanup sequence - type UA */
curl_multi_cleanup(multi); curl_multi_cleanup(multi);
curl_easy_cleanup(curls); curl_easy_cleanup(curls);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -27,37 +27,39 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
int test(char *URL) int test(char *URL)
{ {
int res = 0; int res = 0;
CURL *curl; CURL *curl = NULL;
FILE *hd_src ; FILE *hd_src = NULL;
int hd ; int hd ;
int error; int error;
struct_stat file_info; struct_stat file_info;
int running;
char done=FALSE;
CURLM *m = NULL; CURLM *m = NULL;
struct timeval ml_start; int running;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (!libtest_arg2) { start_test_timing();
if(!libtest_arg2) {
#ifdef LIB529
/* test 529 */
fprintf(stderr, "Usage: lib529 [url] [uploadfile]\n");
#else
/* test 525 */
fprintf(stderr, "Usage: lib525 [url] [uploadfile]\n"); fprintf(stderr, "Usage: lib525 [url] [uploadfile]\n");
return -1; #endif
return TEST_ERR_USAGE;
} }
hd_src = fopen(libtest_arg2, "rb"); hd_src = fopen(libtest_arg2, "rb");
if(NULL == hd_src) { if(NULL == hd_src) {
error = ERRNO; error = ERRNO;
fprintf(stderr, "fopen() failed with error: %d %s\n", fprintf(stderr, "fopen() failed with error: %d (%s)\n",
error, strerror(error)); error, strerror(error));
fprintf(stderr, "Error opening file: %s\n", libtest_arg2); fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
return TEST_ERR_MAJOR_BAD; return TEST_ERR_FOPEN;
} }
/* get the file size of the local file */ /* get the file size of the local file */
@ -65,40 +67,35 @@ int test(char *URL)
if(hd == -1) { if(hd == -1) {
/* can't open file, bail out */ /* can't open file, bail out */
error = ERRNO; error = ERRNO;
fprintf(stderr, "fstat() failed with error: %d %s\n", fprintf(stderr, "fstat() failed with error: %d (%s)\n",
error, strerror(error)); error, strerror(error));
fprintf(stderr, "ERROR: cannot open file %s\n", libtest_arg2); fprintf(stderr, "ERROR: cannot open file (%s)\n", libtest_arg2);
fclose(hd_src); fclose(hd_src);
return -1; return TEST_ERR_FSTAT;
} }
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { res_global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_global_init() failed\n"); if(res) {
fclose(hd_src); fclose(hd_src);
return TEST_ERR_MAJOR_BAD; return res;
} }
if ((curl = curl_easy_init()) == NULL) { easy_init(curl);
fprintf(stderr, "curl_easy_init() failed\n");
fclose(hd_src);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
/* enable uploading */ /* enable uploading */
test_setopt(curl, CURLOPT_UPLOAD, 1L); easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */ /* specify target */
test_setopt(curl,CURLOPT_URL, URL); easy_setopt(curl,CURLOPT_URL, URL);
/* go verbose */ /* go verbose */
test_setopt(curl, CURLOPT_VERBOSE, 1L); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* use active FTP */ /* use active FTP */
test_setopt(curl, CURLOPT_FTPPORT, "-"); easy_setopt(curl, CURLOPT_FTPPORT, "-");
/* now specify which file to upload */ /* now specify which file to upload */
test_setopt(curl, CURLOPT_READDATA, hd_src); easy_setopt(curl, CURLOPT_READDATA, hd_src);
/* NOTE: if you want this code to work on Windows with libcurl as a DLL, you /* NOTE: if you want this code to work on Windows with libcurl as a DLL, you
MUST also provide a read callback with CURLOPT_READFUNCTION. Failing to MUST also provide a read callback with CURLOPT_READFUNCTION. Failing to
@ -109,110 +106,60 @@ int test(char *URL)
option you MUST make sure that the type of the passed-in argument is a option you MUST make sure that the type of the passed-in argument is a
curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
make sure that to pass in a type 'long' argument. */ make sure that to pass in a type 'long' argument. */
test_setopt(curl, CURLOPT_INFILESIZE_LARGE, easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
(curl_off_t)file_info.st_size);
if ((m = curl_multi_init()) == NULL) { multi_init(m);
fprintf(stderr, "curl_multi_init() failed\n");
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(hd_src);
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) { multi_add_handle(m, curl);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(hd_src);
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; for(;;) {
ml_start = tutil_tvnow();
while (!done) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
done = TRUE;
break;
}
if (res != CURLM_OK) { if(!running)
fprintf(stderr, "not okay???\n"); break; /* done */
break;
}
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 189;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 195;
break;
}
res = CURLM_CALL_MULTI_PERFORM; select_test(maxfd+1, &rd, &wr, &exc, &interval);
}
if (ml_timedout || mp_timedout) { abort_on_test_timeout();
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
#ifdef LIB529 #ifdef LIB529
/* test 529 */ /* test 529 */
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, curl); curl_multi_remove_handle(m, curl);
curl_multi_cleanup(m); curl_multi_cleanup(m);
}
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_global_cleanup();
#else #else
/* test 525 */ /* test 525 */
if(m) /* proper cleanup sequence - type PB */
curl_multi_remove_handle(m, curl); curl_multi_remove_handle(m, curl);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if(m) curl_multi_cleanup(m);
curl_multi_cleanup(m); curl_global_cleanup();
#endif #endif
fclose(hd_src); /* close the local file */ /* close the local file */
fclose(hd_src);
curl_global_cleanup();
return res; return res;
} }

View File

@ -46,8 +46,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
#define NUM_HANDLES 4 #define NUM_HANDLES 4
@ -56,109 +55,51 @@ int test(char *URL)
int res = 0; int res = 0;
CURL *curl[NUM_HANDLES]; CURL *curl[NUM_HANDLES];
int running; int running;
char done=FALSE;
CURLM *m = NULL; CURLM *m = NULL;
int current=0; int current = 0;
int i, j; int i;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { for(i=0; i < NUM_HANDLES; i++)
fprintf(stderr, "curl_global_init() failed\n"); curl[i] = NULL;
return TEST_ERR_MAJOR_BAD;
} start_test_timing();
global_init(CURL_GLOBAL_ALL);
/* get NUM_HANDLES easy handles */ /* get NUM_HANDLES easy handles */
for(i=0; i < NUM_HANDLES; i++) { for(i=0; i < NUM_HANDLES; i++) {
curl[i] = curl_easy_init(); easy_init(curl[i]);
if(!curl[i]) { /* specify target */
fprintf(stderr, "curl_easy_init() failed " easy_setopt(curl[i], CURLOPT_URL, URL);
"on handle #%d\n", i);
for (j=i-1; j >= 0; j--) {
curl_easy_cleanup(curl[j]);
}
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
res = curl_easy_setopt(curl[i], CURLOPT_URL, URL);
if(res) {
fprintf(stderr, "curl_easy_setopt() failed "
"on handle #%d\n", i);
for (j=i; j >= 0; j--) {
curl_easy_cleanup(curl[j]);
}
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
/* go verbose */ /* go verbose */
res = curl_easy_setopt(curl[i], CURLOPT_VERBOSE, 1L); easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
if(res) {
fprintf(stderr, "curl_easy_setopt() failed "
"on handle #%d\n", i);
for (j=i; j >= 0; j--) {
curl_easy_cleanup(curl[j]);
}
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
} }
if ((m = curl_multi_init()) == NULL) { multi_init(m);
fprintf(stderr, "curl_multi_init() failed\n");
for(i=0; i < NUM_HANDLES; i++) {
curl_easy_cleanup(curl[i]);
}
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, curl[current])) != CURLM_OK) { multi_add_handle(m, curl[current]);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
for(i=0; i < NUM_HANDLES; i++) {
curl_easy_cleanup(curl[i]);
}
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE;
ml_start = tutil_tvnow();
fprintf(stderr, "Start at URL 0\n"); fprintf(stderr, "Start at URL 0\n");
while (!done) { for(;;) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) { if(!running) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
#ifdef LIB527 #ifdef LIB527
/* NOTE: this code does not remove the handle from the multi handle /* NOTE: this code does not remove the handle from the multi handle
here, which would be the nice, sane and documented way of working. here, which would be the nice, sane and documented way of working.
This however tests that the API survives this abuse gracefully. */ This however tests that the API survives this abuse gracefully. */
curl_easy_cleanup(curl[current]); curl_easy_cleanup(curl[current]);
curl[current] = NULL;
#endif #endif
if(++current < NUM_HANDLES) { if(++current < NUM_HANDLES) {
fprintf(stderr, "Advancing to URL %d\n", current); fprintf(stderr, "Advancing to URL %d\n", current);
@ -169,74 +110,75 @@ int test(char *URL)
/* make us re-use the same handle all the time, and try resetting /* make us re-use the same handle all the time, and try resetting
the handle first too */ the handle first too */
curl_easy_reset(curl[0]); curl_easy_reset(curl[0]);
test_setopt(curl[0], CURLOPT_URL, URL); easy_setopt(curl[0], CURLOPT_URL, URL);
test_setopt(curl[0], CURLOPT_VERBOSE, 1L); /* go verbose */
easy_setopt(curl[0], CURLOPT_VERBOSE, 1L);
/* re-add it */ /* re-add it */
res = (int)curl_multi_add_handle(m, curl[0]); multi_add_handle(m, curl[0]);
#else #else
res = (int)curl_multi_add_handle(m, curl[current]); multi_add_handle(m, curl[current]);
#endif #endif
if(res) {
fprintf(stderr, "add handle failed: %d.\n", res);
res = 243;
break;
}
} }
else { else {
done = TRUE; /* bail out */ break; /* done */
break;
} }
} }
if (res != CURLM_OK) {
fprintf(stderr, "not okay???\n");
break;
}
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 189;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 195; select_test(maxfd+1, &rd, &wr, &exc, &interval);
break;
} abort_on_test_timeout();
} }
if (ml_timedout || mp_timedout) {
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
}
#ifdef LIB532
test_cleanup: test_cleanup:
#endif
#ifndef LIB527 #if defined(LIB526)
/* get NUM_HANDLES easy handles */
/* test 526 and 528 */
/* proper cleanup sequence - type PB */
for(i=0; i < NUM_HANDLES; i++) { for(i=0; i < NUM_HANDLES; i++) {
#ifdef LIB526 curl_multi_remove_handle(m, curl[i]);
if(m)
curl_multi_remove_handle(m, curl[i]);
#endif
curl_easy_cleanup(curl[i]); curl_easy_cleanup(curl[i]);
} }
#endif curl_multi_cleanup(m);
if(m)
curl_multi_cleanup(m);
curl_global_cleanup(); curl_global_cleanup();
#elif defined(LIB527)
/* test 527 */
/* Upon non-failure test flow the easy's have already been cleanup'ed. In
case there is a failure we arrive here with easy's that have not been
cleanup'ed yet, in this case we have to cleanup them or otherwise these
will be leaked, let's use undocumented cleanup sequence - type UB */
if(res)
for(i=0; i < NUM_HANDLES; i++)
curl_easy_cleanup(curl[i]);
curl_multi_cleanup(m);
curl_global_cleanup();
#elif defined(LIB532)
/* test 532 */
/* undocumented cleanup sequence - type UB */
for(i=0; i < NUM_HANDLES; i++)
curl_easy_cleanup(curl[i]);
curl_multi_cleanup(m);
curl_global_cleanup();
#endif
return res; return res;
} }

View File

@ -25,8 +25,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
#define NUM_HANDLES 4 #define NUM_HANDLES 4
@ -35,169 +34,71 @@ int test(char *URL)
int res = 0; int res = 0;
CURL *curl[NUM_HANDLES]; CURL *curl[NUM_HANDLES];
int running; int running;
char done=FALSE; CURLM *m = NULL;
CURLM *m; int i;
int i, j;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
char target_url[256]; char target_url[256];
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { for(i=0; i < NUM_HANDLES; i++)
fprintf(stderr, "curl_global_init() failed\n"); curl[i] = NULL;
return TEST_ERR_MAJOR_BAD;
}
if ((m = curl_multi_init()) == NULL) { start_test_timing();
fprintf(stderr, "curl_multi_init() failed\n");
curl_global_cleanup(); global_init(CURL_GLOBAL_ALL);
return TEST_ERR_MAJOR_BAD;
} multi_init(m);
/* get NUM_HANDLES easy handles */ /* get NUM_HANDLES easy handles */
for(i=0; i < NUM_HANDLES; i++) { for(i=0; i < NUM_HANDLES; i++) {
curl[i] = curl_easy_init(); /* get an easy handle */
if(!curl[i]) { easy_init(curl[i]);
fprintf(stderr, "curl_easy_init() failed " /* specify target */
"on handle #%d\n", i);
for (j=i-1; j >= 0; j--) {
curl_multi_remove_handle(m, curl[j]);
curl_easy_cleanup(curl[j]);
}
curl_multi_cleanup(m);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
sprintf(target_url, "%s%04i", URL, i + 1); sprintf(target_url, "%s%04i", URL, i + 1);
target_url[sizeof(target_url) - 1] = '\0'; target_url[sizeof(target_url) - 1] = '\0';
easy_setopt(curl[i], CURLOPT_URL, target_url);
res = curl_easy_setopt(curl[i], CURLOPT_URL, target_url);
if(res) {
fprintf(stderr, "curl_easy_setopt() failed "
"on handle #%d\n", i);
for (j=i; j >= 0; j--) {
curl_multi_remove_handle(m, curl[j]);
curl_easy_cleanup(curl[j]);
}
curl_multi_cleanup(m);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
/* go verbose */ /* go verbose */
res = curl_easy_setopt(curl[i], CURLOPT_VERBOSE, 1L); easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
if(res) {
fprintf(stderr, "curl_easy_setopt() failed "
"on handle #%d\n", i);
for (j=i; j >= 0; j--) {
curl_multi_remove_handle(m, curl[j]);
curl_easy_cleanup(curl[j]);
}
curl_multi_cleanup(m);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
/* include headers */ /* include headers */
res = curl_easy_setopt(curl[i], CURLOPT_HEADER, 1L); easy_setopt(curl[i], CURLOPT_HEADER, 1L);
if(res) {
fprintf(stderr, "curl_easy_setopt() failed "
"on handle #%d\n", i);
for (j=i; j >= 0; j--) {
curl_multi_remove_handle(m, curl[j]);
curl_easy_cleanup(curl[j]);
}
curl_multi_cleanup(m);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
/* add handle to multi */ /* add handle to multi */
if ((res = (int)curl_multi_add_handle(m, curl[i])) != CURLM_OK) { multi_add_handle(m, curl[i]);
fprintf(stderr, "curl_multi_add_handle() failed, "
"on handle #%d with code %d\n", i, res);
curl_easy_cleanup(curl[i]);
for (j=i-1; j >= 0; j--) {
curl_multi_remove_handle(m, curl[j]);
curl_easy_cleanup(curl[j]);
}
curl_multi_cleanup(m);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD + i;
}
} }
curl_multi_setopt(m, CURLMOPT_PIPELINING, 1L); multi_setopt(m, CURLMOPT_PIPELINING, 1L);
ml_timedout = FALSE;
ml_start = tutil_tvnow();
fprintf(stderr, "Start at URL 0\n"); fprintf(stderr, "Start at URL 0\n");
while (!done) { for(;;) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
done = TRUE; /* bail out */
break;
}
if (res != CURLM_OK) { if(!running)
fprintf(stderr, "not okay???\n"); break; /* done */
break;
}
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 189;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 195;
break;
}
res = CURLM_CALL_MULTI_PERFORM; select_test(maxfd+1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
} }
if (ml_timedout || mp_timedout) { test_cleanup:
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
}
/* test_cleanup: */ /* proper cleanup sequence - type PB */
/* cleanup NUM_HANDLES easy handles */
for(i=0; i < NUM_HANDLES; i++) { for(i=0; i < NUM_HANDLES; i++) {
curl_multi_remove_handle(m, curl[i]); curl_multi_remove_handle(m, curl[i]);
curl_easy_cleanup(curl[i]); curl_easy_cleanup(curl[i]);

View File

@ -29,81 +29,45 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
int test(char *URL) int test(char *URL)
{ {
int res = 0; int res = 0;
CURL *curl; CURL *curl = NULL;
int running; int running;
char done=FALSE;
CURLM *m = NULL; CURLM *m = NULL;
int current=0; int current=0;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((curl = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_URL, URL); easy_init(curl);
test_setopt(curl, CURLOPT_VERBOSE, 1);
test_setopt(curl, CURLOPT_FAILONERROR, 1);
if ((m = curl_multi_init()) == NULL) { easy_setopt(curl, CURLOPT_URL, URL);
fprintf(stderr, "curl_multi_init() failed\n"); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_cleanup(curl); easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) { multi_init(m);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(curl);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; multi_add_handle(m, curl);
ml_start = tutil_tvnow();
fprintf(stderr, "Start at URL 0\n"); fprintf(stderr, "Start at URL 0\n");
while (!done) { for(;;) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) { if(!running) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
if(!current++) { if(!current++) {
fprintf(stderr, "Advancing to URL 1\n"); fprintf(stderr, "Advancing to URL 1\n");
/* remove the handle we use */ /* remove the handle we use */
@ -112,62 +76,36 @@ int test(char *URL)
/* make us re-use the same handle all the time, and try resetting /* make us re-use the same handle all the time, and try resetting
the handle first too */ the handle first too */
curl_easy_reset(curl); curl_easy_reset(curl);
test_setopt(curl, CURLOPT_URL, libtest_arg2); easy_setopt(curl, CURLOPT_URL, libtest_arg2);
test_setopt(curl, CURLOPT_VERBOSE, 1); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_FAILONERROR, 1); easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
/* re-add it */ /* re-add it */
res = (int)curl_multi_add_handle(m, curl); multi_add_handle(m, curl);
if(res) {
fprintf(stderr, "add handle failed: %d.\n", res);
res = 243;
break;
}
} }
else { else
done = TRUE; /* bail out */ break; /* done */
break;
}
}
if (res != CURLM_OK) {
fprintf(stderr, "not okay???\n");
break;
} }
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 189;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 195;
break;
}
res = CURLM_CALL_MULTI_PERFORM; select_test(maxfd+1, &rd, &wr, &exc, &interval);
}
if (ml_timedout || mp_timedout) { abort_on_test_timeout();
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
/* undocumented cleanup sequence - type UB */
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if(m) curl_multi_cleanup(m);
curl_multi_cleanup(m);
curl_global_cleanup(); curl_global_cleanup();
return res; return res;

View File

@ -27,118 +27,111 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
static CURLMcode perform(CURLM * multi) static int perform(CURLM *multi)
{ {
int handles; int handles;
CURLMcode code;
fd_set fdread, fdwrite, fdexcep; fd_set fdread, fdwrite, fdexcep;
struct timeval mp_start; int res = 0;
char mp_timedout = FALSE;
mp_timedout = FALSE; for(;;) {
mp_start = tutil_tvnow(); struct timeval interval;
int maxfd = -99;
for (;;) { interval.tv_sec = 0;
static struct timeval timeout = /* 100 ms */ { 0, 100000L }; interval.tv_usec = 100000L; /* 100 ms */
int maxfd = -1;
code = curl_multi_perform(multi, &handles); res_multi_perform(multi, &handles);
if (tutil_tvdiff(tutil_tvnow(), mp_start) > if(res)
MULTI_PERFORM_HANG_TIMEOUT) { return res;
mp_timedout = TRUE;
break;
}
if (handles <= 0)
return CURLM_OK;
switch (code) { res_test_timedout();
case CURLM_OK: if(res)
break; return res;
default:
return code; if(!handles)
} break; /* done */
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);
curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the res_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
function calls. On success, the value of maxfd is guaranteed to be if(res)
greater or equal than -1. We call select(maxfd + 1, ...), specially in return res;
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) /* At this point, maxfd is guaranteed to be greater or equal than -1. */
return (CURLMcode) ~CURLM_OK;
res_select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
if(res)
return res;
res_test_timedout();
if(res)
return res;
} }
/* We only reach this point if (mp_timedout) */ return 0; /* success */
if (mp_timedout) fprintf(stderr, "mp_timedout\n");
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
return (CURLMcode) ~CURLM_OK;
} }
int test(char *URL) int test(char *URL)
{ {
CURLM *multi; CURLM *multi = NULL;
CURL *easy; CURL *easy = NULL;
int res = 0; int res = 0;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD; global_init(CURL_GLOBAL_ALL);
multi_init(multi);
easy_init(easy);
multi_setopt(multi, CURLMOPT_PIPELINING, 1L);
easy_setopt(easy, CURLOPT_WRITEFUNCTION, fwrite);
easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
easy_setopt(easy, CURLOPT_URL, URL);
res_multi_add_handle(multi, easy);
if(res) {
printf("curl_multi_add_handle() 1 failed\n");
goto test_cleanup;
} }
if ((multi = curl_multi_init()) == NULL) { res = perform(multi);
fprintf(stderr, "curl_multi_init() failed\n"); if(res) {
curl_global_cleanup(); printf("retrieve 1 failed\n");
return TEST_ERR_MAJOR_BAD; goto test_cleanup;
} }
if ((easy = curl_easy_init()) == NULL) { curl_multi_remove_handle(multi, easy);
fprintf(stderr, "curl_easy_init() failed\n");
curl_multi_cleanup(multi);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
curl_multi_setopt(multi, CURLMOPT_PIPELINING, 1L);
test_setopt(easy, CURLOPT_WRITEFUNCTION, fwrite);
test_setopt(easy, CURLOPT_FAILONERROR, 1L);
test_setopt(easy, CURLOPT_URL, URL);
if (curl_multi_add_handle(multi, easy) != CURLM_OK) {
printf("curl_multi_add_handle() failed\n");
res = TEST_ERR_MAJOR_BAD;
} else {
if (perform(multi) != CURLM_OK)
printf("retrieve 1 failed\n");
curl_multi_remove_handle(multi, easy);
}
curl_easy_reset(easy); curl_easy_reset(easy);
test_setopt(easy, CURLOPT_FAILONERROR, 1L); easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
test_setopt(easy, CURLOPT_URL, libtest_arg2); easy_setopt(easy, CURLOPT_URL, libtest_arg2);
if (curl_multi_add_handle(multi, easy) != CURLM_OK) { res_multi_add_handle(multi, easy);
if(res) {
printf("curl_multi_add_handle() 2 failed\n"); printf("curl_multi_add_handle() 2 failed\n");
res = TEST_ERR_MAJOR_BAD; goto test_cleanup;
} else {
if (perform(multi) != CURLM_OK)
printf("retrieve 2 failed\n");
curl_multi_remove_handle(multi, easy);
} }
res = perform(multi);
if(res) {
printf("retrieve 2 failed\n");
goto test_cleanup;
}
curl_multi_remove_handle(multi, easy);
test_cleanup: test_cleanup:
/* undocumented cleanup sequence - type UB */
curl_easy_cleanup(easy); curl_easy_cleanup(easy);
curl_multi_cleanup(multi); curl_multi_cleanup(multi);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -30,105 +30,111 @@
#include "test.h" #include "test.h"
#include "testutil.h"
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define TEST_HANG_TIMEOUT 60 * 1000
#define PROXY libtest_arg2 #define PROXY libtest_arg2
#define PROXYUSERPWD libtest_arg3 #define PROXYUSERPWD libtest_arg3
#define HOST test_argv[4] #define HOST test_argv[4]
CURL *eh = NULL; #define NUM_HANDLES 2
static int init(CURLM *cm, const char* url, const char* userpwd, CURL *eh[NUM_HANDLES];
static int init(int num, CURLM *cm, const char* url, const char* userpwd,
struct curl_slist *headers) struct curl_slist *headers)
{ {
int res; int res = 0;
if ((eh = curl_easy_init()) == NULL) { res_easy_init(eh[num]);
fprintf(stderr, "curl_easy_init() failed\n");
goto init_failed;
}
res = curl_easy_setopt(eh, CURLOPT_URL, url);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_PROXY, PROXY); res_easy_setopt(eh[num], CURLOPT_URL, url);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_PROXYUSERPWD, userpwd); res_easy_setopt(eh[num], CURLOPT_PROXY, PROXY);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY); res_easy_setopt(eh[num], CURLOPT_PROXYUSERPWD, userpwd);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_VERBOSE, 1L); res_easy_setopt(eh[num], CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_HEADER, 1L); res_easy_setopt(eh[num], CURLOPT_VERBOSE, 1L);
if(res) if(res)
goto init_failed; goto init_failed;
res = curl_easy_setopt(eh, CURLOPT_HTTPHEADER, headers); /* custom Host: */ res_easy_setopt(eh[num], CURLOPT_HEADER, 1L);
if(res) if(res)
goto init_failed; goto init_failed;
if ((res = (int)curl_multi_add_handle(cm, eh)) != CURLM_OK) { res_easy_setopt(eh[num], CURLOPT_HTTPHEADER, headers); /* custom Host: */
fprintf(stderr, "curl_multi_add_handle() failed, with code %d\n", res); if(res)
goto init_failed;
res_multi_add_handle(cm, eh[num]);
if(res)
goto init_failed; goto init_failed;
}
return 0; /* success */ return 0; /* success */
init_failed: init_failed:
if(eh) {
curl_easy_cleanup(eh);
eh = NULL;
}
return 1; /* failure */ curl_easy_cleanup(eh[num]);
eh[num] = NULL;
return res; /* failure */
} }
static int loop(CURLM *cm, const char* url, const char* userpwd, static int loop(int num, CURLM *cm, const char* url, const char* userpwd,
struct curl_slist *headers) struct curl_slist *headers)
{ {
CURLMsg *msg; CURLMsg *msg;
long L; long L;
int M, Q, U = -1; int Q, U = -1;
fd_set R, W, E; fd_set R, W, E;
struct timeval T; struct timeval T;
CURLMcode rc; int res = 0;
if(init(cm, url, userpwd, headers)) res = init(num, cm, url, userpwd, headers);
return 1; /* failure */ if(res)
return res;
while (U) { while (U) {
rc = curl_multi_perform(cm, &U); int M = -99;
if(rc == CURLM_OUT_OF_MEMORY)
return 1; /* failure */ res_multi_perform(cm, &U);
if(res)
return res;
res_test_timedout();
if(res)
return res;
if (U) { if (U) {
FD_ZERO(&R); FD_ZERO(&R);
FD_ZERO(&W); FD_ZERO(&W);
FD_ZERO(&E); FD_ZERO(&E);
if (curl_multi_fdset(cm, &R, &W, &E, &M)) { res_multi_fdset(cm, &R, &W, &E, &M);
fprintf(stderr, "E: curl_multi_fdset\n"); if(res)
return 1; /* failure */ return res;
}
/* In a real-world program you OF COURSE check the return that maxfd is /* At this point, M is guaranteed to be greater or equal than -1. */
bigger than -1 so that the call to select() below makes sense! */
if (curl_multi_timeout(cm, &L)) { res_multi_timeout(cm, &L);
fprintf(stderr, "E: curl_multi_timeout\n"); if(res)
return 1; /* failure */ return res;
}
if(L != -1) { if(L != -1) {
T.tv_sec = L/1000; T.tv_sec = L/1000;
@ -139,25 +145,33 @@ static int loop(CURLM *cm, const char* url, const char* userpwd,
T.tv_usec = 0; T.tv_usec = 0;
} }
if (0 > select(M+1, &R, &W, &E, &T)) { res_select_test(M+1, &R, &W, &E, &T);
fprintf(stderr, "E: select\n"); if(res)
return 1; /* failure */ return res;
}
} }
while ((msg = curl_multi_info_read(cm, &Q))) { while((msg = curl_multi_info_read(cm, &Q)) != NULL) {
if (msg->msg == CURLMSG_DONE) { if(msg->msg == CURLMSG_DONE) {
int i;
CURL *e = msg->easy_handle; CURL *e = msg->easy_handle;
fprintf(stderr, "R: %d - %s\n", (int)msg->data.result, fprintf(stderr, "R: %d - %s\n", (int)msg->data.result,
curl_easy_strerror(msg->data.result)); curl_easy_strerror(msg->data.result));
curl_multi_remove_handle(cm, e); curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e); curl_easy_cleanup(e);
eh = NULL; for(i=0; i < NUM_HANDLES; i++) {
if(eh[i] == e) {
eh[i] = NULL;
break;
}
}
} }
else { else
fprintf(stderr, "E: CURLMsg (%d)\n", (int)msg->msg); fprintf(stderr, "E: CURLMsg (%d)\n", (int)msg->msg);
}
} }
res_test_timedout();
if(res)
return res;
} }
return 0; /* success */ return 0; /* success */
@ -168,7 +182,13 @@ int test(char *URL)
CURLM *cm = NULL; CURLM *cm = NULL;
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
char buffer[246]; /* naively fixed-size */ char buffer[246]; /* naively fixed-size */
int res; int res = 0;
int i;
for(i=0; i < NUM_HANDLES; i++)
eh[i] = NULL;
start_test_timing();
if(test_argc < 4) if(test_argc < 4)
return 99; return 99;
@ -182,37 +202,37 @@ int test(char *URL)
return TEST_ERR_MAJOR_BAD; return TEST_ERR_MAJOR_BAD;
} }
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { res_global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_global_init() failed\n"); if(res) {
curl_slist_free_all(headers); curl_slist_free_all(headers);
return TEST_ERR_MAJOR_BAD; return res;
} }
if ((cm = curl_multi_init()) == NULL) { res_multi_init(cm);
fprintf(stderr, "curl_multi_init() failed\n"); if(res) {
curl_slist_free_all(headers);
curl_global_cleanup(); curl_global_cleanup();
return TEST_ERR_MAJOR_BAD; curl_slist_free_all(headers);
return res;
} }
res = loop(cm, URL, PROXYUSERPWD, headers); res = loop(0, cm, URL, PROXYUSERPWD, headers);
if(res) if(res)
goto test_cleanup; goto test_cleanup;
fprintf(stderr, "lib540: now we do the request again\n"); fprintf(stderr, "lib540: now we do the request again\n");
res = loop(cm, URL, PROXYUSERPWD, headers);
res = loop(1, cm, URL, PROXYUSERPWD, headers);
test_cleanup: test_cleanup:
if(cm && eh) /* proper cleanup sequence - type PB */
curl_multi_remove_handle(cm, eh);
if(eh) for(i=0; i < NUM_HANDLES; i++) {
curl_easy_cleanup(eh); curl_multi_remove_handle(cm, eh[i]);
curl_easy_cleanup(eh[i]);
if(cm) }
curl_multi_cleanup(cm);
curl_multi_cleanup(cm);
curl_global_cleanup(); curl_global_cleanup();
curl_slist_free_all(headers); curl_slist_free_all(headers);

View File

@ -33,7 +33,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define UPLOADTHIS "this is the blurb we want to upload\n" #define UPLOADTHIS "this is the blurb we want to upload\n"
@ -75,114 +75,82 @@ static curlioerr ioctlcallback(CURL *handle,
int test(char *URL) int test(char *URL)
{ {
int res; int res = 0;
CURL *curl; CURL *curl = NULL;
int counter=0; int counter=0;
CURLM *m = NULL; CURLM *m = NULL;
int running=1; int running=1;
struct timeval mp_start;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((curl = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_URL, URL); easy_init(curl);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_HEADER, 1L); easy_setopt(curl, CURLOPT_URL, URL);
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
easy_setopt(curl, CURLOPT_HEADER, 1L);
/* read the POST data from a callback */ /* read the POST data from a callback */
test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback); easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
test_setopt(curl, CURLOPT_IOCTLDATA, &counter); easy_setopt(curl, CURLOPT_IOCTLDATA, &counter);
test_setopt(curl, CURLOPT_READFUNCTION, readcallback); easy_setopt(curl, CURLOPT_READFUNCTION, readcallback);
test_setopt(curl, CURLOPT_READDATA, &counter); easy_setopt(curl, CURLOPT_READDATA, &counter);
/* We CANNOT do the POST fine without setting the size (or choose chunked)! */ /* We CANNOT do the POST fine without setting the size (or choose chunked)! */
test_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(UPLOADTHIS)); easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(UPLOADTHIS));
test_setopt(curl, CURLOPT_POST, 1L); easy_setopt(curl, CURLOPT_POST, 1L);
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS
/* Convert the POST data to ASCII. */ /* Convert the POST data to ASCII. */
test_setopt(curl, CURLOPT_TRANSFERTEXT, 1L); easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
#endif #endif
test_setopt(curl, CURLOPT_PROXY, libtest_arg2); easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
test_setopt(curl, CURLOPT_PROXYUSERPWD, libtest_arg3); easy_setopt(curl, CURLOPT_PROXYUSERPWD, libtest_arg3);
test_setopt(curl, CURLOPT_PROXYAUTH, easy_setopt(curl, CURLOPT_PROXYAUTH,
(long) (CURLAUTH_NTLM | CURLAUTH_DIGEST | CURLAUTH_BASIC) ); (long) (CURLAUTH_NTLM | CURLAUTH_DIGEST | CURLAUTH_BASIC) );
if ((m = curl_multi_init()) == NULL) { multi_init(m);
fprintf(stderr, "curl_multi_init() failed\n");
curl_easy_cleanup(curl);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) { multi_add_handle(m, curl);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(curl);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
while (running) { while (running) {
static struct timeval timeout = /* 100 ms */ { 0, 100000L }; struct timeval timeout;
fd_set fdread, fdwrite, fdexcep; fd_set fdread, fdwrite, fdexcep;
int maxfd = -1; int maxfd = -99;
timeout.tv_sec = 0;
timeout.tv_usec = 100000L; /* 100 ms */
multi_perform(m, &running);
abort_on_test_timeout();
res = (int)curl_multi_perform(m, &running);
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE;
break;
}
#ifdef TPF #ifdef TPF
sleep(1); /* avoid ctl-10 dump */ sleep(1); /* avoid ctl-10 dump */
#endif #endif
if (running <= 0) {
fprintf(stderr, "nothing left running.\n"); if(!running)
break; break; /* done */
}
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);
curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
res = ~CURLM_OK;
break;
}
}
if (mp_timedout) { select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
"that it would have run forever.\n"); abort_on_test_timeout();
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, curl);
curl_multi_cleanup(m); curl_multi_remove_handle(m, curl);
} curl_multi_cleanup(m);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -21,9 +21,12 @@
***************************************************************************/ ***************************************************************************/
#include "test.h" #include "test.h"
#include "testutil.h"
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define TEST_HANG_TIMEOUT 60 * 1000
/* /*
* Simply download a HTTPS file! * Simply download a HTTPS file!
* *
@ -36,43 +39,44 @@
*/ */
int test(char *URL) int test(char *URL)
{ {
CURL *http_handle; CURL *http_handle = NULL;
CURLM *multi_handle = NULL; CURLM *multi_handle = NULL;
int res; int res = 0;
int still_running; /* keep number of running handles */ int still_running; /* keep number of running handles */
http_handle = curl_easy_init(); start_test_timing();
if (!http_handle)
return TEST_ERR_MAJOR_BAD; /*
** curl_global_init called indirectly from curl_easy_init.
*/
easy_init(http_handle);
/* set options */ /* set options */
test_setopt(http_handle, CURLOPT_URL, URL); easy_setopt(http_handle, CURLOPT_URL, URL);
test_setopt(http_handle, CURLOPT_HEADER, 1L); easy_setopt(http_handle, CURLOPT_HEADER, 1L);
test_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L); easy_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L);
test_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L); easy_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);
/* init a multi stack */ /* init a multi stack */
multi_handle = curl_multi_init(); multi_init(multi_handle);
if (!multi_handle) {
curl_easy_cleanup(http_handle);
return TEST_ERR_MAJOR_BAD;
}
/* add the individual transfers */ /* add the individual transfers */
curl_multi_add_handle(multi_handle, http_handle); multi_add_handle(multi_handle, http_handle);
/* we start some action by calling perform right away */ /* we start some action by calling perform right away */
(void) curl_multi_perform(multi_handle, &still_running); multi_perform(multi_handle, &still_running);
abort_on_test_timeout();
while(still_running) { while(still_running) {
struct timeval timeout; struct timeval timeout;
int rc; /* select() return code */
fd_set fdread; fd_set fdread;
fd_set fdwrite; fd_set fdwrite;
fd_set fdexcep; fd_set fdexcep;
int maxfd; int maxfd = -99;
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
@ -83,31 +87,25 @@ int test(char *URL)
timeout.tv_usec = 0; timeout.tv_usec = 0;
/* get file descriptors from the transfers */ /* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the /* At this point, maxfd is guaranteed to be greater or equal than -1. */
function calls, *and* you make sure that maxfd is bigger than -1 so
that the call to select() below makes sense! */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) { abort_on_test_timeout();
case -1:
/* select error */ /* timeout or readable/writable sockets */
break; multi_perform(multi_handle, &still_running);
case 0:
default: abort_on_test_timeout();
/* timeout or readable/writable sockets */
(void) curl_multi_perform(multi_handle, &still_running);
break;
}
} }
test_cleanup: test_cleanup:
if(multi_handle) /* undocumented cleanup sequence - type UA */
curl_multi_cleanup(multi_handle);
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle); curl_easy_cleanup(http_handle);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -27,121 +27,66 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
int test(char *URL) int test(char *URL)
{ {
int res = 0; int res = 0;
CURL *curl; CURL *curl = NULL;
int running; int running;
char done=FALSE;
CURLM *m = NULL; CURLM *m = NULL;
struct timeval ml_start;
struct timeval mp_start;
char ml_timedout = FALSE;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((curl = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_URL, URL); easy_init(curl);
test_setopt(curl, CURLOPT_VERBOSE, 1);
test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
if ((m = curl_multi_init()) == NULL) { easy_setopt(curl, CURLOPT_URL, URL);
fprintf(stderr, "curl_multi_init() failed\n"); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_cleanup(curl); easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
curl_global_cleanup(); easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) { multi_init(m);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(curl);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; multi_add_handle(m, curl);
ml_start = tutil_tvnow();
fprintf(stderr, "Start at URL 0\n"); fprintf(stderr, "Start at URL 0\n");
while (!done) { for(;;) {
fd_set rd, wr, exc;
int max_fd;
struct timeval interval; struct timeval interval;
fd_set rd, wr, exc;
int maxfd = -99;
interval.tv_sec = 1; interval.tv_sec = 1;
interval.tv_usec = 0; interval.tv_usec = 0;
if (tutil_tvdiff(tutil_tvnow(), ml_start) > multi_perform(m, &running);
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
mp_timedout = FALSE;
mp_start = tutil_tvnow();
res = (int)curl_multi_perform(m, &running); abort_on_test_timeout();
if (tutil_tvdiff(tutil_tvnow(), mp_start) >
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE;
break;
}
if (running <= 0) {
done = TRUE; /* bail out */
break;
}
if (res != CURLM_OK) { if(!running)
fprintf(stderr, "not okay???\n"); break; /* done */
break;
}
FD_ZERO(&rd); FD_ZERO(&rd);
FD_ZERO(&wr); FD_ZERO(&wr);
FD_ZERO(&exc); FD_ZERO(&exc);
max_fd = 0;
if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) { multi_fdset(m, &rd, &wr, &exc, &maxfd);
fprintf(stderr, "unexpected failured of fdset.\n");
res = 189;
break;
}
if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
fprintf(stderr, "bad select??\n");
res = 195;
break;
}
}
if (ml_timedout || mp_timedout) { select_test(maxfd+1, &rd, &wr, &exc, &interval);
if (ml_timedout) fprintf(stderr, "ml_timedout\n");
if (mp_timedout) fprintf(stderr, "mp_timedout\n"); abort_on_test_timeout();
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
} }
test_cleanup: test_cleanup:
/* undocumented cleanup sequence - type UB */
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if(m) curl_multi_cleanup(m);
curl_multi_cleanup(m);
curl_global_cleanup(); curl_global_cleanup();
return res; return res;

View File

@ -25,8 +25,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 90 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
/* /*
* Get a single URL without select(). * Get a single URL without select().
@ -34,84 +33,51 @@
int test(char *URL) int test(char *URL)
{ {
CURL *c; CURL *c = NULL;
CURLM *m = NULL; CURLM *m = NULL;
int res = 0; int res = 0;
int running=1; int running = 1;
double connect_time = 0.0; double connect_time = 0.0;
struct timeval mp_start;
char mp_timedout = FALSE;
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if ((c = curl_easy_init()) == NULL) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(c, CURLOPT_HEADER, 1L); easy_init(c);
test_setopt(c, CURLOPT_URL, URL);
if ((m = curl_multi_init()) == NULL) { easy_setopt(c, CURLOPT_HEADER, 1L);
fprintf(stderr, "curl_multi_init() failed\n"); easy_setopt(c, CURLOPT_URL, URL);
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) { multi_init(m);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
mp_timedout = FALSE; multi_add_handle(m, c);
mp_start = tutil_tvnow();
while (running) { while (running) {
static struct timeval timeout = /* 100 ms */ { 0, 100000L }; struct timeval timeout;
fd_set fdread, fdwrite, fdexcep; fd_set fdread, fdwrite, fdexcep;
int maxfd = -1; int maxfd = -99;
res = (int)curl_multi_perform(m, &running); timeout.tv_sec = 0;
if (tutil_tvdiff(tutil_tvnow(), mp_start) > timeout.tv_usec = 100000L; /* 100 ms */
MULTI_PERFORM_HANG_TIMEOUT) {
mp_timedout = TRUE; multi_perform(m, &running);
break;
} abort_on_test_timeout();
if (running <= 0) {
fprintf(stderr, "nothing left running.\n"); if(!running)
break; break; /* done */
}
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);
curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) { /* At this point, maxfd is guaranteed to be greater or equal than -1. */
res = ~CURLM_OK;
break;
}
}
if (mp_timedout) { select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
"that it would have run forever.\n"); abort_on_test_timeout();
res = TEST_ERR_RUNS_FOREVER;
} }
curl_easy_getinfo(c, CURLINFO_CONNECT_TIME, &connect_time); curl_easy_getinfo(c, CURLINFO_CONNECT_TIME, &connect_time);
@ -122,10 +88,10 @@ int test(char *URL)
test_cleanup: test_cleanup:
if(m) { /* proper cleanup sequence - type PA */
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m); curl_multi_remove_handle(m, c);
} curl_multi_cleanup(m);
curl_easy_cleanup(c); curl_easy_cleanup(c);
curl_global_cleanup(); curl_global_cleanup();

View File

@ -27,6 +27,8 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define TEST_HANG_TIMEOUT 60 * 1000
/* 3x download! /* 3x download!
* 1. normal * 1. normal
* 2. dup handle * 2. dup handle
@ -35,26 +37,21 @@
int test(char *URL) int test(char *URL)
{ {
CURLMcode m; CURL *handle = NULL;
CURL *handle = NULL, *duphandle; CURL *duphandle = NULL;
CURLM *mhandle = NULL; CURLM *mhandle = NULL;
int res = 0; int res = 0;
int still_running = 0; int still_running = 0;
if(curl_global_init(CURL_GLOBAL_ALL)) { start_test_timing();
fprintf(stderr, "curl_global_init() failed\n");
goto test_cleanup;
}
handle = curl_easy_init(); global_init(CURL_GLOBAL_ALL);
if(!handle) {
res = CURLE_OUT_OF_MEMORY;
goto test_cleanup;
}
test_setopt(handle, CURLOPT_URL, URL); easy_init(handle);
test_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
test_setopt(handle, CURLOPT_VERBOSE, 1L); easy_setopt(handle, CURLOPT_URL, URL);
easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
easy_setopt(handle, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(handle); res = curl_easy_perform(handle);
if(res) if(res)
@ -70,49 +67,48 @@ int test(char *URL)
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
handle = duphandle; handle = duphandle;
mhandle = curl_multi_init(); multi_init(mhandle);
if(!mhandle) {
fprintf(stderr, "curl_multi_init() failed\n");
goto test_cleanup;
}
curl_multi_add_handle(mhandle, handle); multi_add_handle(mhandle, handle);
curl_multi_perform(mhandle, &still_running); multi_perform(mhandle, &still_running);
abort_on_test_timeout();
while(still_running) { while(still_running) {
static struct timeval timeout = /* 100 ms */ { 0, 100000L }; struct timeval timeout;
int rc;
fd_set fdread; fd_set fdread;
fd_set fdwrite; fd_set fdwrite;
fd_set fdexcep; fd_set fdexcep;
int max_fdset = -1; int maxfd = -99;
timeout.tv_sec = 0;
timeout.tv_usec = 100000L; /* 100 ms */
FD_ZERO(&fdread); FD_ZERO(&fdread);
FD_ZERO(&fdwrite); FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);
m = curl_multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &max_fdset); multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &maxfd);
if(m != CURLM_OK) {
fprintf(stderr, "curl_multi_fdset() error\n"); /* At this point, maxfd is guaranteed to be greater or equal than -1. */
goto test_cleanup;
} select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
/* We call select(max_fdset + 1, ...), specially in case of (maxfd == -1),
* we call select(0, ...), which is basically equal to sleep. */ abort_on_test_timeout();
rc = select(max_fdset + 1, &fdread, &fdwrite, &fdexcep, &timeout);
if(rc == -1) { multi_perform(mhandle, &still_running);
fprintf(stderr, "select() error\n");
goto test_cleanup; abort_on_test_timeout();
}
else {
curl_multi_perform(mhandle, &still_running);
}
} }
test_cleanup: test_cleanup:
if(mhandle)
curl_multi_cleanup(mhandle); /* undocumented cleanup sequence - type UA */
if(handle)
curl_easy_cleanup(handle); curl_multi_cleanup(mhandle);
curl_easy_cleanup(handle);
curl_global_cleanup(); curl_global_cleanup();
return res; return res;
} }

View File

@ -27,7 +27,7 @@
#include "warnless.h" #include "warnless.h"
#include "memdebug.h" #include "memdebug.h"
#define MAIN_LOOP_HANG_TIMEOUT 4 * 1000 #define TEST_HANG_TIMEOUT 60 * 1000
struct Sockets struct Sockets
{ {
@ -226,30 +226,30 @@ static void checkFdSet(CURLM *curl, struct Sockets *sockets, fd_set *fdset,
int test(char *URL) int test(char *URL)
{ {
int res = 0; int res = 0;
CURL *curl; CURL *curl = NULL;
FILE *hd_src ; FILE *hd_src = NULL;
int hd ; int hd ;
int error; int error;
struct_stat file_info; struct_stat file_info;
CURLM *m = NULL; CURLM *m = NULL;
struct timeval ml_start;
char ml_timedout = FALSE;
struct ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}}; struct ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}};
struct timeval timeout = {-1, 0}; struct timeval timeout = {-1, 0};
int success = 0; int success = 0;
start_test_timing();
if (!libtest_arg3) { if (!libtest_arg3) {
fprintf(stderr, "Usage: lib582 [url] [filename] [username]\n"); fprintf(stderr, "Usage: lib582 [url] [filename] [username]\n");
return -1; return TEST_ERR_USAGE;
} }
hd_src = fopen(libtest_arg2, "rb"); hd_src = fopen(libtest_arg2, "rb");
if(NULL == hd_src) { if(NULL == hd_src) {
error = ERRNO; error = ERRNO;
fprintf(stderr, "fopen() failed with error: %d %s\n", fprintf(stderr, "fopen() failed with error: %d (%s)\n",
error, strerror(error)); error, strerror(error));
fprintf(stderr, "Error opening file: %s\n", libtest_arg2); fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
return TEST_ERR_MAJOR_BAD; return TEST_ERR_FOPEN;
} }
/* get the file size of the local file */ /* get the file size of the local file */
@ -257,71 +257,49 @@ int test(char *URL)
if(hd == -1) { if(hd == -1) {
/* can't open file, bail out */ /* can't open file, bail out */
error = ERRNO; error = ERRNO;
fprintf(stderr, "fstat() failed with error: %d %s\n", fprintf(stderr, "fstat() failed with error: %d (%s)\n",
error, strerror(error)); error, strerror(error));
fprintf(stderr, "ERROR: cannot open file %s\n", libtest_arg2); fprintf(stderr, "ERROR: cannot open file (%s)\n", libtest_arg2);
fclose(hd_src); fclose(hd_src);
return -1; return TEST_ERR_FSTAT;
} }
fprintf(stderr, "Set to upload %d bytes\n", (int)file_info.st_size); fprintf(stderr, "Set to upload %d bytes\n", (int)file_info.st_size);
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { res_global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_global_init() failed\n"); if(res) {
fclose(hd_src); fclose(hd_src);
return TEST_ERR_MAJOR_BAD; return res;
} }
if ((curl = curl_easy_init()) == NULL) { easy_init(curl);
fprintf(stderr, "curl_easy_init() failed\n");
fclose(hd_src);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
/* enable uploading */ /* enable uploading */
test_setopt(curl, CURLOPT_UPLOAD, 1L); easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */ /* specify target */
test_setopt(curl,CURLOPT_URL, URL); easy_setopt(curl,CURLOPT_URL, URL);
/* go verbose */ /* go verbose */
test_setopt(curl, CURLOPT_VERBOSE, 1L); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* now specify which file to upload */ /* now specify which file to upload */
test_setopt(curl, CURLOPT_READDATA, hd_src); easy_setopt(curl, CURLOPT_READDATA, hd_src);
test_setopt(curl, CURLOPT_USERPWD, libtest_arg3); easy_setopt(curl, CURLOPT_USERPWD, libtest_arg3);
test_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub"); easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
test_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key"); easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
test_setopt(curl, CURLOPT_INFILESIZE_LARGE, easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
(curl_off_t)file_info.st_size);
if ((m = curl_multi_init()) == NULL) { multi_init(m);
fprintf(stderr, "curl_multi_init() failed\n");
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(hd_src);
return TEST_ERR_MAJOR_BAD;
}
test_multi_setopt(m, CURLMOPT_SOCKETFUNCTION, curlSocketCallback);
test_multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets);
test_multi_setopt(m, CURLMOPT_TIMERFUNCTION, curlTimerCallback); multi_setopt(m, CURLMOPT_SOCKETFUNCTION, curlSocketCallback);
test_multi_setopt(m, CURLMOPT_TIMERDATA, &timeout); multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets);
if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) { multi_setopt(m, CURLMOPT_TIMERFUNCTION, curlTimerCallback);
fprintf(stderr, "curl_multi_add_handle() failed, " multi_setopt(m, CURLMOPT_TIMERDATA, &timeout);
"with code %d\n", res);
curl_multi_cleanup(m);
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(hd_src);
return TEST_ERR_MAJOR_BAD;
}
ml_timedout = FALSE; multi_add_handle(m, curl);
ml_start = tutil_tvnow();
while (!checkForCompletion(m, &success)) while (!checkForCompletion(m, &success))
{ {
@ -329,12 +307,6 @@ int test(char *URL)
curl_socket_t maxFd = 0; curl_socket_t maxFd = 0;
struct timeval tv = {10, 0}; struct timeval tv = {10, 0};
if (tutil_tvdiff(tutil_tvnow(), ml_start) >
MAIN_LOOP_HANG_TIMEOUT) {
ml_timedout = TRUE;
break;
}
FD_ZERO(&readSet); FD_ZERO(&readSet);
FD_ZERO(&writeSet); FD_ZERO(&writeSet);
updateFdSet(&sockets.read, &readSet, &maxFd); updateFdSet(&sockets.read, &readSet, &maxFd);
@ -363,6 +335,8 @@ int test(char *URL)
/* Curl's timer has elapsed. */ /* Curl's timer has elapsed. */
notifyCurl(m, CURL_SOCKET_TIMEOUT, 0, "timeout"); notifyCurl(m, CURL_SOCKET_TIMEOUT, 0, "timeout");
} }
abort_on_test_timeout();
} }
if (!success) if (!success)
@ -370,28 +344,24 @@ int test(char *URL)
fprintf(stderr, "Error uploading file.\n"); fprintf(stderr, "Error uploading file.\n");
res = TEST_ERR_MAJOR_BAD; res = TEST_ERR_MAJOR_BAD;
} }
else if (ml_timedout) {
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
res = TEST_ERR_RUNS_FOREVER;
}
test_cleanup: test_cleanup:
if(m) /* proper cleanup sequence - type PB */
curl_multi_remove_handle(m, curl);
curl_easy_cleanup(curl);
if(m) {
fprintf(stderr, "Now multi-cleanup!\n");
curl_multi_cleanup(m);
}
fclose(hd_src); /* close the local file */ curl_multi_remove_handle(m, curl);
if (sockets.read.sockets) curl_easy_cleanup(curl);
curl_multi_cleanup(m);
curl_global_cleanup();
/* close the local file */
fclose(hd_src);
/* free local memory */
if(sockets.read.sockets)
free(sockets.read.sockets); free(sockets.read.sockets);
if (sockets.write.sockets) if(sockets.write.sockets)
free(sockets.write.sockets); free(sockets.write.sockets);
curl_global_cleanup();
return res; return res;
} }

View File

@ -33,58 +33,36 @@
int test(char *URL) int test(char *URL)
{ {
int stillRunning; int stillRunning;
CURLM* multiHandle; CURLM* multiHandle = NULL;
CURL* curl; CURL* curl = NULL;
int res1 = 0; int res = 0;
int res;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { global_init(CURL_GLOBAL_ALL);
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if((multiHandle = curl_multi_init()) == NULL) { multi_init(multiHandle);
fprintf(stderr, "curl_multi_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
if((curl = curl_easy_init()) == NULL) { easy_init(curl);
fprintf(stderr, "curl_easy_init() failed\n");
curl_multi_cleanup(multiHandle);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_USERPWD, libtest_arg2); easy_setopt(curl, CURLOPT_USERPWD, libtest_arg2);
test_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub"); easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
test_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key"); easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
test_setopt(curl, CURLOPT_UPLOAD, 1); easy_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1); easy_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_URL, URL); easy_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_INFILESIZE, (long)5); easy_setopt(curl, CURLOPT_INFILESIZE, (long)5);
if((res = (int)curl_multi_add_handle(multiHandle, curl)) != CURLM_OK) { multi_add_handle(multiHandle, curl);
fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res);
curl_easy_cleanup(curl);
curl_multi_cleanup(multiHandle);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
/* this tests if removing an easy handle immediately after multi /* this tests if removing an easy handle immediately after multi
perform has been called succeeds or not. */ perform has been called succeeds or not. */
fprintf(stderr, "curl_multi_perform()...\n"); fprintf(stderr, "curl_multi_perform()...\n");
res1 = (int) curl_multi_perform(multiHandle, &stillRunning);
if(res1) multi_perform(multiHandle, &stillRunning);
fprintf(stderr, "curl_multi_perform() failed, "
"with code %d\n", res1); fprintf(stderr, "curl_multi_perform() succeeded\n");
else
fprintf(stderr, "curl_multi_perform() succeeded\n");
fprintf(stderr, "curl_multi_remove_handle()...\n"); fprintf(stderr, "curl_multi_remove_handle()...\n");
res = (int) curl_multi_remove_handle(multiHandle, curl); res = (int) curl_multi_remove_handle(multiHandle, curl);
@ -96,12 +74,11 @@ int test(char *URL)
test_cleanup: test_cleanup:
/* undocumented cleanup sequence - type UB */
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_multi_cleanup(multiHandle); curl_multi_cleanup(multiHandle);
curl_global_cleanup(); curl_global_cleanup();
if(res) return res;
return res;
else
return res1;
} }

View File

@ -50,9 +50,6 @@
# include "select.h" # include "select.h"
#endif #endif
#define TEST_ERR_MAJOR_BAD 100
#define TEST_ERR_RUNS_FOREVER 99
#define test_setopt(A,B,C) \ #define test_setopt(A,B,C) \
if((res = curl_easy_setopt((A),(B),(C))) != CURLE_OK) goto test_cleanup if((res = curl_easy_setopt((A),(B),(C))) != CURLE_OK) goto test_cleanup
@ -66,8 +63,10 @@ extern char *libtest_arg3; /* set by first.c to the argv[3] or NULL */
extern int test_argc; extern int test_argc;
extern char **test_argv; extern char **test_argv;
extern int select_test(int num_fds, fd_set *rd, fd_set *wr, fd_set *exc, extern struct timeval tv_test_start; /* for test timing */
struct timeval *tv);
extern int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
struct timeval *tv);
extern int test(char *URL); /* the actual test function provided by each extern int test(char *URL); /* the actual test function provided by each
individual libXXX.c file */ individual libXXX.c file */
@ -75,3 +74,331 @@ extern int test(char *URL); /* the actual test function provided by each
#ifdef UNITTESTS #ifdef UNITTESTS
extern int unitfail; extern int unitfail;
#endif #endif
/*
** TEST_ERR_* values must be greater than CURL_LAST CURLcode in order
** to avoid confusion with any CURLcode or CURLMcode. These TEST_ERR_*
** codes are returned to signal test specific situations and should
** not get mixed with CURLcode or CURLMcode values.
**
** For portability reasons TEST_ERR_* values should be less than 127.
*/
#define TEST_ERR_MAJOR_BAD 126
#define TEST_ERR_RUNS_FOREVER 125
#define TEST_ERR_EASY_INIT 124
#define TEST_ERR_MULTI_INIT 123
#define TEST_ERR_NUM_HANDLES 122
#define TEST_ERR_SELECT 121
#define TEST_ERR_SUCCESS 120
#define TEST_ERR_FAILURE 119
#define TEST_ERR_USAGE 118
#define TEST_ERR_FOPEN 117
#define TEST_ERR_FSTAT 116
/*
** Macros for test source code readability/maintainability.
**
** All of the following macros require that an int data type 'res' variable
** exists in scope where macro is used, and that it has been initialized to
** zero before the macro is used.
**
** exe_* and chk_* macros are helper macros not intended to be used from
** outside of this header file. Arguments 'Y' and 'Z' of these represent
** source code file and line number, while Arguments 'A', 'B', etc, are
** the arguments used to actually call a libcurl function.
**
** All easy_* and multi_* macros call a libcurl function and evaluate if
** the function has succeeded or failed. When the function succeeds 'res'
** variable is not set nor cleared and program continues normal flow. On
** the other hand if function fails 'res' variable is set and a jump to
** label 'test_cleanup' is performed.
**
** Every easy_* and multi_* macros have a res_easy_* and res_multi_* macro
** counterpart that operates in tha same way with the exception that no
** jump takes place in case of failure. res_easy_* and res_multi_* macros
** should be immediately followed by checking if 'res' variable has been
** set.
**
** 'res' variable when set will hold a CURLcode, CURLMcode, or any of the
** TEST_ERR_* values defined above. It is advisable to return this value
** as test result.
*/
/* ---------------------------------------------------------------- */
#define exe_easy_init(A,Y,Z) do { \
if(((A) = curl_easy_init()) == NULL) { \
fprintf(stderr, "%s:%d curl_easy_init() failed\n", (Y), (Z)); \
res = TEST_ERR_EASY_INIT; \
} \
} WHILE_FALSE
#define res_easy_init(A) \
exe_easy_init((A),(__FILE__),(__LINE__))
#define chk_easy_init(A,Y,Z) do { \
exe_easy_init((A),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define easy_init(A) \
chk_easy_init((A),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_init(A,Y,Z) do { \
if(((A) = curl_multi_init()) == NULL) { \
fprintf(stderr, "%s:%d curl_multi_init() failed\n", (Y), (Z)); \
res = TEST_ERR_MULTI_INIT; \
} \
} WHILE_FALSE
#define res_multi_init(A) \
exe_multi_init((A),(__FILE__),(__LINE__))
#define chk_multi_init(A,Y,Z) do { \
exe_multi_init((A),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_init(A) \
chk_multi_init((A),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_easy_setopt(A,B,C,Y,Z) do { \
CURLcode ec; \
if((ec = curl_easy_setopt((A),(B),(C))) != CURLE_OK) { \
fprintf(stderr, "%s:%d curl_easy_setopt() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_easy_strerror(ec)); \
res = (int)ec; \
} \
} WHILE_FALSE
#define res_easy_setopt(A,B,C) \
exe_easy_setopt((A),(B),(C),(__FILE__),(__LINE__))
#define chk_easy_setopt(A,B,C,Y,Z) do { \
exe_easy_setopt((A),(B),(C),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define easy_setopt(A,B,C) \
chk_easy_setopt((A),(B),(C),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_setopt(A,B,C,Y,Z) do { \
CURLMcode ec; \
if((ec = curl_multi_setopt((A),(B),(C))) != CURLM_OK) { \
fprintf(stderr, "%s:%d curl_multi_setopt() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_multi_strerror(ec)); \
res = (int)ec; \
} \
} WHILE_FALSE
#define res_multi_setopt(A,B,C) \
exe_multi_setopt((A),(B),(C),(__FILE__),(__LINE__))
#define chk_multi_setopt(A,B,C,Y,Z) do { \
exe_multi_setopt((A),(B),(C),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_setopt(A,B,C) \
chk_multi_setopt((A),(B),(C),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_add_handle(A,B,Y,Z) do { \
CURLMcode ec; \
if((ec = curl_multi_add_handle((A),(B))) != CURLM_OK) { \
fprintf(stderr, "%s:%d curl_multi_add_handle() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_multi_strerror(ec)); \
res = (int)ec; \
} \
} WHILE_FALSE
#define res_multi_add_handle(A,B) \
exe_multi_add_handle((A),(B),(__FILE__),(__LINE__))
#define chk_multi_add_handle(A,B,Y,Z) do { \
exe_multi_add_handle((A),(B),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_add_handle(A,B) \
chk_multi_add_handle((A),(B),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_perform(A,B,Y,Z) do { \
CURLMcode ec; \
if((ec = curl_multi_perform((A),(B))) != CURLM_OK) { \
fprintf(stderr, "%s:%d curl_multi_perform() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_multi_strerror(ec)); \
res = (int)ec; \
} \
else if(*((B)) < 0) { \
fprintf(stderr, "%s:%d curl_multi_perform() succeeded, " \
"but returned invalid running_handles value (%d)\n", \
(Y), (Z), (int)*((B))); \
res = TEST_ERR_NUM_HANDLES; \
} \
} WHILE_FALSE
#define res_multi_perform(A,B) \
exe_multi_perform((A),(B),(__FILE__),(__LINE__))
#define chk_multi_perform(A,B,Y,Z) do { \
exe_multi_perform((A),(B),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_perform(A,B) \
chk_multi_perform((A),(B),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_fdset(A,B,C,D,E,Y,Z) do { \
CURLMcode ec; \
if((ec = curl_multi_fdset((A),(B),(C),(D),(E))) != CURLM_OK) { \
fprintf(stderr, "%s:%d curl_multi_fdset() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_multi_strerror(ec)); \
res = (int)ec; \
} \
else if(*((E)) < -1) { \
fprintf(stderr, "%s:%d curl_multi_fdset() succeeded, " \
"but returned invalid max_fd value (%d)\n", \
(Y), (Z), (int)*((E))); \
res = TEST_ERR_NUM_HANDLES; \
} \
} WHILE_FALSE
#define res_multi_fdset(A,B,C,D,E) \
exe_multi_fdset((A),(B),(C),(D),(E),(__FILE__),(__LINE__))
#define chk_multi_fdset(A,B,C,D,E,Y,Z) do { \
exe_multi_fdset((A),(B),(C),(D),(E),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_fdset(A,B,C,D,E) \
chk_multi_fdset((A),(B),(C),(D),(E),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_multi_timeout(A,B,Y,Z) do { \
CURLMcode ec; \
if((ec = curl_multi_timeout((A),(B))) != CURLM_OK) { \
fprintf(stderr, "%s:%d curl_multi_timeout() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_multi_strerror(ec)); \
res = (int)ec; \
} \
} WHILE_FALSE
#define res_multi_timeout(A,B) \
exe_multi_timeout((A),(B),(__FILE__),(__LINE__))
#define chk_multi_timeout(A,B,Y,Z) do { \
exe_multi_timeout((A),(B),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define multi_timeout(A,B) \
chk_multi_timeout((A),(B),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_select_test(A,B,C,D,E,Y,Z) do { \
int ec; \
if(select_wrapper((A),(B),(C),(D),(E)) == -1 ) { \
ec = SOCKERRNO; \
fprintf(stderr, "%s:%d select() failed, with " \
"errno %d (%s)\n", \
(Y), (Z), ec, strerror(ec)); \
res = TEST_ERR_SELECT; \
} \
} WHILE_FALSE
#define res_select_test(A,B,C,D,E) \
exe_select_test((A),(B),(C),(D),(E),(__FILE__),(__LINE__))
#define chk_select_test(A,B,C,D,E,Y,Z) do { \
exe_select_test((A),(B),(C),(D),(E),(Y),(Z)); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define select_test(A,B,C,D,E) \
chk_select_test((A),(B),(C),(D),(E),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define start_test_timing() do { \
tv_test_start = tutil_tvnow(); \
} WHILE_FALSE
#define exe_test_timedout(Y,Z) do { \
if(tutil_tvdiff(tutil_tvnow(), tv_test_start) > TEST_HANG_TIMEOUT) { \
fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \
"that it would have run forever.\n", (Y), (Z)); \
res = TEST_ERR_RUNS_FOREVER; \
} \
} WHILE_FALSE
#define res_test_timedout() \
exe_test_timedout((__FILE__),(__LINE__))
#define chk_test_timedout(Y,Z) do { \
exe_test_timedout(Y,Z); \
if(res) \
goto test_cleanup; \
} WHILE_FALSE
#define abort_on_test_timeout() \
chk_test_timedout((__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */
#define exe_global_init(A,Y,Z) do { \
CURLcode ec; \
if((ec = curl_global_init((A))) != CURLE_OK) { \
fprintf(stderr, "%s:%d curl_global_init() failed, " \
"with code %d (%s)\n", \
(Y), (Z), (int)ec, curl_easy_strerror(ec)); \
res = (int)ec; \
} \
} WHILE_FALSE
#define res_global_init(A) \
exe_global_init((A),(__FILE__),(__LINE__))
#define chk_global_init(A,Y,Z) do { \
exe_global_init((A),(Y),(Z)); \
if(res) \
return res; \
} WHILE_FALSE
/* global_init() is different than other macros. In case of
failure it 'return's instead of going to 'test_cleanup'. */
#define global_init(A) \
chk_global_init((A),(__FILE__),(__LINE__))
/* ---------------------------------------------------------------- */