Commit 629d2e34 authored by Yang Tse's avatar Yang Tse
Browse files

multi tests: OOM handling fixes

Additionally, improved error checking and logging.
parent 90fcad63
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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>
+2 −3
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
@@ -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)

+14 −6
Original line number Diff line number Diff line
@@ -30,19 +30,25 @@
#  include "memdebug.h"
#endif

int select_test (int num_fds, fd_set *rd, fd_set *wr, fd_set *exc,
int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
                   struct timeval *tv)
{
  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
+33 −67
Original line number Diff line number Diff line
@@ -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().
@@ -34,90 +33,57 @@

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;
    int maxfd = -99;

    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;
    }
    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. */
    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);

    if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) {
      res = ~CURLM_OK;
      break;
    }
  }
    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

  if (mp_timedout) {
    fprintf(stderr, "mp_timedout\nABORTING TEST, since it seems "
            "that it would have run forever.\n");
    res = TEST_ERR_RUNS_FOREVER;
    abort_on_test_timeout();
  }

test_cleanup:

  if(m) {
  /* proper cleanup sequence - type PA */

  curl_multi_remove_handle(m, c);
  curl_multi_cleanup(m);
  }
  curl_easy_cleanup(c);
  curl_global_cleanup();

Loading