]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi tests: OOM handling fixes
authorYang Tse <yangsita@gmail.com>
Fri, 21 Oct 2011 14:26:18 +0000 (16:26 +0200)
committerYang Tse <yangsita@gmail.com>
Fri, 21 Oct 2011 14:52:14 +0000 (16:52 +0200)
Additionally, improved error checking and logging.

22 files changed:
tests/data/test504
tests/data/test538
tests/libtest/Makefile.inc
tests/libtest/first.c
tests/libtest/lib502.c
tests/libtest/lib503.c
tests/libtest/lib504.c
tests/libtest/lib507.c
tests/libtest/lib525.c
tests/libtest/lib526.c
tests/libtest/lib530.c
tests/libtest/lib533.c
tests/libtest/lib536.c
tests/libtest/lib540.c
tests/libtest/lib555.c
tests/libtest/lib560.c
tests/libtest/lib564.c
tests/libtest/lib573.c
tests/libtest/lib575.c
tests/libtest/lib582.c
tests/libtest/lib583.c
tests/libtest/test.h

index 573ab51c7624f866ba1e05e264f6a2ea1d4b4ebc..2d3a3dd0d08d5707508536248a67c0dfb850ddb6 100644 (file)
@@ -35,9 +35,10 @@ http://%HOSTIP:%HTTPSPORT/504 %HOSTIP:55555
 </client>
 
 # Verify data after the test has been "shot"
+# TEST_ERR_SUCCESS is errorcode 120
 <verify>
 <errorcode>
-100
+120
 </errorcode>
 </verify>
 </testcase>
index f33b2a654b4ad82736f2b3215598905448720e96..d2fecd353ddcda8fedd77575daaef94b1e420e1c 100644 (file)
@@ -32,11 +32,10 @@ ftp://%HOSTIP:%FTPPORT/538
 </client>
 
 # Verify data after the test has been "shot"
+# TEST_ERR_SUCCESS is errorcode 120
 <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>
-100
+120
 </errorcode>
 <protocol>
 USER anonymous\r
index 30883d2270acaf7c2344f89c35ace462688b9c66..86b3b29aba83bb48e2f7dc88288769716438a170 100644 (file)
@@ -93,7 +93,7 @@ lib537_SOURCES = lib537.c $(SUPPORTFILES) $(WARNLESS)
 
 lib539_SOURCES = lib539.c $(SUPPORTFILES)
 
-lib540_SOURCES = lib540.c $(SUPPORTFILES) $(WARNLESS)
+lib540_SOURCES = lib540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
 
 lib541_SOURCES = lib541.c $(SUPPORTFILES)
 
@@ -125,11 +125,11 @@ lib556_SOURCES = lib556.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)
 
-lib575_SOURCES = lib575.c $(SUPPORTFILES) $(WARNLESS)
+lib575_SOURCES = lib575.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
 
 lib576_SOURCES = lib576.c $(SUPPORTFILES)
 
index d6b486003f52056cdf53cb86029bc917fdffeb75..57e6ddd79871a97c84e33c363b86626419d8f4db 100644 (file)
 #  include "memdebug.h"
 #endif
 
-int select_test (int num_fds, fd_set *rd, fd_set *wr, fd_set *exc,
-                 struct timeval *tv)
+int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
+                   struct timeval *tv)
 {
+  if(nfds < 0) {
+    SET_SOCKERRNO(EINVAL);
+    return -1;
+  }
 #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);
     return 0;
   }
 #endif
-  return select(num_fds, rd, wr, exc, tv);
+  return select(nfds, rd, wr, exc, tv);
 }
 
 char *libtest_arg2=NULL;
@@ -50,6 +56,8 @@ char *libtest_arg3=NULL;
 int test_argc;
 char **test_argv;
 
+struct timeval tv_test_start; /* for test timing */
+
 #ifdef UNITTESTS
 int unitfail; /* for unittests */
 #endif
index e8bfe47443c3e70d63c0dbbb0d1597a4ce22664a..554583ae2aa45ea74d5d0acfa8ebeaa69cec0245 100644 (file)
@@ -25,8 +25,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 /*
  * Get a single URL without select().
 
 int test(char *URL)
 {
-  CURL *c;
+  CURL *c = NULL;
   CURLM *m = NULL;
   int res = 0;
-  int running=1;
-  struct timeval mp_start;
-  char mp_timedout = FALSE;
+  int running;
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  if ((c = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  test_setopt(c, CURLOPT_URL, URL);
+  easy_init(c);
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(c);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_setopt(c, CURLOPT_URL, URL);
 
-  if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
 
-  mp_timedout = FALSE;
-  mp_start = tutil_tvnow();
+  multi_add_handle(m, c);
 
-  while (running) {
-    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+  for(;;) {
+    struct timeval timeout;
     fd_set fdread, fdwrite, fdexcep;
-    int maxfd = -1;
-
-    res = (int)curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (running <= 0) {
-      fprintf(stderr, "nothing left running.\n");
-      break;
-    }
+    int maxfd = -99;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 100000L; /* 100 ms */
+
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
     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
-       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) {
-      res = ~CURLM_OK;
-      break;
-    }
-  }
 
-  if (mp_timedout) {
-    fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
-            "that it would have run forever.\n");
-    res = TEST_ERR_RUNS_FOREVER;
+    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
-  if(m) {
-    curl_multi_remove_handle(m, c);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+
+  curl_multi_remove_handle(m, c);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(c);
   curl_global_cleanup();
 
index 763318827533a2f9744b2e5a253bc068bf77d6c6..f3f96aaa51eb80f96edfd26f1f7d317f827bf469 100644 (file)
@@ -25,8 +25,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 /*
  * Source code in here hugely as reported in bug report 651460 by
 
 int test(char *URL)
 {
-  CURL *c;
+  CURL *c = NULL;
   CURLM *m = NULL;
   int res = 0;
   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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
 
-  if ((c = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  test_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.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) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(c);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) {
-    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;
-  }
+  easy_init(c);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  easy_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */
+  easy_setopt(c, CURLOPT_URL, URL);
+  easy_setopt(c, CURLOPT_USERPWD, "test:ing");
+  easy_setopt(c, CURLOPT_PROXYUSERPWD, "test:ing");
+  easy_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L);
+  easy_setopt(c, CURLOPT_HEADER, 1L);
 
-  while(!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  multi_init(m);
+
+  multi_add_handle(m, c);
+
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    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)
-      break;
-
-    if (res != CURLM_OK) {
-      fprintf(stderr, "not okay???\n");
-      break;
-    }
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 89;
-      break;
-    }
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
 
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 95;
-      break;
-    }
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-  }
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
 
-  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;
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
-  if(m) {
-    curl_multi_remove_handle(m, c);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+
+  curl_multi_remove_handle(m, c);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(c);
   curl_global_cleanup();
 
index 70aec38cc984295e260363674dcc0a1f6bf5f4c7..358fc98dc8080cfdb7596d1e71f29761791ebf70 100644 (file)
@@ -25,8 +25,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 /*
  * Source code in here hugely as reported in bug report 651464 by
  */
 int test(char *URL)
 {
-  CURL *c;
+  CURL *c = NULL;
   int res = 0;
   CURLM *m = NULL;
   fd_set rd, wr, exc;
-  CURLMcode ret;
-  char done = FALSE;
   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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
 
-  if ((c = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
+
+  global_init(CURL_GLOBAL_ALL);
+
+  easy_init(c);
 
   /* The point here is that there must not be anything running on the given
      proxy port */
   if (libtest_arg2)
-    test_setopt(c, CURLOPT_PROXY, libtest_arg2);
-  test_setopt(c, CURLOPT_URL, URL);
-  test_setopt(c, CURLOPT_VERBOSE, 1L);
-
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(c);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+    easy_setopt(c, CURLOPT_PROXY, libtest_arg2);
+  easy_setopt(c, CURLOPT_URL, URL);
+  easy_setopt(c, CURLOPT_VERBOSE, 1L);
 
-  if ((ret = curl_multi_add_handle(m, c)) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_add_handle(m, c);
 
-  while (!done) {
+  for(;;) {
     struct timeval interval;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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");
 
-    ret = curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (mp_timedout)
-      break;
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
 
     if(!running) {
       /* 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);
       fprintf(stderr, "Expected: not running\n");
       if(msg && !numleft)
-        res = 100; /* this is where we should be */
+        res = TEST_ERR_SUCCESS; /* this is where we should be */
       else
-        res = 99; /* not correct */
-      break;
-    }
-    fprintf(stderr, "running == %d, ret == %d\n", running, ret);
-
-    if (ret != CURLM_OK) {
-      res = 2;
-      break;
+        res = TEST_ERR_FAILURE; /* not correct */
+      break; /* done */
     }
+    fprintf(stderr, "running == %d\n", running);
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
     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) {
-    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;
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
-  if(m) {
-    curl_multi_remove_handle(m, c);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+
+  curl_multi_remove_handle(m, c);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(c);
   curl_global_cleanup();
 
index e4a1b241b4f05f52470857cf65da0ac76be19e15..87c21defbdf6372bbb84955fd32e47d73de73131 100644 (file)
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 int test(char *URL)
 {
-  CURL* curls;
-  CURLM* multi;
+  CURL* curls = NULL;
+  CURLM* multi = NULL;
   int still_running;
   int i = -1;
   int res = 0;
   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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
 
-  if ((multi = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  if ((curls = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_multi_cleanup(multi);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  test_setopt(curls, CURLOPT_URL, URL);
-  test_setopt(curls, CURLOPT_HEADER, 1L);
+  multi_init(multi);
 
-  if ((ret = curl_multi_add_handle(multi, curls)) != CURLM_OK) {
-    fprintf(stderr, "curl_multi_add_handle() failed, "
-            "with code %d\n", ret);
-    curl_easy_cleanup(curls);
-    curl_multi_cleanup(multi);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_init(curls);
 
-  mp_timedout = FALSE;
-  mp_start = tutil_tvnow();
+  easy_setopt(curls, CURLOPT_URL, URL);
+  easy_setopt(curls, CURLOPT_HEADER, 1L);
 
-  ret = curl_multi_perform(multi, &still_running);
-  if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-      MULTI_PERFORM_HANG_TIMEOUT)
-    mp_timedout = TRUE;
+  multi_add_handle(multi, curls);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_perform(multi, &still_running);
 
-  while ((!ml_timedout) && (!mp_timedout) && (still_running)) {
+  abort_on_test_timeout();
+
+  while(still_running) {
     struct timeval timeout;
-    int rc;
     fd_set fdread;
     fd_set fdwrite;
     fd_set fdexcep;
-    int maxfd;
+    int maxfd = -99;
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
@@ -97,47 +66,29 @@ int test(char *URL)
     timeout.tv_sec = 1;
     timeout.tv_usec = 0;
 
-    if (tutil_tvdiff(tutil_tvnow(), ml_start) >
-        MAIN_LOOP_HANG_TIMEOUT) {
-      ml_timedout = TRUE;
-      break;
-    }
-
-    curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
-    rc = select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
-    switch(rc) {
-      case -1:
-        break;
-      case 0:
-      default:
-        mp_timedout = FALSE;
-        mp_start = tutil_tvnow();
-        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;
+    multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
+
+    multi_perform(multi, &still_running);
+
+    abort_on_test_timeout();
   }
 
+  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:
 
+  /* undocumented cleanup sequence - type UA */
+
   curl_multi_cleanup(multi);
   curl_easy_cleanup(curls);
   curl_global_cleanup();
index 5814b030e55c1ca4df8f54f6e0f7379986d1aba7..ca128cb9c641c8b5848a3b2e15d324aa568ad53b 100644 (file)
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 int test(char *URL)
 {
   int res = 0;
-  CURL *curl;
-  FILE *hd_src ;
+  CURL *curl = NULL;
+  FILE *hd_src = NULL;
   int hd ;
   int error;
   struct_stat file_info;
-  int running;
-  char done=FALSE;
   CURLM *m = NULL;
-  struct timeval ml_start;
-  struct timeval mp_start;
-  char ml_timedout = FALSE;
-  char mp_timedout = FALSE;
+  int running;
+
+  start_test_timing();
 
-  if (!libtest_arg2) {
+  if(!libtest_arg2) {
+#ifdef LIB529
+    /* test 529 */
+    fprintf(stderr, "Usage: lib529 [url] [uploadfile]\n");
+#else
+    /* test 525 */
     fprintf(stderr, "Usage: lib525 [url] [uploadfile]\n");
-    return -1;
+#endif
+    return TEST_ERR_USAGE;
   }
 
   hd_src = fopen(libtest_arg2, "rb");
   if(NULL == hd_src) {
     error = ERRNO;
-    fprintf(stderr, "fopen() failed with error: %d %s\n",
+    fprintf(stderr, "fopen() failed with error: %d (%s)\n",
             error, strerror(error));
-    fprintf(stderr, "Error opening file: %s\n", libtest_arg2);
-    return TEST_ERR_MAJOR_BAD;
+    fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
+    return TEST_ERR_FOPEN;
   }
 
   /* get the file size of the local file */
@@ -65,40 +67,35 @@ int test(char *URL)
   if(hd == -1) {
     /* can't open file, bail out */
     error = ERRNO;
-    fprintf(stderr, "fstat() failed with error: %d %s\n",
+    fprintf(stderr, "fstat() failed with error: %d (%s)\n",
             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);
-    return -1;
+    return TEST_ERR_FSTAT;
   }
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
+  res_global_init(CURL_GLOBAL_ALL);
+  if(res) {
     fclose(hd_src);
-    return TEST_ERR_MAJOR_BAD;
+    return res;
   }
 
-  if ((curl = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    fclose(hd_src);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_init(curl);
 
   /* enable uploading */
-  test_setopt(curl, CURLOPT_UPLOAD, 1L);
+  easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
   /* specify target */
-  test_setopt(curl,CURLOPT_URL, URL);
+  easy_setopt(curl,CURLOPT_URL, URL);
 
   /* go verbose */
-  test_setopt(curl, CURLOPT_VERBOSE, 1L);
+  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
 
   /* use active FTP */
-  test_setopt(curl, CURLOPT_FTPPORT, "-");
+  easy_setopt(curl, CURLOPT_FTPPORT, "-");
 
   /* 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
      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
      curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
      make sure that to pass in a type 'long' argument. */
-  test_setopt(curl, CURLOPT_INFILESIZE_LARGE,
-                   (curl_off_t)file_info.st_size);
-
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(curl);
-    curl_global_cleanup();
-    fclose(hd_src);
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
 
-  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_add_handle(m, curl);
 
-  while (!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    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) {
-      fprintf(stderr, "not okay???\n");
-      break;
-    }
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 189;
-      break;
-    }
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
 
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 195;
-      break;
-    }
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    res = CURLM_CALL_MULTI_PERFORM;
-  }
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
 
-  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;
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
 #ifdef LIB529
   /* test 529 */
-  if(m) {
-    curl_multi_remove_handle(m, curl);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+  curl_multi_remove_handle(m, curl);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(curl);
+  curl_global_cleanup();
 #else
   /* test 525 */
-  if(m)
-    curl_multi_remove_handle(m, curl);
+  /* proper cleanup sequence - type PB */
+  curl_multi_remove_handle(m, curl);
   curl_easy_cleanup(curl);
-  if(m)
-    curl_multi_cleanup(m);
+  curl_multi_cleanup(m);
+  curl_global_cleanup();
 #endif
 
-  fclose(hd_src); /* close the local file */
+  /* close the local file */
+  fclose(hd_src);
 
-  curl_global_cleanup();
   return res;
 }
index 6e16be11b3242c36ba7f1313588a6ab9fdbbcd91..9db04dba701d69a1a1098bf2ba9a106390ab48e9 100644 (file)
@@ -46,8 +46,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 #define NUM_HANDLES 4
 
@@ -56,109 +55,51 @@ int test(char *URL)
   int res = 0;
   CURL *curl[NUM_HANDLES];
   int running;
-  char done=FALSE;
   CURLM *m = NULL;
-  int current=0;
-  int i, j;
-  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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  int current = 0;
+  int i;
+
+  for(i=0; i < NUM_HANDLES; i++)
+    curl[i] = NULL;
+
+  start_test_timing();
+
+  global_init(CURL_GLOBAL_ALL);
 
   /* get NUM_HANDLES easy handles */
   for(i=0; i < NUM_HANDLES; i++) {
-    curl[i] = curl_easy_init();
-    if(!curl[i]) {
-      fprintf(stderr, "curl_easy_init() failed "
-              "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;
-    }
-
+    easy_init(curl[i]);
+    /* specify target */
+    easy_setopt(curl[i], CURLOPT_URL, URL);
     /* go verbose */
-    res = curl_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) {
-    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;
+    easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
   }
 
-  if ((res = (int)curl_multi_add_handle(m, curl[current])) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_add_handle(m, curl[current]);
 
   fprintf(stderr, "Start at URL 0\n");
 
-  while (!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (running <= 0) {
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running) {
 #ifdef LIB527
       /* NOTE: this code does not remove the handle from the multi handle
          here, which would be the nice, sane and documented way of working.
          This however tests that the API survives this abuse gracefully. */
       curl_easy_cleanup(curl[current]);
+      curl[current] = NULL;
 #endif
       if(++current < NUM_HANDLES) {
         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
            the handle first too */
         curl_easy_reset(curl[0]);
-        test_setopt(curl[0], CURLOPT_URL, URL);
-        test_setopt(curl[0], CURLOPT_VERBOSE, 1L);
+        easy_setopt(curl[0], CURLOPT_URL, URL);
+        /* go verbose */
+        easy_setopt(curl[0], CURLOPT_VERBOSE, 1L);
 
         /* re-add it */
-        res = (int)curl_multi_add_handle(m, curl[0]);
+        multi_add_handle(m, curl[0]);
 #else
-        res = (int)curl_multi_add_handle(m, curl[current]);
+        multi_add_handle(m, curl[current]);
 #endif
-        if(res) {
-          fprintf(stderr, "add handle failed: %d.\n", res);
-          res = 243;
-          break;
-        }
       }
       else {
-        done = TRUE; /* bail out */
-        break;
+        break; /* done */
       }
     }
 
-    if (res != CURLM_OK) {
-      fprintf(stderr, "not okay???\n");
-      break;
-    }
-
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 189;
-      break;
-    }
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
 
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 195;
-      break;
-    }
-  }
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
 
-  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;
+    abort_on_test_timeout();
   }
 
-#ifdef LIB532
 test_cleanup:
-#endif
 
-#ifndef LIB527
-  /* get NUM_HANDLES easy handles */
+#if defined(LIB526)
+
+  /* test 526 and 528 */
+  /* proper cleanup sequence - type PB */
+
   for(i=0; i < NUM_HANDLES; i++) {
-#ifdef LIB526
-    if(m)
-      curl_multi_remove_handle(m, curl[i]);
-#endif
+    curl_multi_remove_handle(m, curl[i]);
     curl_easy_cleanup(curl[i]);
   }
-#endif
-  if(m)
-    curl_multi_cleanup(m);
+  curl_multi_cleanup(m);
+  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;
 }
index 03c4a62fa57ca5e3ce87eead47d5226dcb578740..ad84ff8a5579b6328c7d00168c135cf76c2bb292 100644 (file)
@@ -25,8 +25,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 #define NUM_HANDLES 4
 
@@ -35,169 +34,71 @@ int test(char *URL)
   int res = 0;
   CURL *curl[NUM_HANDLES];
   int running;
-  char done=FALSE;
-  CURLM *m;
-  int i, j;
-  struct timeval ml_start;
-  struct timeval mp_start;
-  char ml_timedout = FALSE;
-  char mp_timedout = FALSE;
+  CURLM *m = NULL;
+  int i;
   char target_url[256];
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  for(i=0; i < NUM_HANDLES; i++)
+    curl[i] = NULL;
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
+
+  global_init(CURL_GLOBAL_ALL);
+
+  multi_init(m);
 
   /* get NUM_HANDLES easy handles */
   for(i=0; i < NUM_HANDLES; i++) {
-    curl[i] = curl_easy_init();
-    if(!curl[i]) {
-      fprintf(stderr, "curl_easy_init() failed "
-              "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;
-    }
+    /* get an easy handle */
+    easy_init(curl[i]);
+    /* specify target */
     sprintf(target_url, "%s%04i", URL, i + 1);
     target_url[sizeof(target_url) - 1] = '\0';
-
-    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;
-    }
-
+    easy_setopt(curl[i], CURLOPT_URL, target_url);
     /* go verbose */
-    res = curl_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;
-    }
-
+    easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
     /* include headers */
-    res = curl_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;
-    }
-
+    easy_setopt(curl[i], CURLOPT_HEADER, 1L);
     /* add handle to multi */
-    if ((res = (int)curl_multi_add_handle(m, curl[i])) != CURLM_OK) {
-      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;
-    }
+    multi_add_handle(m, curl[i]);
   }
 
-  curl_multi_setopt(m, CURLMOPT_PIPELINING, 1L);
-
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_setopt(m, CURLMOPT_PIPELINING, 1L);
 
   fprintf(stderr, "Start at URL 0\n");
 
-  while (!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    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) {
-      fprintf(stderr, "not okay???\n");
-      break;
-    }
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 189;
-      break;
-    }
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
 
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 195;
-      break;
-    }
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    res = CURLM_CALL_MULTI_PERFORM;
-  }
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
 
-  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;
+    abort_on_test_timeout();
   }
 
-/* test_cleanup: */
+test_cleanup:
+
+  /* proper cleanup sequence - type PB */
 
-  /* cleanup NUM_HANDLES easy handles */
   for(i=0; i < NUM_HANDLES; i++) {
     curl_multi_remove_handle(m, curl[i]);
     curl_easy_cleanup(curl[i]);
index 487e01824f4ed0e9cae2b0b455895bcb883437e5..fdc18a1eb959c4a902cbdc86f4fb3e828ae8ffac 100644 (file)
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 int test(char *URL)
 {
   int res = 0;
-  CURL *curl;
+  CURL *curl = NULL;
   int running;
-  char done=FALSE;
   CURLM *m = NULL;
   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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
 
-  if ((curl = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  test_setopt(curl, CURLOPT_URL, URL);
-  test_setopt(curl, CURLOPT_VERBOSE, 1);
-  test_setopt(curl, CURLOPT_FAILONERROR, 1);
+  global_init(CURL_GLOBAL_ALL);
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(curl);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_init(curl);
 
-  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
-    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;
-  }
+  easy_setopt(curl, CURLOPT_URL, URL);
+  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+  easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
+
+  multi_init(m);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_add_handle(m, curl);
 
   fprintf(stderr, "Start at URL 0\n");
 
-  while (!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (running <= 0) {
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running) {
       if(!current++) {
         fprintf(stderr, "Advancing to URL 1\n");
         /* 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
            the handle first too */
         curl_easy_reset(curl);
-        test_setopt(curl, CURLOPT_URL, libtest_arg2);
-        test_setopt(curl, CURLOPT_VERBOSE, 1);
-        test_setopt(curl, CURLOPT_FAILONERROR, 1);
+        easy_setopt(curl, CURLOPT_URL, libtest_arg2);
+        easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+        easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
 
         /* re-add it */
-        res = (int)curl_multi_add_handle(m, curl);
-        if(res) {
-          fprintf(stderr, "add handle failed: %d.\n", res);
-          res = 243;
-          break;
-        }
-      }
-      else {
-        done = TRUE; /* bail out */
-        break;
+        multi_add_handle(m, curl);
       }
-    }
-
-    if (res != CURLM_OK) {
-      fprintf(stderr, "not okay???\n");
-      break;
+      else
+        break; /* done */
     }
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
 
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 189;
-      break;
-    }
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
 
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 195;
-      break;
-    }
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    res = CURLM_CALL_MULTI_PERFORM;
-  }
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
 
-  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;
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
+  /* undocumented cleanup sequence - type UB */
+
   curl_easy_cleanup(curl);
-  if(m)
-    curl_multi_cleanup(m);
+  curl_multi_cleanup(m);
   curl_global_cleanup();
 
   return res;
index 4813145d044a81bfa46bfc17e28c8646cec90291..e3ae402b710e02785d71f6ed64dc24ce1ee2c22c 100644 (file)
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
-static CURLMcode perform(CURLM * multi)
+static int perform(CURLM *multi)
 {
   int handles;
-  CURLMcode code;
   fd_set fdread, fdwrite, fdexcep;
-  struct timeval mp_start;
-  char mp_timedout = FALSE;
-
-  mp_timedout = FALSE;
-  mp_start = tutil_tvnow();
-
-  for (;;) {
-    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
-    int maxfd = -1;
-
-    code = curl_multi_perform(multi, &handles);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (handles <= 0)
-      return CURLM_OK;
-
-    switch (code) {
-      case CURLM_OK:
-        break;
-      default:
-        return code;
-    }
+  int res = 0;
+
+  for(;;) {
+    struct timeval interval;
+    int maxfd = -99;
+
+    interval.tv_sec = 0;
+    interval.tv_usec = 100000L; /* 100 ms */
+
+    res_multi_perform(multi, &handles);
+    if(res)
+      return res;
+
+    res_test_timedout();
+    if(res)
+      return res;
+
+    if(!handles)
+      break; /* done */
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
     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
-       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. */
+    res_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
+    if(res)
+      return res;
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -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) */
-  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;
+  return 0; /* success */
 }
 
 int test(char *URL)
 {
-  CURLM *multi;
-  CURL *easy;
+  CURLM *multi = NULL;
+  CURL *easy = NULL;
   int res = 0;
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  if ((multi = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  if ((easy = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_multi_cleanup(multi);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  multi_init(multi);
 
-  curl_multi_setopt(multi, CURLMOPT_PIPELINING, 1L);
+  easy_init(easy);
 
-  test_setopt(easy, CURLOPT_WRITEFUNCTION, fwrite);
-  test_setopt(easy, CURLOPT_FAILONERROR, 1L);
-  test_setopt(easy, CURLOPT_URL, URL);
+  multi_setopt(multi, CURLMOPT_PIPELINING, 1L);
 
-  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");
+  easy_setopt(easy, CURLOPT_WRITEFUNCTION, fwrite);
+  easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
+  easy_setopt(easy, CURLOPT_URL, URL);
 
-    curl_multi_remove_handle(multi, easy);
+  res_multi_add_handle(multi, easy);
+  if(res) {
+    printf("curl_multi_add_handle() 1 failed\n");
+    goto test_cleanup;
   }
+
+  res = perform(multi);
+  if(res) {
+    printf("retrieve 1 failed\n");
+    goto test_cleanup;
+  }
+
+  curl_multi_remove_handle(multi, easy);
+
   curl_easy_reset(easy);
 
-  test_setopt(easy, CURLOPT_FAILONERROR, 1L);
-  test_setopt(easy, CURLOPT_URL, libtest_arg2);
+  easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
+  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");
-    res = TEST_ERR_MAJOR_BAD;
-  } else {
-    if (perform(multi) != CURLM_OK)
-      printf("retrieve 2 failed\n");
+    goto test_cleanup;
+  }
 
-    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:
 
+  /* undocumented cleanup sequence - type UB */
+
   curl_easy_cleanup(easy);
   curl_multi_cleanup(multi);
   curl_global_cleanup();
index e864947c9bc8a5c6b3af771bbffa9dcf3c7b1226..21d14872baafe634f05f638c103d340a95a93898 100644 (file)
 
 #include "test.h"
 
+#include "testutil.h"
 #include "warnless.h"
 #include "memdebug.h"
 
+#define TEST_HANG_TIMEOUT 60 * 1000
+
 #define PROXY libtest_arg2
 #define PROXYUSERPWD libtest_arg3
 #define HOST test_argv[4]
 
-CURL *eh = NULL;
+#define NUM_HANDLES 2
+
+CURL *eh[NUM_HANDLES];
 
-static int init(CURLM *cm, const char* url, const char* userpwd,
+static int init(int num, CURLM *cm, const char* url, const char* userpwd,
                 struct curl_slist *headers)
 {
-  int res;
+  int res = 0;
 
-  if ((eh = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
+  res_easy_init(eh[num]);
+  if(res)
     goto init_failed;
-  }
 
-  res = curl_easy_setopt(eh, CURLOPT_URL, url);
+  res_easy_setopt(eh[num], CURLOPT_URL, url);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_PROXY, PROXY);
+  res_easy_setopt(eh[num], CURLOPT_PROXY, PROXY);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_PROXYUSERPWD, userpwd);
+  res_easy_setopt(eh[num], CURLOPT_PROXYUSERPWD, userpwd);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
+  res_easy_setopt(eh[num], CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_VERBOSE, 1L);
+  res_easy_setopt(eh[num], CURLOPT_VERBOSE, 1L);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_HEADER, 1L);
+  res_easy_setopt(eh[num], CURLOPT_HEADER, 1L);
   if(res)
     goto init_failed;
 
-  res = curl_easy_setopt(eh, CURLOPT_HTTPHEADER, headers); /* custom Host: */
+  res_easy_setopt(eh[num], CURLOPT_HTTPHEADER, headers); /* custom Host: */
   if(res)
     goto init_failed;
 
-  if ((res = (int)curl_multi_add_handle(cm, eh)) != CURLM_OK) {
-    fprintf(stderr, "curl_multi_add_handle() failed, with code %d\n", res);
+  res_multi_add_handle(cm, eh[num]);
+  if(res)
     goto init_failed;
-  }
 
   return 0; /* success */
 
 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)
 {
   CURLMsg *msg;
   long L;
-  int M, Q, U = -1;
+  int Q, U = -1;
   fd_set R, W, E;
   struct timeval T;
-  CURLMcode rc;
+  int res = 0;
 
-  if(init(cm, url, userpwd, headers))
-    return 1; /* failure */
+  res = init(num, cm, url, userpwd, headers);
+  if(res)
+    return res;
 
   while (U) {
 
-    rc = curl_multi_perform(cm, &U);
-    if(rc == CURLM_OUT_OF_MEMORY)
-      return 1; /* failure */
+    int M = -99;
+
+    res_multi_perform(cm, &U);
+    if(res)
+      return res;
+
+    res_test_timedout();
+    if(res)
+      return res;
 
     if (U) {
       FD_ZERO(&R);
       FD_ZERO(&W);
       FD_ZERO(&E);
 
-      if (curl_multi_fdset(cm, &R, &W, &E, &M)) {
-        fprintf(stderr, "E: curl_multi_fdset\n");
-        return 1; /* failure */
-      }
+      res_multi_fdset(cm, &R, &W, &E, &M);
+      if(res)
+        return res;
 
-      /* In a real-world program you OF COURSE check the return that maxfd is
-         bigger than -1 so that the call to select() below makes sense! */
+      /* At this point, M is guaranteed to be greater or equal than -1. */
 
-      if (curl_multi_timeout(cm, &L)) {
-        fprintf(stderr, "E: curl_multi_timeout\n");
-        return 1; /* failure */
-      }
+      res_multi_timeout(cm, &L);
+      if(res)
+        return res;
 
       if(L != -1) {
         T.tv_sec = L/1000;
@@ -139,25 +145,33 @@ static int loop(CURLM *cm, const char* url, const char* userpwd,
         T.tv_usec = 0;
       }
 
-      if (0 > select(M+1, &R, &W, &E, &T)) {
-        fprintf(stderr, "E: select\n");
-        return 1; /* failure */
-      }
+      res_select_test(M+1, &R, &W, &E, &T);
+      if(res)
+        return res;
     }
 
-    while ((msg = curl_multi_info_read(cm, &Q))) {
-      if (msg->msg == CURLMSG_DONE) {
+    while((msg = curl_multi_info_read(cm, &Q)) != NULL) {
+      if(msg->msg == CURLMSG_DONE) {
+        int i;
         CURL *e = msg->easy_handle;
         fprintf(stderr, "R: %d - %s\n", (int)msg->data.result,
                 curl_easy_strerror(msg->data.result));
         curl_multi_remove_handle(cm, 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);
-      }
     }
+
+    res_test_timedout();
+    if(res)
+      return res;
   }
 
   return 0; /* success */
@@ -168,7 +182,13 @@ int test(char *URL)
   CURLM *cm = NULL;
   struct curl_slist *headers = NULL;
   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)
     return 99;
@@ -182,37 +202,37 @@ int test(char *URL)
     return TEST_ERR_MAJOR_BAD;
   }
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
+  res_global_init(CURL_GLOBAL_ALL);
+  if(res) {
     curl_slist_free_all(headers);
-    return TEST_ERR_MAJOR_BAD;
+    return res;
   }
 
-  if ((cm = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_slist_free_all(headers);
+  res_multi_init(cm);
+  if(res) {
     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)
     goto test_cleanup;
 
   fprintf(stderr, "lib540: now we do the request again\n");
-  res = loop(cm, URL, PROXYUSERPWD, headers);
 
-test_cleanup:
+  res = loop(1, cm, URL, PROXYUSERPWD, headers);
 
-  if(cm && eh)
-    curl_multi_remove_handle(cm, eh);
+test_cleanup:
 
-  if(eh)
-    curl_easy_cleanup(eh);
+  /* proper cleanup sequence - type PB */
 
-  if(cm)
-    curl_multi_cleanup(cm);
+  for(i=0; i < NUM_HANDLES; i++) {
+    curl_multi_remove_handle(cm, eh[i]);
+    curl_easy_cleanup(eh[i]);
+  }
 
+  curl_multi_cleanup(cm);
   curl_global_cleanup();
 
   curl_slist_free_all(headers);
index b077927ac5ab5777aa5937fed3c53a686ca6cf4c..49a81bf577423e66c19486271b05e1908cfd3326 100644 (file)
@@ -33,7 +33,7 @@
 #include "warnless.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"
 
@@ -75,114 +75,82 @@ static curlioerr ioctlcallback(CURL *handle,
 
 int test(char *URL)
 {
-  int res;
-  CURL *curl;
+  int res = 0;
+  CURL *curl = NULL;
   int counter=0;
   CURLM *m = NULL;
   int running=1;
-  struct timeval mp_start;
-  char mp_timedout = FALSE;
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  if ((curl = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
+
+  easy_init(curl);
 
-  test_setopt(curl, CURLOPT_URL, URL);
-  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 */
-  test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
-  test_setopt(curl, CURLOPT_IOCTLDATA, &counter);
-  test_setopt(curl, CURLOPT_READFUNCTION, readcallback);
-  test_setopt(curl, CURLOPT_READDATA, &counter);
+  easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
+  easy_setopt(curl, CURLOPT_IOCTLDATA, &counter);
+  easy_setopt(curl, CURLOPT_READFUNCTION, readcallback);
+  easy_setopt(curl, CURLOPT_READDATA, &counter);
   /* 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
   /* Convert the POST data to ASCII. */
-  test_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
+  easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
 #endif
-  test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
-  test_setopt(curl, CURLOPT_PROXYUSERPWD, libtest_arg3);
-  test_setopt(curl, CURLOPT_PROXYAUTH,
+  easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
+  easy_setopt(curl, CURLOPT_PROXYUSERPWD, libtest_arg3);
+  easy_setopt(curl, CURLOPT_PROXYAUTH,
                    (long) (CURLAUTH_NTLM | CURLAUTH_DIGEST | CURLAUTH_BASIC) );
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(curl);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  multi_init(m);
 
-  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
-    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();
+  multi_add_handle(m, curl);
 
   while (running) {
-    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+    struct timeval timeout;
     fd_set fdread, fdwrite, fdexcep;
-    int maxfd = -1;
-
-    res = (int)curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
+    int maxfd = -99;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 100000L; /* 100 ms */
+
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
 #ifdef TPF
     sleep(1); /* avoid ctl-10 dump */
 #endif
-    if (running <= 0) {
-      fprintf(stderr, "nothing left running.\n");
-      break;
-    }
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
     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
-       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) {
-      res = ~CURLM_OK;
-      break;
-    }
-  }
 
-  if (mp_timedout) {
-    fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
-            "that it would have run forever.\n");
-    res = TEST_ERR_RUNS_FOREVER;
+    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
-  if(m) {
-    curl_multi_remove_handle(m, curl);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+
+  curl_multi_remove_handle(m, curl);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(curl);
   curl_global_cleanup();
 
index cba9aa0004472b87bd4afee61fd6c32c67154024..e8be1c7bddee2dbecf99dc1ec0a00bd999762132 100644 (file)
  ***************************************************************************/
 #include "test.h"
 
+#include "testutil.h"
 #include "warnless.h"
 #include "memdebug.h"
 
+#define TEST_HANG_TIMEOUT 60 * 1000
+
 /*
  * Simply download a HTTPS file!
  *
  */
 int test(char *URL)
 {
-  CURL *http_handle;
+  CURL *http_handle = NULL;
   CURLM *multi_handle = NULL;
-  int res;
+  int res = 0;
 
   int still_running; /* keep number of running handles */
 
-  http_handle = curl_easy_init();
-  if (!http_handle)
-    return TEST_ERR_MAJOR_BAD;
+  start_test_timing();
+
+  /*
+  ** curl_global_init called indirectly from curl_easy_init.
+  */
+
+  easy_init(http_handle);
 
   /* set options */
-  test_setopt(http_handle, CURLOPT_URL, URL);
-  test_setopt(http_handle, CURLOPT_HEADER, 1L);
-  test_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L);
-  test_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);
+  easy_setopt(http_handle, CURLOPT_URL, URL);
+  easy_setopt(http_handle, CURLOPT_HEADER, 1L);
+  easy_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L);
+  easy_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);
 
   /* init a multi stack */
-  multi_handle = curl_multi_init();
-  if (!multi_handle) {
-    curl_easy_cleanup(http_handle);
-    return TEST_ERR_MAJOR_BAD;
-  }
+  multi_init(multi_handle);
 
   /* 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 */
-  (void) curl_multi_perform(multi_handle, &still_running);
+  multi_perform(multi_handle, &still_running);
+
+  abort_on_test_timeout();
 
   while(still_running) {
     struct timeval timeout;
-    int rc; /* select() return code */
 
     fd_set fdread;
     fd_set fdwrite;
     fd_set fdexcep;
-    int maxfd;
+    int maxfd = -99;
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
@@ -83,31 +87,25 @@ int test(char *URL)
     timeout.tv_usec = 0;
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
-
-    /* In a real-world program you OF COURSE check the return code of the
-       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);
-
-    switch(rc) {
-    case -1:
-      /* select error */
-      break;
-    case 0:
-    default:
-      /* timeout or readable/writable sockets */
-      (void) curl_multi_perform(multi_handle, &still_running);
-      break;
-    }
+    multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
+
+    /* timeout or readable/writable sockets */
+    multi_perform(multi_handle, &still_running);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
-  if(multi_handle)
-    curl_multi_cleanup(multi_handle);
+  /* undocumented cleanup sequence - type UA */
 
+  curl_multi_cleanup(multi_handle);
   curl_easy_cleanup(http_handle);
   curl_global_cleanup();
 
index 9bb3c7404ab1d08da9b47819e774e673624b846b..ed00e1bf62a3641891f9d44932ff79fe1e189229 100644 (file)
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 int test(char *URL)
 {
   int res = 0;
-  CURL *curl;
+  CURL *curl = NULL;
   int running;
-  char done=FALSE;
   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) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
 
-  if ((curl = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  test_setopt(curl, CURLOPT_URL, URL);
-  test_setopt(curl, CURLOPT_VERBOSE, 1);
-  test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
-  test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+  global_init(CURL_GLOBAL_ALL);
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(curl);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_init(curl);
 
-  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
-    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;
-  }
+  easy_setopt(curl, CURLOPT_URL, URL);
+  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+  easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
+  easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_init(m);
+
+  multi_add_handle(m, curl);
 
   fprintf(stderr, "Start at URL 0\n");
 
-  while (!done) {
-    fd_set rd, wr, exc;
-    int max_fd;
+  for(;;) {
     struct timeval interval;
+    fd_set rd, wr, exc;
+    int maxfd = -99;
 
     interval.tv_sec = 1;
     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();
-
-    res = (int)curl_multi_perform(m, &running);
-    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) {
-      fprintf(stderr, "not okay???\n");
-      break;
-    }
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&rd);
     FD_ZERO(&wr);
     FD_ZERO(&exc);
-    max_fd = 0;
-
-    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
-      fprintf(stderr, "unexpected failured of fdset.\n");
-      res = 189;
-      break;
-    }
-
-    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
-      fprintf(stderr, "bad select??\n");
-      res = 195;
-      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");
-    res = TEST_ERR_RUNS_FOREVER;
+    multi_fdset(m, &rd, &wr, &exc, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
 
+  /* undocumented cleanup sequence - type UB */
+
   curl_easy_cleanup(curl);
-  if(m)
-    curl_multi_cleanup(m);
+  curl_multi_cleanup(m);
   curl_global_cleanup();
 
   return res;
index 1d8602e1ff5b4646191a7a75e99d1ce1101e340a..943f6e8c84cbd37e636ddb0057f04d4b91bd014a 100644 (file)
@@ -25,8 +25,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
-#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 /*
  * Get a single URL without select().
 
 int test(char *URL)
 {
-  CURL *c;
+  CURL *c = NULL;
   CURLM *m = NULL;
   int res = 0;
-  int running=1;
+  int running = 1;
   double connect_time = 0.0;
-  struct timeval mp_start;
-  char mp_timedout = FALSE;
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
+  start_test_timing();
 
-  if ((c = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  test_setopt(c, CURLOPT_HEADER, 1L);
-  test_setopt(c, CURLOPT_URL, URL);
+  easy_init(c);
 
-  if ((m = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_easy_cleanup(c);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_setopt(c, CURLOPT_HEADER, 1L);
+  easy_setopt(c, CURLOPT_URL, URL);
 
-  if ((res = (int)curl_multi_add_handle(m, c)) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
 
-  mp_timedout = FALSE;
-  mp_start = tutil_tvnow();
+  multi_add_handle(m, c);
 
   while (running) {
-    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+    struct timeval timeout;
     fd_set fdread, fdwrite, fdexcep;
-    int maxfd = -1;
-
-    res = (int)curl_multi_perform(m, &running);
-    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
-        MULTI_PERFORM_HANG_TIMEOUT) {
-      mp_timedout = TRUE;
-      break;
-    }
-    if (running <= 0) {
-      fprintf(stderr, "nothing left running.\n");
-      break;
-    }
+    int maxfd = -99;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 100000L; /* 100 ms */
+
+    multi_perform(m, &running);
+
+    abort_on_test_timeout();
+
+    if(!running)
+      break; /* done */
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
     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
-       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) {
-      res = ~CURLM_OK;
-      break;
-    }
-  }
 
-  if (mp_timedout) {
-    fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
-            "that it would have run forever.\n");
-    res = TEST_ERR_RUNS_FOREVER;
+    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
   }
 
   curl_easy_getinfo(c, CURLINFO_CONNECT_TIME, &connect_time);
@@ -122,10 +88,10 @@ int test(char *URL)
 
 test_cleanup:
 
-  if(m) {
-    curl_multi_remove_handle(m, c);
-    curl_multi_cleanup(m);
-  }
+  /* proper cleanup sequence - type PA */
+
+  curl_multi_remove_handle(m, c);
+  curl_multi_cleanup(m);
   curl_easy_cleanup(c);
   curl_global_cleanup();
 
index 144d11ce4b97224f3ab2ae7263dda6349d33d9dd..942df68c5798f86c4723f364ce4ec1d363c3f310 100644 (file)
@@ -27,6 +27,8 @@
 #include "warnless.h"
 #include "memdebug.h"
 
+#define TEST_HANG_TIMEOUT 60 * 1000
+
 /* 3x download!
  * 1. normal
  * 2. dup handle
 
 int test(char *URL)
 {
-  CURLMcode m;
-  CURL *handle = NULL, *duphandle;
+  CURL *handle = NULL;
+  CURL *duphandle = NULL;
   CURLM *mhandle = NULL;
   int res = 0;
   int still_running = 0;
 
-  if(curl_global_init(CURL_GLOBAL_ALL)) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    goto test_cleanup;
-  }
+  start_test_timing();
 
-  handle = curl_easy_init();
-  if(!handle) {
-    res = CURLE_OUT_OF_MEMORY;
-    goto test_cleanup;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
-  test_setopt(handle, CURLOPT_URL, URL);
-  test_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
-  test_setopt(handle, CURLOPT_VERBOSE, 1L);
+  easy_init(handle);
+
+  easy_setopt(handle, CURLOPT_URL, URL);
+  easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
+  easy_setopt(handle, CURLOPT_VERBOSE, 1L);
 
   res = curl_easy_perform(handle);
   if(res)
@@ -70,49 +67,48 @@ int test(char *URL)
   curl_easy_cleanup(handle);
   handle = duphandle;
 
-  mhandle = curl_multi_init();
-  if(!mhandle) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    goto test_cleanup;
-  }
+  multi_init(mhandle);
 
-  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) {
-    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
-    int rc;
+    struct timeval timeout;
     fd_set fdread;
     fd_set fdwrite;
     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(&fdwrite);
     FD_ZERO(&fdexcep);
 
-    m = curl_multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &max_fdset);
-    if(m != CURLM_OK) {
-      fprintf(stderr, "curl_multi_fdset() error\n");
-      goto test_cleanup;
-    }
-    /* We call select(max_fdset + 1, ...), specially in case of (maxfd == -1),
-     * we call select(0, ...), which is basically equal to sleep. */
-    rc = select(max_fdset + 1, &fdread, &fdwrite, &fdexcep, &timeout);
-    if(rc == -1) {
-      fprintf(stderr, "select() error\n");
-      goto test_cleanup;
-    }
-    else {
-      curl_multi_perform(mhandle, &still_running);
-    }
+    multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
+
+    multi_perform(mhandle, &still_running);
+
+    abort_on_test_timeout();
   }
 
 test_cleanup:
-  if(mhandle)
-    curl_multi_cleanup(mhandle);
-  if(handle)
-    curl_easy_cleanup(handle);
+
+  /* undocumented cleanup sequence - type UA */
+
+  curl_multi_cleanup(mhandle);
+  curl_easy_cleanup(handle);
   curl_global_cleanup();
+
   return res;
 }
index 91c005ed900af3036fc9f03f6ac8e9ec9f962c09..25b70609ceb277abb2f42cbbc190cf0c0a9e4689 100644 (file)
@@ -27,7 +27,7 @@
 #include "warnless.h"
 #include "memdebug.h"
 
-#define MAIN_LOOP_HANG_TIMEOUT     4 * 1000
+#define TEST_HANG_TIMEOUT 60 * 1000
 
 struct Sockets
 {
@@ -226,30 +226,30 @@ static void checkFdSet(CURLM *curl, struct Sockets *sockets, fd_set *fdset,
 int test(char *URL)
 {
   int res = 0;
-  CURL *curl;
-  FILE *hd_src ;
+  CURL *curl = NULL;
+  FILE *hd_src = NULL;
   int hd ;
   int error;
   struct_stat file_info;
   CURLM *m = NULL;
-  struct timeval ml_start;
-  char ml_timedout = FALSE;
   struct ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}};
   struct timeval timeout = {-1, 0};
   int success = 0;
 
+  start_test_timing();
+
   if (!libtest_arg3) {
     fprintf(stderr, "Usage: lib582 [url] [filename] [username]\n");
-    return -1;
+    return TEST_ERR_USAGE;
   }
 
   hd_src = fopen(libtest_arg2, "rb");
   if(NULL == hd_src) {
     error = ERRNO;
-    fprintf(stderr, "fopen() failed with error: %d %s\n",
+    fprintf(stderr, "fopen() failed with error: %d (%s)\n",
             error, strerror(error));
-    fprintf(stderr, "Error opening file: %s\n", libtest_arg2);
-    return TEST_ERR_MAJOR_BAD;
+    fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
+    return TEST_ERR_FOPEN;
   }
 
   /* get the file size of the local file */
@@ -257,71 +257,49 @@ int test(char *URL)
   if(hd == -1) {
     /* can't open file, bail out */
     error = ERRNO;
-    fprintf(stderr, "fstat() failed with error: %d %s\n",
+    fprintf(stderr, "fstat() failed with error: %d (%s)\n",
             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);
-    return -1;
+    return TEST_ERR_FSTAT;
   }
   fprintf(stderr, "Set to upload %d bytes\n", (int)file_info.st_size);
 
-  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
+  res_global_init(CURL_GLOBAL_ALL);
+  if(res) {
     fclose(hd_src);
-    return TEST_ERR_MAJOR_BAD;
+    return res;
   }
 
-  if ((curl = curl_easy_init()) == NULL) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    fclose(hd_src);
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  easy_init(curl);
 
   /* enable uploading */
-  test_setopt(curl, CURLOPT_UPLOAD, 1L);
+  easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
   /* specify target */
-  test_setopt(curl,CURLOPT_URL, URL);
+  easy_setopt(curl,CURLOPT_URL, URL);
 
   /* go verbose */
-  test_setopt(curl, CURLOPT_VERBOSE, 1L);
+  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
 
   /* 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);
-  test_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
-  test_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
+  easy_setopt(curl, CURLOPT_USERPWD, libtest_arg3);
+  easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
+  easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
 
-  test_setopt(curl, CURLOPT_INFILESIZE_LARGE,
-                   (curl_off_t)file_info.st_size);
+  easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
 
-  if ((m = curl_multi_init()) == NULL) {
-    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);
-  test_multi_setopt(m, CURLMOPT_TIMERDATA, &timeout);
-
-  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
-    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;
-  }
+  multi_init(m);
+
+  multi_setopt(m, CURLMOPT_SOCKETFUNCTION, curlSocketCallback);
+  multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets);
+
+  multi_setopt(m, CURLMOPT_TIMERFUNCTION, curlTimerCallback);
+  multi_setopt(m, CURLMOPT_TIMERDATA, &timeout);
 
-  ml_timedout = FALSE;
-  ml_start = tutil_tvnow();
+  multi_add_handle(m, curl);
 
   while (!checkForCompletion(m, &success))
   {
@@ -329,12 +307,6 @@ int test(char *URL)
     curl_socket_t maxFd = 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(&writeSet);
     updateFdSet(&sockets.read, &readSet, &maxFd);
@@ -363,6 +335,8 @@ int test(char *URL)
       /* Curl's timer has elapsed. */
       notifyCurl(m, CURL_SOCKET_TIMEOUT, 0, "timeout");
     }
+
+    abort_on_test_timeout();
   }
 
   if (!success)
@@ -370,28 +344,24 @@ int test(char *URL)
     fprintf(stderr, "Error uploading file.\n");
     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:
 
-  if(m)
-    curl_multi_remove_handle(m, curl);
+  /* 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);
-  }
+  curl_multi_cleanup(m);
+  curl_global_cleanup();
 
-  fclose(hd_src); /* close the local file */
-  if (sockets.read.sockets)
+  /* close the local file */
+  fclose(hd_src);
+
+  /* free local memory */
+  if(sockets.read.sockets)
     free(sockets.read.sockets);
-  if (sockets.write.sockets)
+  if(sockets.write.sockets)
     free(sockets.write.sockets);
 
-  curl_global_cleanup();
   return res;
 }
index 6fac67d07d3f315a5781bbdf8f5cd54aaed2d590..ad5a5cea79bde3ad2d74e386a93607968b6d823b 100644 (file)
 int test(char *URL)
 {
   int stillRunning;
-  CURLM* multiHandle;
-  CURL* curl;
-  int res1 = 0;
-  int res;
-
-  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
-    fprintf(stderr, "curl_global_init() failed\n");
-    return TEST_ERR_MAJOR_BAD;
-  }
-
-  if((multiHandle = curl_multi_init()) == NULL) {
-    fprintf(stderr, "curl_multi_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
-
-  if((curl = curl_easy_init()) == NULL) {
-    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);
-  test_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
-  test_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
-
-  test_setopt(curl, CURLOPT_UPLOAD, 1);
-  test_setopt(curl, CURLOPT_VERBOSE, 1);
-
-  test_setopt(curl, CURLOPT_URL, URL);
-  test_setopt(curl, CURLOPT_INFILESIZE, (long)5);
-
-  if((res = (int)curl_multi_add_handle(multiHandle, curl)) != CURLM_OK) {
-    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;
-  }
+  CURLM* multiHandle = NULL;
+  CURL* curl = NULL;
+  int res = 0;
+
+  global_init(CURL_GLOBAL_ALL);
+
+  multi_init(multiHandle);
+
+  easy_init(curl);
+
+  easy_setopt(curl, CURLOPT_USERPWD, libtest_arg2);
+  easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
+  easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
+
+  easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+  easy_setopt(curl, CURLOPT_URL, URL);
+  easy_setopt(curl, CURLOPT_INFILESIZE, (long)5);
+
+  multi_add_handle(multiHandle, curl);
 
   /* this tests if removing an easy handle immediately after multi
      perform has been called succeeds or not. */
 
   fprintf(stderr, "curl_multi_perform()...\n");
-  res1 = (int) curl_multi_perform(multiHandle, &stillRunning);
-  if(res1)
-    fprintf(stderr, "curl_multi_perform() failed, "
-            "with code %d\n", res1);
-  else
-    fprintf(stderr, "curl_multi_perform() succeeded\n");
+
+  multi_perform(multiHandle, &stillRunning);
+
+  fprintf(stderr, "curl_multi_perform() succeeded\n");
 
   fprintf(stderr, "curl_multi_remove_handle()...\n");
   res = (int) curl_multi_remove_handle(multiHandle, curl);
@@ -96,12 +74,11 @@ int test(char *URL)
 
 test_cleanup:
 
+  /* undocumented cleanup sequence - type UB */
+
   curl_easy_cleanup(curl);
   curl_multi_cleanup(multiHandle);
   curl_global_cleanup();
 
-  if(res)
-    return res;
-  else
-    return res1;
+  return res;
 }
index 046b5504e44fbad7aaae3128a557e8626a454ca0..81c435d1fba7090b2b57c1422494c2fec5676034 100644 (file)
@@ -50,9 +50,6 @@
 #  include "select.h"
 #endif
 
-#define TEST_ERR_MAJOR_BAD     100
-#define TEST_ERR_RUNS_FOREVER   99
-
 #define test_setopt(A,B,C) \
   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 char **test_argv;
 
-extern int select_test(int num_fds, fd_set *rd, fd_set *wr, fd_set *exc,
-                       struct timeval *tv);
+extern struct timeval tv_test_start; /* for test timing */
+
+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
                                individual libXXX.c file */
@@ -75,3 +74,331 @@ extern int test(char *URL); /* the actual test function provided by each
 #ifdef UNITTESTS
 extern int unitfail;
 #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__))
+
+/* ---------------------------------------------------------------- */