Update libtest/associated tests.
authorBrian Aker <brian@tangent.org>
Fri, 17 Feb 2012 02:39:27 +0000 (18:39 -0800)
committerBrian Aker <brian@tangent.org>
Fri, 17 Feb 2012 02:39:27 +0000 (18:39 -0800)
48 files changed:
clients/memcapable.cc
clients/memcat.cc
clients/memerror.cc
configure.ac
libtest/binaries.cc
libtest/blobslap_worker.cc
libtest/cmdline.cc
libtest/cmdline.h
libtest/comparison.hpp
libtest/dream.cc [new file with mode: 0644]
libtest/dream.h [new file with mode: 0644]
libtest/gearmand.cc
libtest/has.cc [new file with mode: 0644]
libtest/has.hpp [new file with mode: 0644]
libtest/http.cc [new file with mode: 0644]
libtest/http.hpp [new file with mode: 0644]
libtest/include.am
libtest/libtool.cc
libtest/memcached.cc
libtest/server.cc
libtest/server.h
libtest/server_container.cc
libtest/signal.cc
libtest/signal.h
libtest/skiptest.cc
libtest/string.hpp
libtest/test.cc
libtest/test.h
libtest/test.hpp
libtest/unittest.cc
libtest/vchar.cc [new file with mode: 0644]
libtest/vchar.hpp [new file with mode: 0644]
libtest/wait.cc
tests/cli.am
tests/libmemcached-1.0/mem_functions.cc
tests/memcapable.cc
tests/memcat.cc
tests/memcp.cc
tests/memdump.cc
tests/memerror.cc
tests/memflush.cc
tests/memrm.cc
tests/memslap.cc
util/daemon.cc
util/instance.cc
util/operation.cc
util/signal.hpp
util/string.hpp

index 9bd310c524dd563c482ecaa3f7a200c8c8de3637..bc3b551f412810d73fb9d7410d15bd5dcdfee7ad 100644 (file)
@@ -244,10 +244,14 @@ static enum test_return ensure(bool val, const char *expression, const char *fil
   if (!val)
   {
     if (verbose)
+    {
       fprintf(stderr, "\n%s:%d: %s", file, line, expression);
+    }
 
     if (do_core)
+    {
       abort();
+    }
 
     return TEST_FAIL;
   }
@@ -271,9 +275,14 @@ static enum test_return retry_write(const void* buf, size_t len)
     size_t num_bytes= len - offset;
     ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes);
     if (nw == -1)
+    {
       verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
+    }
     else
+    {
       offset+= (size_t)nw;
+    }
+
   } while (offset < len);
 
   return TEST_PASS;
@@ -286,7 +295,7 @@ static enum test_return retry_write(const void* buf, size_t len)
 static enum test_return resend_packet(command *cmd)
 {
   size_t length= sizeof (protocol_binary_request_no_extras) +
-          ntohl(cmd->plain.message.header.request.bodylen);
+    ntohl(cmd->plain.message.header.request.bodylen);
 
   execute(retry_write(cmd, length));
   return TEST_PASS;
@@ -324,8 +333,10 @@ static enum test_return retry_read(void *buf, size_t len)
        fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno));
       verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
       break;
+
     case 0:
       return TEST_FAIL;
+
     default:
       offset+= (size_t)nr;
     }
@@ -669,9 +680,13 @@ static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
   for (int ii= 0; ii < 10; ii++)
   {
     if (ii == 0)
+    {
       execute(send_packet(&cmd));
+    }
     else
+    {
       execute(resend_packet(&cmd));
+    }
 
     if (cc == PROTOCOL_BINARY_CMD_SET)
     {
@@ -799,17 +814,25 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
   for (int ii= 0; ii < 10; ii++)
   {
     if (ii == 0)
+    {
       execute(send_packet(&cmd));
+    }
     else
+    {
       execute(resend_packet(&cmd));
+    }
 
     if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0)
     {
       uint16_t expected_result;
       if (ii == 0)
+      {
         expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT;
+      }
       else
+      {
         expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS;
+      }
 
       execute(send_binary_noop());
       execute(recv_packet(&rsp));
@@ -820,7 +843,9 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
         execute(binary_set_item(key, key));
     }
     else
+    {
       execute(test_binary_noop());
+    }
   }
 
   /* verify that replace with CAS value works! */
@@ -1094,16 +1119,24 @@ static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
   const char *value;
 
   if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
+  {
     value="hello";
+  }
   else
+  {
     value=" world";
+  }
 
   execute(binary_set_item(key, value));
 
   if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
+  {
     value=" world";
+  }
   else
+  {
     value="hello";
+  }
 
   raw_command(&cmd, cc, key, strlen(key), value, strlen(value));
   execute(send_packet(&cmd));
@@ -1113,7 +1146,9 @@ static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
     verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
   }
   else
+  {
     execute(test_binary_noop());
+  }
 
   raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
   execute(send_packet(&cmd));
@@ -1285,7 +1320,9 @@ static enum test_return test_ascii_set_impl(const char* key, bool noreply)
   execute(send_string(buffer));
 
   if (!noreply)
+  {
     execute(receive_response("STORED\r\n"));
+  }
 
   return test_ascii_version();
 }
@@ -1308,12 +1345,16 @@ static enum test_return test_ascii_add_impl(const char* key, bool noreply)
   execute(send_string(buffer));
 
   if (!noreply)
+  {
     execute(receive_response("STORED\r\n"));
+  }
 
   execute(send_string(buffer));
 
   if (!noreply)
+  {
     execute(receive_response("NOT_STORED\r\n"));
+  }
 
   return test_ascii_version();
 }
@@ -1408,14 +1449,18 @@ static enum test_return ascii_get_item(const char *key, const char *value,
   char buffer[1024];
   size_t datasize= 0;
   if (value != NULL)
+  {
     datasize= strlen(value);
+  }
 
   verify(datasize < sizeof(buffer));
   snprintf(buffer, sizeof(buffer), "get %s\r\n", key);
   execute(send_string(buffer));
 
   if (exist)
+  {
     execute(ascii_get_value(key, value));
+  }
 
   execute(retry_read(buffer, 5));
   verify(memcmp(buffer, "END\r\n", 5) == 0);
@@ -1471,7 +1516,9 @@ static enum test_return ascii_gets_item(const char *key, const char *value,
   char buffer[1024];
   size_t datasize= 0;
   if (value != NULL)
+  {
     datasize= strlen(value);
+  }
 
   verify(datasize < sizeof(buffer));
   snprintf(buffer, sizeof(buffer), "gets %s\r\n", key);
@@ -1505,9 +1552,13 @@ static enum test_return test_ascii_replace_impl(const char* key, bool noreply)
   execute(send_string(buffer));
 
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
+  {
     execute(receive_response("NOT_STORED\r\n"));
+  }
 
   execute(ascii_set_item(key, "value"));
   execute(ascii_get_item(key, "value", true));
@@ -1545,17 +1596,25 @@ static enum test_return test_ascii_cas_impl(const char* key, bool noreply)
   execute(send_string(buffer));
 
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
+  {
     execute(receive_response("STORED\r\n"));
+  }
 
   /* reexecute the same command should fail due to illegal cas */
   execute(send_string(buffer));
 
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
+  {
     execute(receive_response("EXISTS\r\n"));
+  }
 
   return test_ascii_version();
 }
@@ -1647,7 +1706,9 @@ static enum test_return test_ascii_mget(void)
   };
 
   for (uint32_t x= 0; x < nkeys; ++x)
+  {
     execute(ascii_set_item(keys[x], "value"));
+  }
 
   /* Ask for a key that doesn't exist as well */
   execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 "
@@ -1686,7 +1747,9 @@ static enum test_return test_ascii_mget(void)
   }
 
   for (uint32_t x= 0; x < nkeys; ++x)
+  {
     free(returned[x]);
+  }
 
   return TEST_PASS;
 }
@@ -1738,7 +1801,9 @@ static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
     execute(send_string(cmd));
 
     if (noreply)
+    {
       execute(test_ascii_version());
+    }
     else
     {
       char buffer[80];
@@ -1753,7 +1818,9 @@ static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
   /* verify that it doesn't wrap */
   execute(send_string(cmd));
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
   {
     char buffer[80];
@@ -1827,9 +1894,13 @@ static enum test_return test_ascii_concat_impl(const char *key,
   execute(ascii_set_item(key, value));
 
   if (append)
+  {
     value=" world";
+  }
   else
+  {
     value="hello";
+  }
 
   char cmd[400];
   snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n",
@@ -1839,9 +1910,13 @@ static enum test_return test_ascii_concat_impl(const char *key,
   execute(send_string(cmd));
 
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
+  {
     execute(receive_response("STORED\r\n"));
+  }
 
   execute(ascii_get_item(key, "hello world", true));
 
@@ -1852,9 +1927,13 @@ static enum test_return test_ascii_concat_impl(const char *key,
   execute(send_string(cmd));
 
   if (noreply)
+  {
     execute(test_ascii_version());
+  }
   else
+  {
     execute(receive_response("NOT_STORED\r\n"));
+  }
 
   return TEST_PASS;
 }
@@ -2038,7 +2117,7 @@ int main(int argc, char **argv)
               "\t-a\tOnly test the ascii protocol\n"
               "\t-b\tOnly test the binary protocol\n",
               argv[0]);
-      return EXIT_FAILURE;
+      return EXIT_SUCCESS;
     }
   }
 
@@ -2054,7 +2133,9 @@ int main(int argc, char **argv)
   for (int ii= 0; testcases[ii].description != NULL; ++ii)
   {
     if (testname != NULL && strcmp(testcases[ii].description, testname) != 0)
-       continue;
+    {
+      continue;
+    }
 
     if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) ||
         (testcases[ii].description[0] == 'b' && (tests.binary) == 0))
@@ -2078,7 +2159,9 @@ int main(int argc, char **argv)
           continue;
         }
         if (strncmp(buffer, "quit", 4) == 0)
-          exit(0);
+        {
+          exit(EXIT_SUCCESS);
+        }
       }
 
       fprintf(stdout, "%-40s", testcases[ii].description);
@@ -2103,8 +2186,7 @@ int main(int argc, char **argv)
       closesocket(sock);
       if ((sock= connect_server(hostname, port)) == INVALID_SOCKET)
       {
-        fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
-                hostname, port, strerror(get_socket_errno()));
+        fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", hostname, port, strerror(get_socket_errno()));
         fprintf(stderr, "%d of %d tests failed\n", failed, total);
         return EXIT_FAILURE;
       }
@@ -2113,9 +2195,13 @@ int main(int argc, char **argv)
 
   closesocket(sock);
   if (failed == 0)
+  {
     fprintf(stdout, "All tests passed\n");
+  }
   else
+  {
     fprintf(stderr, "%d of %d tests failed\n", failed, total);
+  }
 
-  return (failed == 0) ? 0 : 1;
+  return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index ab482e5d6ad57549b17f06d0352b3b132562f1b4..86ae279c8c671997ef8dbe0ddc19e1df7d6669c0 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
   memcached_return_t rc;
   memcached_server_st *servers;
 
-  int return_code= 0;
+  int return_code= EXIT_SUCCESS;
 
   options_parse(argc, argv);
   initialize_sockets();
@@ -55,11 +55,13 @@ int main(int argc, char *argv[])
     char *temp;
 
     if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
       opt_servers= strdup(temp);
+    }
     else
     {
-      fprintf(stderr, "No Servers provided\n");
-      exit(1);
+      std::cerr << "No servers provied" << std::endl;
+      exit(EXIT_FAILURE);
     }
   }
 
@@ -100,69 +102,66 @@ int main(int argc, char *argv[])
       if (opt_displayflag)
       {
         if (opt_verbose)
-          printf("key: %s\nflags: ", argv[optind]);
-        printf("%x\n", flags);
+        {
+          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << std::endl;
+        }
       }
       else
       {
         if (opt_verbose)
         {
-          printf("key: %s\nflags: %x\nlength: %lu\nvalue: ",
-                 argv[optind], flags, (unsigned long)string_length);
+          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << "length: " << string_length << std::endl << "value: ";
         }
 
         if (opt_file)
         {
-          FILE *fp;
-          size_t written;
-
-          fp= fopen(opt_file, "w");
-          if (!fp)
+          FILE *fp= fopen(opt_file, "w");
+          if (fp == NULL)
           {
             perror("fopen");
-            return_code= -1;
+            return_code= EXIT_FAILURE;
             break;
           }
 
-          written= fwrite(string, 1, string_length, fp);
+          size_t written= fwrite(string, 1, string_length, fp);
           if (written != string_length) 
           {
-            fprintf(stderr, "error writing file (written %lu, should be %lu)\n", (unsigned long)written, (unsigned long)string_length);
-            return_code= -1;
+            std::cerr << "error writing file to file " << opt_file << " wrote " << written << ", should have written" << string_length << std::endl;
+            return_code= EXIT_FAILURE;
             break;
           }
 
           if (fclose(fp))
           {
-            fprintf(stderr, "error closing file\n");
-            return_code= -1;
+            std::cerr << "error closing " << opt_file << std::endl;
+            return_code= EXIT_FAILURE;
             break;
           }
         }
         else
         {
-            printf("%.*s\n", (int)string_length, string);
+          std::cout.write(string, string_length);
+          std::cout << std::endl;
         }
         free(string);
       }
     }
     else if (rc != MEMCACHED_NOTFOUND)
     {
-      fprintf(stderr, "memcat: %s: memcache error %s",
-              argv[optind], memcached_strerror(memc, rc));
+      std::cerr << "error on " << argv[optind] << "(" <<  memcached_strerror(memc, rc) << ")";
       if (memcached_last_error_errno(memc))
       {
-       fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
+        std::cerr << " system error (" << strerror(memcached_last_error_errno(memc)) << ")" << std::endl;
       }
-      fprintf(stderr, "\n");
+      std::cerr << std::endl;
 
-      return_code= -1;
+      return_code= EXIT_FAILURE;
       break;
     }
     else // Unknown Issue
     {
-      fprintf(stderr, "memcat: %s not found\n", argv[optind]);
-      return_code= -1;
+      std::cerr << "error on " << argv[optind] << "("<< memcached_strerror(NULL, rc) << ")" << std::endl;
+      return_code= EXIT_FAILURE;
     }
     optind++;
   }
@@ -170,9 +169,13 @@ int main(int argc, char *argv[])
   memcached_free(memc);
 
   if (opt_servers)
+  {
     free(opt_servers);
+  }
   if (opt_hash)
+  {
     free(opt_hash);
+  }
 
   return return_code;
 }
index fd4238a51eb3dd256fa6530510d9605c12d1aceb..17bc531c96473ed735fb214ae19c1c2ca76c2ac1 100644 (file)
  */
 #include "config.h"
 
-#include <inttypes.h>
+#include <cerrno>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#include <climits>
+
 #include <getopt.h>
 #include <iostream>
 #include <unistd.h>
 /* Prototypes */
 void options_parse(int argc, char *argv[]);
 
-static int opt_verbose= 0;
-
 int main(int argc, char *argv[])
 {
   options_parse(argc, argv);
 
-  if (argc != 2)
+  if (argc < 2)
   {
     return EXIT_FAILURE;
   }
 
-  unsigned long value= strtoul(argv[1], (char **) NULL, 10);
-
-  if (value < MEMCACHED_MAXIMUM_RETURN)
+  while (optind < argc)
   {
-    std::cout << memcached_strerror(NULL, (memcached_return_t)value) << std::endl;
-  }
-  else
-  {
-    std::cerr << memcached_strerror(NULL, MEMCACHED_MAXIMUM_RETURN) << std::endl;
-    return EXIT_FAILURE;
+    errno= 0;
+    char *nptr;
+    unsigned long value= strtoul(argv[optind], &nptr, 10);
+
+    if ((nptr == argv[optind] and value == 0) or
+        (value == ULONG_MAX and errno == ERANGE) or
+        (value == 0 and errno == EINVAL))
+    {
+      std::cerr << "strtoul() was unable to parse given value" << std::endl;
+      return EXIT_FAILURE;
+    }
+
+    if (value < MEMCACHED_MAXIMUM_RETURN)
+    {
+      std::cout << memcached_strerror(NULL, (memcached_return_t)value) << std::endl;
+    }
+    else
+    {
+      std::cerr << memcached_strerror(NULL, MEMCACHED_MAXIMUM_RETURN) << std::endl;
+      return EXIT_FAILURE;
+    }
+
+    optind++;
   }
 
   return EXIT_SUCCESS;
@@ -62,9 +77,6 @@ void options_parse(int argc, char *argv[])
     {
       {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
       {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
       {0, 0, 0, 0},
     };
 
@@ -84,14 +96,6 @@ void options_parse(int argc, char *argv[])
     case 0:
       break;
 
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-
     case OPT_VERSION: /* --version or -V */
       opt_version= true;
       break;
@@ -100,16 +104,12 @@ void options_parse(int argc, char *argv[])
       opt_help= true;
       break;
 
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
     case '?':
       /* getopt_long already printed an error message. */
       exit(EXIT_FAILURE);
 
     default:
-      abort();
+      exit(EXIT_FAILURE);
     }
   }
 
index 217626cd17eff1e6c1b4e93ed420f476c1cf1d30..8bb9a60a37199fb22dcad18e9b6e1e7f1693fd32 100644 (file)
@@ -203,6 +203,12 @@ AS_IF([test "x$ac_cv_header_atomic_h" = "xyes"],[
                      [1],
                       [Define to true if you want to use functions from atomic.h])])])
 
+AC_DEFINE([HAVE_LIBDRIZZLE], [0], [Support for libdrizzle])
+AC_DEFINE([HAVE_DRIZZLED_BINARY], [0], [Support for DrizzleD])
+AC_DEFINE([GEARMAND_BLOBSLAP_WORKER], [0], [Support for Gearman Blobslap worker])
+AC_DEFINE([HAVE_LIBPQ], [0], [Support for Postgres])
+AC_DEFINE([HAVE_LIBCURL], [0], [Support for libcurl])
+
 AC_CHECK_HEADERS_ONCE(winsock2.h poll.h sys/wait.h fnmatch.h)
 AM_CONDITIONAL(BUILD_POLL, test "x$ac_cv_header_poll_h" = "xno")
 AM_CONDITIONAL(BUILD_WIN32_WRAPPERS, test "x$ac_cv_header_winsock2_h" = "xyes")
index 00a897660f5dbc2ae421d4f776467441e9a9b20d..33cde3b74700b4544e5a748e227213d068532189 100644 (file)
@@ -27,7 +27,16 @@ namespace libtest {
 bool has_gearmand_binary()
 {
 #if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
-  if (access(GEARMAND_BINARY,R_OK|X_OK) == 0)
+  std::stringstream arg_buffer;
+
+  if (getenv("PWD"))
+  {
+    arg_buffer << getenv("PWD");
+    arg_buffer << "/";
+  }
+  arg_buffer << GEARMAND_BINARY;
+
+  if (access(arg_buffer.str().c_str() ,R_OK|X_OK) == 0)
   {
     return true;
   }
index 7c7975eda59411d6b55d39b49754f927eb63c8eb..8bbd073857ce8d2bdb1430725e603f6221bdefa5 100644 (file)
@@ -119,7 +119,7 @@ public:
 
   const char *executable()
   {
-    return GEARMAND_BLOBSLAP_WORKER;
+    return "benchmark/blobslap_worker";
   }
 
   const char *pid_file_option()
index 4dc84c9d66990d547f48f40180530c2977b259be..7c2f5f442662748bfabd8e0a70fad4878e08f5bd 100644 (file)
 using namespace libtest;
 
 #include <cstdlib>
-#include <string>
+#include <cstring>
+#include <fcntl.h>
+#include <memory>
+#include <spawn.h>
 #include <sstream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+extern "C" {
+  static int exited_successfully(int status)
+  {
+    if (status == 0)
+    {
+      return EXIT_SUCCESS;
+    }
+
+    if (WIFEXITED(status) == true)
+    {
+      return WEXITSTATUS(status);
+    }
+    else if (WIFSIGNALED(status) == true)
+    {
+      return WTERMSIG(status);
+    }
+
+    return EXIT_FAILURE;
+  }
+}
+
+namespace {
+
+  std::string print_argv(char * * & built_argv, const size_t& argc, const pid_t& pid)
+  {
+    std::stringstream arg_buffer;
+
+    for (size_t x= 0; x < argc; x++)
+    {
+      arg_buffer << built_argv[x] << " ";
+    }
+
+    return arg_buffer.str();
+  }
+
+}
 
 namespace libtest {
 
-bool exec_cmdline(const std::string& executable, const char *args[])
+Application::Application(const std::string& arg, const bool _use_libtool_arg) :
+  _use_libtool(_use_libtool_arg),
+  _argc(0),
+  _exectuble(arg),
+  built_argv(NULL),
+  _pid(-1)
+  { 
+    if (_use_libtool)
+    {
+      if (libtool() == NULL)
+      {
+        throw "libtool requested, but know libtool was found";
+      }
+    }
+
+    if (_use_libtool and getenv("PWD"))
+    {
+      _exectuble_with_path+= getenv("PWD");
+      _exectuble_with_path+= "/";
+    }
+    _exectuble_with_path+= _exectuble;
+  }
+
+Application::~Application()
+{
+  delete_argv();
+}
+
+Application::error_t Application::run(const char *args[])
 {
-  std::stringstream arg_buffer;
+  stdin_fd.reset();
+  stdout_fd.reset();
+  stderr_fd.reset();
+  _stdout_buffer.clear();
+  _stderr_buffer.clear();
 
-  arg_buffer << libtool();
+  posix_spawn_file_actions_t file_actions;
+  posix_spawn_file_actions_init(&file_actions);
 
-  if (getenv("PWD"))
+  stdin_fd.dup_for_spawn(Application::Pipe::READ, file_actions, STDIN_FILENO);
+  stdout_fd.dup_for_spawn(Application::Pipe::WRITE, file_actions, STDOUT_FILENO);
+  stderr_fd.dup_for_spawn(Application::Pipe::WRITE, file_actions, STDERR_FILENO);
+  
+  create_argv(args);
+
+  int spawn_ret;
+  if (_use_libtool)
   {
-    arg_buffer << getenv("PWD");
-    arg_buffer << "/";
+    spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL);
   }
+  else
+  {
+    spawn_ret= posix_spawnp(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL);
+  }
+
+  posix_spawn_file_actions_destroy(&file_actions);
 
-  arg_buffer << executable;
-  for (const char **ptr= args; *ptr; ++ptr)
+  stdin_fd.close(Application::Pipe::READ);
+  stdout_fd.close(Application::Pipe::WRITE);
+  stderr_fd.close(Application::Pipe::WRITE);
+
+  if (spawn_ret)
   {
-    arg_buffer << " " << *ptr;
+    Error << print();
+    return Application::INVALID;
   }
 
+  return Application::SUCCESS;
+}
+
+Application::error_t Application::wait()
+{
+  if (_pid == -1)
+  {
+    Error << "wait() got an invalid pid_t";
+    return Application::INVALID;
+  }
+
+  {
+    ssize_t read_length;
+    char buffer[1024]= { 0 };
+    bool bail= false;
+    while (((read_length= ::read(stdout_fd.fd()[0], buffer, sizeof(buffer))) != 0) or bail)
+    {
+      if (read_length == -1)
+      {
+        switch(errno)
+        {
+        case EAGAIN:
+          continue;
+
+        default:
+          Error << strerror(errno);
+          bail= true;
+        }
+      }
+      _stdout_buffer.reserve(read_length +1);
+      for (size_t x= 0; x < read_length; x++)
+      {
+        _stdout_buffer.push_back(buffer[x]);
+      }
+      // @todo Suck up all output code here
+    }
+  }
+
+  {
+    ssize_t read_length;
+    char buffer[1024]= { 0 };
+    bool bail= false;
+    while (((read_length= ::read(stderr_fd.fd()[0], buffer, sizeof(buffer))) != 0) or bail)
+    {
+      if (read_length == -1)
+      {
+        switch(errno)
+        {
+        case EAGAIN:
+          continue;
+
+        default:
+          Error << strerror(errno);
+          bail= true;
+        }
+      }
+      _stderr_buffer.reserve(read_length +1);
+      for (size_t x= 0; x < read_length; x++)
+      {
+        _stderr_buffer.push_back(buffer[x]);
+      }
+      // @todo Suck up all errput code here
+    }
+  }
+
+  error_t exit_code= FAILURE;
+  {
+    int status= 0;
+    pid_t waited_pid;
+    if ((waited_pid= waitpid(_pid, &status, 0)) == -1)
+    {
+      Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(_pid);
+    }
+    else
+    {
+      assert(waited_pid == _pid);
+      exit_code= error_t(exited_successfully(status));
+    }
+  }
+
+  if (exit_code == Application::INVALID)
+  {
 #if 0
-    arg_buffer << " > /dev/null 2>&1";
+    Error << print_argv(built_argv, _argc, _pid);
 #endif
+  }
+
+  return exit_code;
+}
+
+void Application::add_option(const std::string& arg)
+{
+  _options.push_back(std::make_pair(arg, std::string()));
+}
+
+void Application::add_option(const std::string& name, const std::string& value)
+{
+  _options.push_back(std::make_pair(name, value));
+}
+
+Application::Pipe::Pipe()
+{
+  _fd[0]= -1;
+  _fd[1]= -1;
+  _open[0]= false;
+  _open[1]= false;
+}
+
+void Application::Pipe::reset()
+{
+  close(READ);
+  close(WRITE);
+
+  int ret;
+  if ((ret= pipe(_fd)) < 0)
+  {
+    throw strerror(ret);
+  }
+  _open[0]= true;
+  _open[1]= true;
+
+  {
+    ret= fcntl(_fd[0], F_GETFL, 0);
+    if (ret == -1)
+    {
+      Error << "fcntl(F_GETFL) " << strerror(ret);
+      throw strerror(ret);
+    }
+
+    ret= fcntl(_fd[0], F_SETFL, ret | O_NONBLOCK);
+    if (ret == -1)
+    {
+      Error << "fcntl(F_SETFL) " << strerror(ret);
+      throw strerror(ret);
+    }
+  }
+}
+
+Application::Pipe::~Pipe()
+{
+  close(READ);
+  close(WRITE);
+}
+
+void Application::Pipe::dup_for_spawn(const close_t& arg, posix_spawn_file_actions_t& file_actions, const int newfildes)
+{
+  int type= int(arg);
+
+  int ret;
+  if ((ret= posix_spawn_file_actions_adddup2(&file_actions, _fd[type], newfildes )) < 0)
+  {
+    Error << "posix_spawn_file_actions_adddup2(" << strerror(ret) << ")";
+    throw strerror(ret);
+  }
+
+  if ((ret= posix_spawn_file_actions_addclose(&file_actions, _fd[type])) < 0)
+  {
+    Error << "posix_spawn_file_actions_adddup2(" << strerror(ret) << ")";
+    throw strerror(ret);
+  }
+}
+
+void Application::Pipe::close(const close_t& arg)
+{
+  int type= int(arg);
+
+  if (_open[type])
+  {
+    int ret;
+    if ((ret= ::close(_fd[type])) < 0)
+    {
+      Error << "close(" << strerror(ret) << ")";
+    }
+    _open[type]= false;
+  }
+}
+
+void Application::create_argv(const char *args[])
+{
+  _argc= 2 +_use_libtool ? 2 : 0; // +1 for the command, +2 for libtool/mode=execute, +1 for the NULL
+
+  if (_use_libtool)
+  {
+    _argc+= 2; // +2 for libtool --mode=execute
+  }
+
+  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); iter++)
+  {
+    _argc++;
+    if ((*iter).second.empty() == false)
+    {
+      _argc++;
+    }
+  }
+
+  if (args)
+  {
+    for (const char **ptr= args; *ptr; ++ptr)
+    {
+      _argc++;
+    }
+  }
+
+  delete_argv();
+  built_argv= new char * [_argc];
+
+  size_t x= 0;
+  if (_use_libtool)
+  {
+    assert(libtool());
+    built_argv[x++]= strdup(libtool());
+    built_argv[x++]= strdup("--mode=execute");
+  }
+  built_argv[x++]= strdup(_exectuble_with_path.c_str());
+
+  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); iter++)
+  {
+    built_argv[x++]= strdup((*iter).first.c_str());
+    if ((*iter).second.empty() == false)
+    {
+      built_argv[x++]= strdup((*iter).second.c_str());
+    }
+  }
+
+  if (args)
+  {
+    for (const char **ptr= args; *ptr; ++ptr)
+    {
+      built_argv[x++]= strdup(*ptr);
+    }
+  }
+  built_argv[_argc -1]= NULL;
+}
+
+std::string Application::print()
+{
+  return print_argv(built_argv, _argc, _pid);
+}
+
+void Application::delete_argv()
+{
+  if (built_argv == NULL)
+  {
+    return;
+  }
+
+  for (size_t x= 0; x < _argc; x++)
+  {
+    if (built_argv[x])
+    {
+      ::free(built_argv[x]);
+    }
+  }
+  delete[] built_argv;
+  built_argv= NULL;
+  _argc= 0;
+}
+
+
+int exec_cmdline(const std::string& command, const char *args[], bool use_libtool)
+{
+  Application app(command, use_libtool);
+
+  Application::error_t ret= app.run(args);
 
-  if (system(arg_buffer.str().c_str()) == -1)
+  if (ret != Application::SUCCESS)
   {
-    return false;
+    return int(ret);
   }
+  ret= app.wait();
 
-  return true;
+  return int(ret);
 }
 
 const char *gearmand_binary() 
index dcb4b0ab2b78b0ccea3fdb96e2c84d82ddb3e5af..d1019d548a6b65a98d54bd495e929e8e274a3553 100644 (file)
 
 #pragma once
 
+#include <spawn.h>
+
 namespace libtest {
 
-bool exec_cmdline(const std::string& executable, const char *args[]);
+class Application {
+private:
+  typedef std::vector< std::pair<std::string, std::string> > Options;
+
+public:
+
+  enum error_t {
+    SUCCESS= EXIT_SUCCESS,
+    FAILURE= EXIT_FAILURE,
+    INVALID= 127
+  };
+
+  class Pipe {
+  public:
+    Pipe();
+    ~Pipe();
+
+    int* fd()
+    {
+      return _fd;
+    }
+
+    enum close_t {
+      READ,
+      WRITE
+    };
+
+    void reset();
+    void close(const close_t& arg);
+    void dup_for_spawn(const close_t& arg,
+                       posix_spawn_file_actions_t& file_actions,
+                       const int newfildes);
+
+  private:
+    int _fd[2];
+    bool _open[2];
+  };
+
+public:
+  Application(const std::string& arg, const bool _use_libtool_arg= false);
+
+  virtual ~Application();
+
+  void add_option(const std::string&);
+  void add_option(const std::string&, const std::string&);
+  error_t run(const char *args[]= NULL);
+  error_t wait();
+
+  libtest::vchar_t stdout_result() const
+  {
+    return _stdout_buffer;
+  }
+
+  size_t stdout_result_length() const
+  {
+    return _stdout_buffer.size();
+  }
+
+  libtest::vchar_t stderr_result() const
+  {
+    return _stderr_buffer;
+  }
+
+  size_t stderr_result_length() const
+  {
+    return _stderr_buffer.size();
+  }
+
+  std::string print();
+
+private:
+  void create_argv(const char *args[]);
+  void delete_argv();
+
+private:
+  const bool _use_libtool;
+  size_t _argc;
+  std::string _exectuble;
+  std::string _exectuble_with_path;
+  Options _options;
+  Pipe stdin_fd;
+  Pipe stdout_fd;
+  Pipe stderr_fd;
+  char * * built_argv;
+  pid_t _pid;
+  libtest::vchar_t _stdout_buffer;
+  libtest::vchar_t _stderr_buffer;
+};
+
+static inline std::ostream& operator<<(std::ostream& output, const enum Application::error_t &arg)
+{
+  switch (arg)
+  {
+    case Application::SUCCESS:
+      output << "EXIT_SUCCESS";
+      break;
+
+    case Application::FAILURE:
+      output << "EXIT_FAILURE";
+      break;
+
+    case Application::INVALID:
+      output << "127";
+      break;
+  }
+
+  return output;
+}
+
+int exec_cmdline(const std::string& executable, const char *args[], bool use_libtool= false);
 
 const char *gearmand_binary(); 
 
index 33cfa5a5b095a77ea43f969b6ceedbd87ba51240..bcb7558e61cd907da977208989fa4185cd02fff5 100644 (file)
@@ -29,7 +29,7 @@
 #endif
 
 #if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN
-#include <libgearman/gearman.h>
+#include <libgearman-1.0/ostream.hpp>
 #endif
 
 namespace libtest {
diff --git a/libtest/dream.cc b/libtest/dream.cc
new file mode 100644 (file)
index 0000000..32dece3
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <libtest/common.h>
+
+namespace libtest {
+
+void dream(time_t tv_sec, long tv_nsec)
+{
+#ifdef WIN32
+  if (tv_sec == 0 and tv_nsec)
+  {
+    tv_sec++;
+  }
+  sleep(tv_sec);
+#else
+  struct timespec requested;
+  requested.tv_sec= tv_sec;
+  requested.tv_nsec= tv_nsec;
+  nanosleep(&requested, NULL);
+#endif
+}
+
+}
diff --git a/libtest/dream.h b/libtest/dream.h
new file mode 100644 (file)
index 0000000..e702aa6
--- /dev/null
@@ -0,0 +1,29 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#pragma once
+
+namespace libtest {
+
+void dream(time_t tv_sec, long tv_nsec= 0);
+
+}
+
index deac09f3562cd2754b63e049fb9ff4d93cce56f8..bcb7f8aaba2d7bcd7d033d4bf534b14b5ece03d2 100644 (file)
@@ -96,7 +96,7 @@ public:
 
   pid_t get_pid(bool error_is_ok)
   {
-    if (not pid_file().empty())
+    if (pid_file().empty() == false)
     {
       Wait wait(pid_file(), 0);
 
@@ -124,12 +124,12 @@ public:
   bool ping()
   {
     gearman_client_st *client= gearman_client_create(NULL);
-    if (not client)
+    if (client == NULL)
     {
       Error << "Could not allocate memory for gearman_client_create()";
       return false;
     }
-    gearman_client_set_timeout(client, 1000);
+    gearman_client_set_timeout(client, 3000);
 
     if (gearman_success(gearman_client_add_server(client, hostname().c_str(), port())))
     {
@@ -140,6 +140,13 @@ public:
         gearman_client_free(client);
         return true;
       }
+#if 0
+      Error << hostname().c_str() << ":" << port() << " was " << gearman_strerror(rc) << " extended: " << gearman_client_error(client);
+#endif
+    }
+    else
+    {
+      Error << "gearman_client_add_server() " << gearman_client_error(client);
     }
 
     gearman_client_free(client);
@@ -169,7 +176,7 @@ public:
 
   const char *log_file_option()
   {
-    return "-vvvvv --log-file=";
+    return "--verbose=DEBUG --log-file=";
   }
 
   const char *port_option()
@@ -182,6 +189,11 @@ public:
     return true;
   }
 
+  bool has_syslog() const
+  {
+    return true;
+  }
+
   bool build(int argc, const char *argv[]);
 };
 
@@ -194,7 +206,7 @@ bool Gearmand::build(int argc, const char *argv[])
     arg_buffer << " -u root ";
   }
 
-  arg_buffer << " --listen=127.0.0.1 ";
+  arg_buffer << " --listen=localhost ";
 
   for (int x= 1 ; x < argc ; x++)
   {
diff --git a/libtest/has.cc b/libtest/has.cc
new file mode 100644 (file)
index 0000000..e7376c2
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <config.h>
+#include <libtest/has.hpp>
+
+#include <cstdlib>
+
+bool has_memcached_support(void)
+{
+  if (HAVE_LIBMEMCACHED and HAVE_MEMCACHED_BINARY)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool has_drizzle_support(void)
+{
+  if (HAVE_LIBDRIZZLE and HAVE_DRIZZLED_BINARY)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool has_postgres_support(void)
+{
+  if (getenv("POSTGES_IS_RUNNING_AND_SETUP"))
+  {
+
+    if (HAVE_LIBPQ)
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
diff --git a/libtest/has.hpp b/libtest/has.hpp
new file mode 100644 (file)
index 0000000..e1b598f
--- /dev/null
@@ -0,0 +1,28 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#pragma once
+
+bool has_memcached_support(void);
+
+bool has_drizzle_support(void);
+
+bool has_postgres_support(void);
diff --git a/libtest/http.cc b/libtest/http.cc
new file mode 100644 (file)
index 0000000..5309d50
--- /dev/null
@@ -0,0 +1,157 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <libtest/common.h>
+
+#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
+#include <curl/curl.h>
+#else
+class CURL;
+#endif
+
+namespace libtest {
+namespace http {
+
+#define YATL_USERAGENT "YATL/1.0"
+
+extern "C" size_t
+  http_get_result_callback(void *ptr, size_t size, size_t nmemb, void *data)
+  {
+    size_t body_size= size * nmemb;
+
+    vchar_t *_body= (vchar_t*)data;
+
+    _body->resize(size * nmemb);
+    memcpy(&_body[0], ptr, _body->size());
+
+    return _body->size();
+  }
+
+
+static void init(CURL *curl, const std::string& url)
+{
+  if (HAVE_LIBCURL)
+  {
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+    assert(curl);
+    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+    curl_easy_setopt(curl, CURLOPT_USERAGENT, YATL_USERAGENT);
+#endif
+  }
+}
+
+bool GET::execute()
+{
+  if (HAVE_LIBCURL)
+  {
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+    CURL *curl= curl_easy_init();
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return retref == CURLE_OK;
+#endif
+  }
+
+  return false;
+}
+
+bool POST::execute()
+{
+  if (HAVE_LIBCURL)
+  {
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+    CURL *curl= curl_easy_init();;
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, _body.size());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)&_body[0]);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+#endif
+  }
+
+  return false;
+}
+
+bool TRACE::execute()
+{
+  if (HAVE_LIBCURL)
+  {
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+    CURL *curl= curl_easy_init();;
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "TRACE");
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body[0]);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return retref == CURLE_OK;
+#endif
+  }
+
+  return false;
+}
+
+bool HEAD::execute()
+{
+  if (HAVE_LIBCURL)
+  {
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+    CURL *curl= curl_easy_init();;
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return retref == CURLE_OK;
+#endif
+  }
+
+  return false;
+}
+
+} // namespace http
+} // namespace libtest
diff --git a/libtest/http.hpp b/libtest/http.hpp
new file mode 100644 (file)
index 0000000..012d7a0
--- /dev/null
@@ -0,0 +1,119 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#pragma once
+
+namespace libtest {
+namespace http {
+
+class HTTP {
+public:
+
+  HTTP(const std::string& url_arg) :
+    _url(url_arg),
+    _response(0)
+  { }
+
+  virtual bool execute()= 0;
+
+  virtual ~HTTP()
+  { }
+
+  const std::string& url() const
+  {
+    return _url;
+  }
+
+  long response()
+  {
+    return _response;
+  }
+
+private:
+  std::string _url;
+
+protected:
+  long _response;
+};
+
+class GET: public HTTP {
+public:
+
+  GET(const std::string& url_arg) :
+    HTTP(url_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _body;
+};
+
+class POST: public HTTP {
+public:
+
+  POST(const std::string& url_arg,
+       const vchar_t& post_arg) :
+    HTTP(url_arg),
+    _post(post_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _post;
+  libtest::vchar_t _body;
+};
+
+class TRACE: public HTTP {
+public:
+
+  TRACE(const std::string& url_arg,
+        const vchar_t& body_arg) :
+    HTTP(url_arg),
+    _body(body_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _body;
+};
+
+class HEAD: public HTTP {
+public:
+
+  HEAD(const std::string& url_arg) :
+    HTTP(url_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+};
+
+} // namespace http
+} // namespace libtest
index a668d69034104ff495efd2243f20df511b88d0d4..0ad8da4f6c4d20875a465b67379818beb57b0f64 100644 (file)
@@ -64,11 +64,14 @@ noinst_HEADERS+= \
                 libtest/common.h \
                 libtest/comparison.hpp \
                 libtest/core.h \
+                libtest/dream.h \
                 libtest/error.h \
                 libtest/failed.h \
                 libtest/framework.h \
                 libtest/gearmand.h \
                 libtest/get.h \
+                libtest/has.hpp \
+                libtest/http.hpp \
                 libtest/is_pid.hpp \
                 libtest/is_local.hpp \
                 libtest/killpid.h \
@@ -86,6 +89,7 @@ noinst_HEADERS+= \
                 libtest/string.hpp \
                 libtest/test.h \
                 libtest/test.hpp \
+                libtest/vchar.hpp \
                 libtest/visibility.h \
                 libtest/wait.h
 
@@ -94,7 +98,10 @@ libtest_libtest_la_SOURCES= \
                            libtest/binaries.cc \
                            libtest/cmdline.cc \
                            libtest/core.cc \
+                           libtest/dream.cc \
                            libtest/framework.cc \
+                           libtest/has.cc \
+                           libtest/http.cc \
                            libtest/is_local.cc \
                            libtest/killpid.cc \
                            libtest/libtool.cc \
@@ -105,15 +112,18 @@ libtest_libtest_la_SOURCES= \
                            libtest/signal.cc \
                            libtest/socket.cc \
                            libtest/strerror.cc \
-                           libtest/test.cc
+                           libtest/test.cc \
+                           libtest/vchar.cc
 
-libtest_libtest_la_CXXFLAGS= ${AM_CXXFLAGS}
+libtest_libtest_la_CXXFLAGS=
 libtest_libtest_la_CXXFLAGS+= ${NO_CONVERSION}
 libtest_libtest_la_CXXFLAGS+= -DBUILDING_LIBTEST
 libtest_libtest_la_CXXFLAGS+= $(PTHREAD_CFLAGS)
 libtest_libtest_la_CXXFLAGS+= -DLIBTEST_TEMP="\"tmp_chroot\""
+libtest_libtest_la_CXXFLAGS+= $(CURL_CFLAGS)
 libtest_libtest_la_LIBADD=
 libtest_libtest_la_LIBADD+= $(PTHREAD_LIBS)
+libtest_libtest_la_LIBADD+= $(CURL_LIBS)
 libtest_libtest_la_DEPENDENCIES= libtest_tmp_dir
 
 # Declare unittest so that we can append to it
@@ -152,10 +162,10 @@ libtest_libtest_la_SOURCES+= libtest/blobslap_worker.cc
 libtest_libtest_la_SOURCES+= libtest/gearmand.cc
 libtest_libtest_la_SOURCES+= util/instance.cc
 libtest_libtest_la_SOURCES+= util/operation.cc
-libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BLOBSLAP_WORKER="\"${abs_top_builddir}/benchmark/blobslap_worker\""
 
 libtest_unittest_LDADD+= libgearman/libgearman.la
 libtest_unittest_DEPENDENCIES+= libgearman/libgearman.la
+libtest_unittest_DEPENDENCIES+= gearmand/gearmand
 else
 if HAVE_LIBGEARMAN
 libtest_libtest_la_DEPENDENCIES+= libgearman/libgearman.la
@@ -164,9 +174,6 @@ libtest_libtest_la_SOURCES+= libtest/blobslap_worker.cc
 libtest_libtest_la_SOURCES+= libtest/gearmand.cc
 libtest_libtest_la_SOURCES+= util/instance.cc
 libtest_libtest_la_SOURCES+= util/operation.cc
-libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BLOBSLAP_WORKER=0
-else
-libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BLOBSLAP_WORKER=0
 endif
 endif
 
@@ -188,7 +195,6 @@ tmp_chroot/var/run: tmp_chroot/var
        @$(mkdir_p) tmp_chroot/var/run
 
 
-libtest_unittest_CXXFLAGS+= ${AM_CXXFLAGS}
 libtest_unittest_DEPENDENCIES+= libtest/libtest.la libtest_tmp_dir
 libtest_unittest_LDADD+= libtest/libtest.la
 libtest_unittest_SOURCES= libtest/unittest.cc
index c7aa29d7c818691280fedca09db2e0de3e869f9a..90f0035e5a5ffdd9ff62a05c079f6a245e9102f2 100644 (file)
@@ -28,12 +28,12 @@ namespace libtest {
 
 const char *libtool(void)
 {
-  if (_libtool[0])
+  if (_libtool[0] == 0)
   {
     std::string libtool_buffer;
-    if (getenv("srcdir"))
+    if (getenv("PWD"))
     {
-      libtool_buffer+= getenv("srcdir");
+      libtool_buffer+= getenv("PWD");
       libtool_buffer+= "/";
     }
     else
@@ -44,15 +44,14 @@ const char *libtool(void)
     libtool_buffer+= "libtool";
     if (access(libtool_buffer.c_str(), R_OK | W_OK | X_OK))
     {
+      Error << "Could not find libtool via access(" << libtool_buffer << ") :" << strerror(errno);
       return NULL;
     }
 
-    libtool_buffer+= " --mode=execute ";
-
     snprintf(_libtool, sizeof(_libtool), "%s", libtool_buffer.c_str());
   }
 
   return _libtool;
 }
 
-}
+} // namespace libtest
index fc7a37c693bafa2a1af53405d017a89b4c315a81..7d25153fb078c783734bdaa314ce4862f1f51b70 100644 (file)
@@ -22,8 +22,8 @@
 
 #include <libtest/common.h>
 
-#include <libmemcached/memcached.h>
-#include <libmemcached/util.h>
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/util.h>
 
 using namespace libtest;
 
index 8b8b8f3e98776eef0a11a8fd18cd35280a9fbdcc..9d492b9b84aa1d902f6e8a30a8cddee6fbf6062d 100644 (file)
@@ -43,14 +43,37 @@ static inline std::string &rtrim(std::string &s)
 #include <libtest/killpid.h>
 
 extern "C" {
-  static bool exited_successfully(int status)
+  static bool exited_successfully(int status, const std::string &command)
   {
-    if (WEXITSTATUS(status) == 0)
+    if (status == 0)
     {
       return true;
     }
 
-    return true;
+    if (WIFEXITED(status) == true)
+    {
+      int ret= WEXITSTATUS(status);
+
+      if (ret == 0)
+      {
+        return true;
+      }
+      else if (ret == EXIT_FAILURE)
+      {
+        libtest::Error << "Command executed, but returned EXIT_FAILURE: " << command;
+      }
+      else
+      {
+        libtest::Error << "Command executed, but returned " << ret;
+      }
+    }
+    else if (WIFSIGNALED(status) == true)
+    {
+      int ret_signal= WTERMSIG(status);
+      libtest::Error << "Died from signal " << strsignal(ret_signal);
+    }
+
+    return false;
   }
 }
 
@@ -87,16 +110,6 @@ std::ostream& operator<<(std::ostream& output, const Server &arg)
   return output;  // for multiple << operators
 }
 
-void Server::nap(void)
-{
-#ifdef WIN32
-  sleep(1);
-#else
-  struct timespec global_sleep_value= { 0, 50000 };
-  nanosleep(&global_sleep_value, NULL);
-#endif
-}
-
 Server::Server(const std::string& host_arg, const in_port_t port_arg, bool is_socket_arg) :
   _is_socket(is_socket_arg),
   _pid(-1),
@@ -125,7 +138,7 @@ bool Server::cycle()
     if (kill(current_pid))
     {
       Log << "Killed existing server," << *this << " with pid:" << current_pid;
-      nap();
+      dream(0, 50000);
       continue;
     }
   }
@@ -165,7 +178,7 @@ bool Server::wait_for_pidfile() const
 bool Server::start()
 {
   // If we find that we already have a pid then kill it.
-  if (has_pid() and not kill(_pid))
+  if (has_pid() and kill(_pid) == false)
   {
     Error << "Could not kill() existing server during start() pid:" << _pid;
     return false;
@@ -173,7 +186,7 @@ bool Server::start()
   assert(not has_pid());
 
   _running.clear();
-  if (not command(_running))
+  if (command(_running) == false)
   {
     Error << "Could not build command()";
     return false;
@@ -185,19 +198,19 @@ bool Server::start()
   }
 
   int ret= system(_running.c_str());
-  if (not exited_successfully(ret))
+  if (exited_successfully(ret, _running) == false)
   {
-    Error << "system() failed:" << strerror(errno);
+    Error << "system(" << _running << ") failed: " << strerror(errno);
     _running.clear();
     return false;
   }
 
   if (is_helgrind() or is_valgrind())
   {
-    sleep(4);
+    dream(5, 50000);
   }
 
-  if (pid_file_option() and not pid_file().empty())
+  if (pid_file_option() and pid_file().empty() == false)
   {
     Wait wait(pid_file(), 8);
 
@@ -207,17 +220,20 @@ bool Server::start()
     }
   }
 
-  int count= is_helgrind() or is_valgrind() ? 20 : 5;
-  while (not ping() and --count)
+  int counter= 0;
+  bool pinged= false;
+  while ((pinged= ping()) == false and
+         counter < (is_helgrind() or is_valgrind() ? 20 : 5))
   {
-    nap();
+    dream(counter++, 50000);
   }
 
-  if (count == 0)
+  if (pinged == false)
   {
     // If we happen to have a pid file, lets try to kill it
-    if (pid_file_option() and not pid_file().empty())
+    if (pid_file_option() and pid_file().empty() == false)
     {
+      Error << "We are going to kill it off";
       kill_file(pid_file());
     }
     Error << "Failed to ping() server started with:" << _running;
@@ -324,6 +340,7 @@ void Server::rebuild_base_command()
   if (is_libtool())
   {
     _base_command+= libtool();
+    _base_command+= " --mode=execute ";
   }
 
   if (is_debug() and getenv("GDB_COMMAND"))
@@ -342,6 +359,15 @@ void Server::rebuild_base_command()
     _base_command+= " ";
   }
 
+  if (is_libtool())
+  {
+    if (getenv("PWD"))
+    {
+      _base_command+= getenv("PWD");
+      _base_command+= "/";
+    }
+  }
+
   _base_command+= executable();
 }
 
@@ -365,10 +391,15 @@ bool Server::args(std::string& options)
     arg_buffer << " " << log_file_option() << _log_file;
   }
 
+  if (getenv("LIBTEST_SYSLOG") and has_syslog())
+  {
+    arg_buffer << " --syslog";
+  }
+
   // Update pid_file
   if (pid_file_option())
   {
-    if (_pid_file.empty() and not set_pid_file())
+    if (_pid_file.empty() and set_pid_file() == false)
     {
       return false;
     }
@@ -427,7 +458,7 @@ bool Server::kill(pid_t pid_arg)
 {
   if (check_pid(pid_arg) and kill_pid(pid_arg)) // If we kill it, reset
   {
-    if (broken_pid_file() and not pid_file().empty())
+    if (broken_pid_file() and pid_file().empty() == false)
     {
       unlink(pid_file().c_str());
     }
index b91f55b13de3124b4102961efadffcba053ac3b4..b50b0b2e6fe516a125b679a614e2e14eba9af19c 100644 (file)
@@ -124,6 +124,11 @@ public:
     return (_port != 0);
   }
 
+  virtual bool has_syslog() const
+  {
+    return false;
+  }
+
   // Reset a server if another process has killed the server
   void reset()
   {
@@ -172,7 +177,6 @@ public:
   bool command(std::string& command_arg);
 
 protected:
-  void nap();
   bool set_pid_file();
 
 private:
index cd23169f5b61c022455c91f6c234b09344314d4a..2c31796f3e141c64530df63aabf99b253725e862 100644 (file)
@@ -77,7 +77,6 @@ Server* server_startup_st::pop_server()
 
 bool server_startup_st::shutdown(uint32_t number_of_host)
 {
-  assert(servers.size() > number_of_host);
   if (servers.size() > number_of_host)
   {
     Server* tmp= servers[number_of_host];
index ed017b2befe10ff6769435c756544a2381a9513a..42e6d78da39234032bb3736aa6df3ccfe22c5ad0 100644 (file)
@@ -98,6 +98,12 @@ SignalThread::~SignalThread()
   }
 #endif
   sem_destroy(&lock);
+
+  int error;
+  if ((error= pthread_sigmask(SIG_UNBLOCK, &set, NULL)) != 0)
+  {
+    Error << "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
+  }
 }
 
 extern "C" {
@@ -130,6 +136,11 @@ static void *sig_thread(void *arg)
         context->set_shutdown(SHUTDOWN_FORCED);
       }
       break;
+    case SIGPIPE:
+      {
+        Error << "Ignoring SIGPIPE";
+      }
+      break;
 
     default:
       Error << "Signal handling thread got unexpected signal " <<  strsignal(sig);
@@ -154,10 +165,14 @@ SignalThread::SignalThread() :
     sigaddset(&set, SIGQUIT);
     sigaddset(&set, SIGINT);
   }
+  sigaddset(&set, SIGPIPE);
 
   sigaddset(&set, SIGUSR2);
 
   sem_init(&lock, 0, 0);
+
+  sigemptyset(&original_set);
+  pthread_sigmask(SIG_BLOCK, NULL, &original_set);
 }
 
 
@@ -165,19 +180,15 @@ bool SignalThread::setup()
 {
   set_shutdown(SHUTDOWN_RUNNING);
 
-  sigset_t old_set;
-  sigemptyset(&old_set);
-  pthread_sigmask(SIG_BLOCK, NULL, &old_set);
-
-  if (sigismember(&old_set, SIGQUIT))
+  if (sigismember(&original_set, SIGQUIT))
   {
     Error << strsignal(SIGQUIT) << " has been previously set.";
   }
-  if (sigismember(&old_set, SIGINT))
+  if (sigismember(&original_set, SIGINT))
   {
     Error << strsignal(SIGINT) << " has been previously set.";
   }
-  if (sigismember(&old_set, SIGUSR2))
+  if (sigismember(&original_set, SIGUSR2))
   {
     Error << strsignal(SIGUSR2) << " has been previously set.";
   }
index 25eae45c6a02f59ebc4ae013f6c4d480d9ecfa10..f54633c767e952872f261ead089d8fc15a1051fd 100644 (file)
@@ -42,10 +42,12 @@ class SignalThread {
   volatile shutdown_t __shutdown;
   pthread_mutex_t shutdown_mutex;
   pthread_t thread;
+  sigset_t original_set;
 
 public:
 
   SignalThread();
+  ~SignalThread();
 
   void test();
   void post();
@@ -56,8 +58,6 @@ public:
     return sigwait(&set, &sig);
   }
 
-  ~SignalThread();
-
   void set_shutdown(shutdown_t arg);
   bool is_shutdown();
   shutdown_t get_shutdown();
index 784f3a8f646bd45098691be1f7d8984b73da02e3..ef02152674122dce31cb389c05ea711e2296c690 100644 (file)
 using namespace libtest;
 
 
-collection_st collection[] ={
-  {0, 0, 0, 0}
-};
-
 static void *world_create(server_startup_st&, test_return_t& rc)
 {
   rc= TEST_SKIPPED;
@@ -43,6 +39,5 @@ static void *world_create(server_startup_st&, test_return_t& rc)
 
 void get_world(Framework *world)
 {
-  world->collections= collection;
   world->_create= world_create;
 }
index a60d328b17a2381cdbb79e7206055cf7afb40c11..b5a44f5bf54e0da10c0ac74a49f0d1f5c3905759 100644 (file)
@@ -28,9 +28,5 @@
 #define test_literal_compare_param util_literal_compare_param
 #define test_literal_param_size util_literal_param_size
 #define test_string_make_from_cstr util_string_make_from_cstr
+#define test_string_make_from_array util_string_make_from_array
 #define test_array_length util_array_length
-
-namespace libtest {
-typedef std::vector<char> vchar_t;
-typedef std::vector<char*> vchar_ptr_t;
-}
index 2096ad19dcf4e7bd6797f717909be921c153f5fe..52dd03e7b4e60263b744b42e68df826fe9faa545 100644 (file)
 
 #include <signal.h>
 
+#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
+#include <curl/curl.h>
+#endif
+
 #ifndef __INTEL_COMPILER
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #endif
@@ -70,12 +74,86 @@ static long int timedif(struct timeval a, struct timeval b)
   return s + us;
 }
 
-static Framework *world= NULL;
+static void cleanup_curl(void)
+{
+#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
+  curl_global_cleanup();
+#endif
+}
+
+#include <getopt.h>
+#include <unistd.h>
+
 int main(int argc, char *argv[])
 {
+#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
+  if (curl_global_init(CURL_GLOBAL_ALL))
+  {
+    Error << "curl_global_init(CURL_GLOBAL_ALL) failed";
+    return EXIT_FAILURE;
+  }
+#endif
+
+  if (atexit(cleanup_curl))
+  {
+    Error << "atexit() failed";
+    return EXIT_FAILURE;
+  }
+
+  bool opt_repeat= false;
+  std::string collection_to_run;
+
+  // Options parsing
+  {
+    enum long_option_t {
+      OPT_LIBYATL_VERSION,
+      OPT_LIBYATL_MATCH_COLLECTION,
+      OPT_LIBYATL_REPEAT
+    };
+
+    static struct option long_options[]=
+    {
+      {"repeat", no_argument, NULL, OPT_LIBYATL_REPEAT},
+      {"collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION},
+      {0, 0, 0, 0}
+    };
+
+    int option_index= 0;
+    while (1)
+    {
+      int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
+      if (option_rv == -1)
+      {
+        break;
+      }
+
+      switch (option_rv)
+      {
+      case OPT_LIBYATL_VERSION:
+        break;
+
+      case OPT_LIBYATL_REPEAT:
+        opt_repeat= true;
+        break;
+
+      case OPT_LIBYATL_MATCH_COLLECTION:
+        collection_to_run= optarg;
+        break;
+
+      case '?':
+        /* getopt_long already printed an error message. */
+        Error << "unknown option to getopt_long()";
+        exit(EXIT_FAILURE);
+
+      default:
+        break;
+      }
+    }
+  }
+
   srandom((unsigned int)time(NULL));
 
-  if (getenv("LIBTEST_QUIET"))
+  if (getenv("LIBTEST_QUIET") and strcmp(getenv("LIBTEST_QUIET"), "0") == 0)
   {
     close(STDOUT_FILENO);
   }
@@ -109,243 +187,258 @@ int main(int argc, char *argv[])
     return EXIT_FAILURE;
   }
 
-  world= new Framework();
-
-  if (world == NULL)
-  {
-    Error << "Failed to create Framework()";
-    return EXIT_FAILURE;
-  }
-
-  libtest::SignalThread signal;
-  if (not signal.setup())
-  {
-    return EXIT_FAILURE;
-  }
-
-  Stats stats;
-
-  get_world(world);
+  int exit_code;
+  do {
+    exit_code= EXIT_SUCCESS;
+    Framework *world= new Framework();
 
-  test_return_t error;
-  void *creators_ptr= world->create(error);
-
-  switch (error)
-  {
-  case TEST_SUCCESS:
-    break;
-
-  case TEST_SKIPPED:
-    Out << "SKIP " << argv[0];
-    delete world;
-    return EXIT_SUCCESS;
-
-  case TEST_FATAL:
-  case TEST_FAILURE:
-  case TEST_MEMORY_ALLOCATION_FAILURE:
-    delete world;
-    return EXIT_FAILURE;
-  }
-
-  char *collection_to_run= NULL;
-  if (argc > 1)
-  {
-    collection_to_run= argv[1];
-  }
-  else if (getenv("TEST_COLLECTION"))
-  {
-    if (strlen(getenv("TEST_COLLECTION")))
+    if (world == NULL)
     {
-      collection_to_run= getenv("TEST_COLLECTION");
+      Error << "Failed to create Framework()";
+      return EXIT_FAILURE;
     }
-  }
-
-  if (collection_to_run)
-  {
-    Out << "Only testing " <<  collection_to_run;
-  }
-
-  char *wildcard= NULL;
-  if (argc == 3)
-  {
-    wildcard= argv[2];
-  }
 
-  for (collection_st *next= world->collections; next->name and (not signal.is_shutdown()); next++)
-  {
-    test_return_t collection_rc= TEST_SUCCESS;
-    bool failed= false;
-    bool skipped= false;
+    assert(sigignore(SIGPIPE) == 0);
 
-    if (collection_to_run && fnmatch(collection_to_run, next->name, 0))
-      continue;
+    libtest::SignalThread signal;
+    if (not signal.setup())
+    {
+      Error << "Failed to setup signals";
+      return EXIT_FAILURE;
+    }
 
-    stats.collection_total++;
+    Stats stats;
 
-    collection_rc= world->startup(creators_ptr);
+    get_world(world);
 
-    if (collection_rc == TEST_SUCCESS and next->pre)
-    {
-      collection_rc= world->runner()->pre(next->pre, creators_ptr);
-    }
+    test_return_t error;
+    void *creators_ptr= world->create(error);
 
-    switch (collection_rc)
+    switch (error)
     {
     case TEST_SUCCESS:
       break;
 
+    case TEST_SKIPPED:
+      Out << "SKIP " << argv[0];
+      delete world;
+      return EXIT_SUCCESS;
+
     case TEST_FATAL:
     case TEST_FAILURE:
-      Out << next->name << " [ failed ]";
-      failed= true;
-      signal.set_shutdown(SHUTDOWN_GRACEFUL);
-      goto cleanup;
+    case TEST_MEMORY_ALLOCATION_FAILURE:
+      delete world;
+      return EXIT_FAILURE;
+    }
 
-    case TEST_SKIPPED:
-      Out << next->name << " [ skipping ]";
-      skipped= true;
-      goto cleanup;
+    if (getenv("TEST_COLLECTION"))
+    {
+      if (strlen(getenv("TEST_COLLECTION")))
+      {
+        collection_to_run= getenv("TEST_COLLECTION");
+      }
+    }
 
-    case TEST_MEMORY_ALLOCATION_FAILURE:
-      test_assert(0, "Allocation failure, or unknown return");
+    if (collection_to_run.empty() == false)
+    {
+      Out << "Only testing " <<  collection_to_run;
     }
 
-    Out << "Collection: " << next->name;
+    char *wildcard= NULL;
+    if (argc == 3)
+    {
+      wildcard= argv[2];
+    }
 
-    for (test_st *run= next->tests; run->name; run++)
+    for (collection_st *next= world->collections; next and next->name and (not signal.is_shutdown()); next++)
     {
-      struct timeval start_time, end_time;
-      long int load_time= 0;
+      bool failed= false;
+      bool skipped= false;
 
-      if (wildcard && fnmatch(wildcard, run->name, 0))
+      if (collection_to_run.empty() == false and fnmatch(collection_to_run.c_str(), next->name, 0))
       {
         continue;
       }
 
-      test_return_t return_code;
-      if (test_success(return_code= world->item.startup(creators_ptr)))
-      {
-        if (test_success(return_code= world->item.flush(creators_ptr, run)))
-        {
-          // @note pre will fail is SKIPPED is returned
-          if (test_success(return_code= world->item.pre(creators_ptr)))
-          {
-            { // Runner Code
-              gettimeofday(&start_time, NULL);
-              assert(world->runner());
-              assert(run->test_fn);
-              return_code= world->runner()->run(run->test_fn, creators_ptr);
-              gettimeofday(&end_time, NULL);
-              load_time= timedif(end_time, start_time);
-            }
-          }
+      stats.collection_total++;
 
-          // @todo do something if post fails
-          (void)world->item.post(creators_ptr);
-        }
-        else if (return_code == TEST_SKIPPED)
-        { }
-        else if (return_code == TEST_FAILURE)
-        {
-          Error << " item.flush(failure)";
-          signal.set_shutdown(SHUTDOWN_GRACEFUL);
-        }
-      }
-      else if (return_code == TEST_SKIPPED)
-      { }
-      else if (return_code == TEST_FAILURE)
+      test_return_t collection_rc= world->startup(creators_ptr);
+
+      if (collection_rc == TEST_SUCCESS and next->pre)
       {
-        Error << " item.startup(failure)";
-        signal.set_shutdown(SHUTDOWN_GRACEFUL);
+        collection_rc= world->runner()->pre(next->pre, creators_ptr);
       }
 
-      stats.total++;
-
-      switch (return_code)
+      switch (collection_rc)
       {
       case TEST_SUCCESS:
-        Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
-        stats.success++;
         break;
 
       case TEST_FATAL:
       case TEST_FAILURE:
-        stats.failed++;
+        Out << next->name << " [ failed ]";
         failed= true;
-        Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
-        break;
+        signal.set_shutdown(SHUTDOWN_GRACEFUL);
+        goto cleanup;
 
       case TEST_SKIPPED:
-        stats.skipped++;
+        Out << next->name << " [ skipping ]";
         skipped= true;
-        Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
-        break;
+        goto cleanup;
 
       case TEST_MEMORY_ALLOCATION_FAILURE:
-        test_assert(0, "Memory Allocation Error");
+        test_assert(0, "Allocation failure, or unknown return");
       }
 
-      if (test_failed(world->on_error(return_code, creators_ptr)))
+      Out << "Collection: " << next->name;
+
+      for (test_st *run= next->tests; run->name; run++)
       {
-        Error << "Failed while running on_error()";
-        signal.set_shutdown(SHUTDOWN_GRACEFUL);
-        break;
+        struct timeval start_time, end_time;
+        long int load_time= 0;
+
+        if (wildcard && fnmatch(wildcard, run->name, 0))
+        {
+          continue;
+        }
+
+        test_return_t return_code;
+        try {
+          if (test_success(return_code= world->item.startup(creators_ptr)))
+          {
+            if (test_success(return_code= world->item.flush(creators_ptr, run)))
+            {
+              // @note pre will fail is SKIPPED is returned
+              if (test_success(return_code= world->item.pre(creators_ptr)))
+              {
+                { // Runner Code
+                  gettimeofday(&start_time, NULL);
+                  assert(world->runner());
+                  assert(run->test_fn);
+                  return_code= world->runner()->run(run->test_fn, creators_ptr);
+                  gettimeofday(&end_time, NULL);
+                  load_time= timedif(end_time, start_time);
+                }
+              }
+
+              // @todo do something if post fails
+              (void)world->item.post(creators_ptr);
+            }
+            else if (return_code == TEST_SKIPPED)
+            { }
+            else if (return_code == TEST_FAILURE)
+            {
+              Error << " item.flush(failure)";
+              signal.set_shutdown(SHUTDOWN_GRACEFUL);
+            }
+          }
+          else if (return_code == TEST_SKIPPED)
+          { }
+          else if (return_code == TEST_FAILURE)
+          {
+            Error << " item.startup(failure)";
+            signal.set_shutdown(SHUTDOWN_GRACEFUL);
+          }
+        }
+
+        catch (std::exception &e)
+        {
+          Error << "Exception was thrown: " << e.what();
+          return_code= TEST_FAILURE;
+        }
+        catch (...)
+        {
+          Error << "Unknown exception occurred";
+          return_code= TEST_FAILURE;
+        }
+
+        stats.total++;
+
+        switch (return_code)
+        {
+        case TEST_SUCCESS:
+          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
+          stats.success++;
+          break;
+
+        case TEST_FATAL:
+        case TEST_FAILURE:
+          stats.failed++;
+          failed= true;
+          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+          break;
+
+        case TEST_SKIPPED:
+          stats.skipped++;
+          skipped= true;
+          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+          break;
+
+        case TEST_MEMORY_ALLOCATION_FAILURE:
+          test_assert(0, "Memory Allocation Error");
+        }
+
+        if (test_failed(world->on_error(return_code, creators_ptr)))
+        {
+          Error << "Failed while running on_error()";
+          signal.set_shutdown(SHUTDOWN_GRACEFUL);
+          break;
+        }
       }
-    }
 
-    (void) world->runner()->post(next->post, creators_ptr);
+      (void) world->runner()->post(next->post, creators_ptr);
 
 cleanup:
-    if (failed == false and skipped == false)
-    {
-      stats.collection_success++;
+      if (failed == false and skipped == false)
+      {
+        stats.collection_success++;
+      }
+
+      if (failed)
+      {
+        stats.collection_failed++;
+      }
+
+      if (skipped)
+      {
+        stats.collection_skipped++;
+      }
+
+      world->shutdown(creators_ptr);
+      Outn();
     }
 
-    if (failed)
+    if (not signal.is_shutdown())
     {
-      stats.collection_failed++;
+      signal.set_shutdown(SHUTDOWN_GRACEFUL);
     }
 
-    if (skipped)
+    shutdown_t status= signal.get_shutdown();
+    if (status == SHUTDOWN_FORCED)
     {
-      stats.collection_skipped++;
+      Out << "Tests were aborted.";
+      exit_code= EXIT_FAILURE;
+    }
+    else if (stats.collection_failed)
+    {
+      Out << "Some test failed.";
+      exit_code= EXIT_FAILURE;
+    }
+    else if (stats.collection_skipped and stats.collection_failed and stats.collection_success)
+    {
+      Out << "Some tests were skipped.";
+    }
+    else if (stats.collection_success and stats.collection_failed == 0)
+    {
+      Out << "All tests completed successfully.";
     }
 
-    world->shutdown(creators_ptr);
-    Outn();
-  }
-
-  if (not signal.is_shutdown())
-  {
-    signal.set_shutdown(SHUTDOWN_GRACEFUL);
-  }
-
-  int exit_code= EXIT_SUCCESS;
-  shutdown_t status= signal.get_shutdown();
-  if (status == SHUTDOWN_FORCED)
-  {
-    Out << "Tests were aborted.";
-    exit_code= EXIT_FAILURE;
-  }
-  else if (stats.collection_failed)
-  {
-    Out << "Some test failed.";
-    exit_code= EXIT_FAILURE;
-  }
-  else if (stats.collection_skipped and stats.collection_failed and stats.collection_success)
-  {
-    Out << "Some tests were skipped.";
-  }
-  else if (stats.collection_success and stats.collection_failed == 0)
-  {
-    Out << "All tests completed successfully.";
-  }
-
-  stats_print(&stats);
+    stats_print(&stats);
 
-  delete world;
+    delete world;
 
-  Outn(); // Generate a blank to break up the messages if make check/test has been run
+    Outn(); // Generate a blank to break up the messages if make check/test has been run
+  } while (exit_code == EXIT_SUCCESS and opt_repeat);
 
   return exit_code;
 }
index 74a20e05e8d3df44ebdd70584c155ad9a63d7c28..abd4e2aa4184f2babd6abc9ea1f14d86de925db6 100644 (file)
@@ -87,6 +87,7 @@ do \
     return TEST_FAILURE; \
   } \
 } while (0)
+#define test_true_hint test_true_got
 
 #define test_skip(A,B) \
 do \
@@ -190,9 +191,10 @@ do \
 #define test_strcmp(A,B) \
 do \
 { \
-  if (strcmp((A), (B))) \
+  if ((A) == NULL or (B) == NULL or strcmp((A), (B))) \
   { \
-    fprintf(stderr, "\n%s:%d: Expected %s, got %s\n", __FILE__, __LINE__, (A), (B)); \
+    if ((B) == NULL) fprintf(stderr, "\n%s:%d: Expected %s, got <null>\n", __FILE__, __LINE__, (A)); \
+    else fprintf(stderr, "\n%s:%d: Expected %s, got \"%s\"\n", __FILE__, __LINE__, (A), (B)); \
     libtest::create_core(); \
     return TEST_FAILURE; \
   } \
@@ -201,7 +203,7 @@ do \
 #define test_memcmp(A,B,C) \
 do \
 { \
-  if (memcmp((A), (B), (C))) \
+  if ((A) == NULL or (B) == NULL or memcmp((A), (B), (C))) \
   { \
     fprintf(stderr, "\n%s:%d: %.*s -> %.*s\n", __FILE__, __LINE__, (int)(C), (char *)(A), (int)(C), (char *)(B)); \
     libtest::create_core(); \
@@ -209,6 +211,17 @@ do \
   } \
 } while (0)
 
+#define test_memcmp_hint(A,B,C,__hint) \
+do \
+{ \
+  if ((A) == NULL or (B) == NULL or memcmp((A), (B), (C))) \
+  { \
+    fprintf(stderr, "\n%s:%d: (hint:%s) %.*s -> %.*s\n", __FILE__, __LINE__, __hint, (int)(C), (char *)(A), (int)(C), (char *)(B)); \
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
 #define test_return_if(__test_return_t) \
 do \
 { \
index c30fbfc0273ac5bd0173697d0cf5e87d08032b58..b86bc68e50420c583def962da9dd2df8c25df856 100644 (file)
@@ -32,6 +32,9 @@
 #include <libtest/visibility.h>
 #include <libtest/version.h>
 
+#include <libtest/vchar.hpp>
+
+#include <libtest/has.hpp>
 #include <libtest/error.h>
 #include <libtest/strerror.h>
 #include <libtest/stream.h>
@@ -41,6 +44,7 @@
 #include <libtest/wait.h>
 #include <libtest/callbacks.h>
 #include <libtest/test.h>
+#include <libtest/dream.h>
 #include <libtest/core.h>
 #include <libtest/runner.h>
 #include <libtest/port.h>
@@ -54,3 +58,4 @@
 #include <libtest/cmdline.h>
 #include <libtest/string.hpp>
 #include <libtest/binaries.h>
+#include <libtest/http.hpp>
index 87102ddd7afc8559c4292cc55bf7910fb47be7d4..2d171dfdfae7cea3d3dc37b09f73e184bd4f0317 100644 (file)
@@ -25,7 +25,7 @@
 #include <libtest/test.hpp>
 
 #if defined(LIBTEST_WITH_LIBMEMCACHED_SUPPORT) && LIBTEST_WITH_LIBMEMCACHED_SUPPORT
-#include <libmemcached/memcached.h>
+#include <libmemcached-1.0/memcached.h>
 #endif
 
 #if defined(LIBTEST_WITH_LIBGEARMAN_SUPPORT) && LIBTEST_WITH_LIBGEARMAN_SUPPORT
@@ -230,19 +230,16 @@ static test_return_t gearmand_cycle_test(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-  if (GEARMAND_BINARY)
-  {
-    if (HAVE_LIBGEARMAN)
-    {
-      test_true(has_gearmand_binary());
-      const char *argv[1]= { "cycle_gearmand" };
-      test_true(server_startup(*servers, "gearmand", 9999, 1, argv));
+#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
+  test_true(has_gearmand_binary());
+#else
+  test_skip(true, has_gearmand_binary());
+#endif
 
-      return TEST_SUCCESS;
-    }
-  }
+  const char *argv[1]= { "cycle_gearmand" };
+  test_true(server_startup(*servers, "gearmand", 9999, 1, argv));
 
-  return TEST_SKIPPED;
+  return TEST_SUCCESS;
 }
 
 static test_return_t memcached_cycle_test(void *object)
@@ -307,11 +304,152 @@ static test_return_t memcached_sasl_test(void *object)
   return TEST_SKIPPED;
 }
 
+static test_return_t application_true_BINARY(void *)
+{
+  Application true_app("true");
+
+  test_compare(Application::SUCCESS, true_app.run());
+  test_compare(Application::SUCCESS, true_app.wait());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_true_fubar_BINARY(void *)
+{
+  Application true_app("true");
+
+  const char *args[]= { "--fubar", 0 };
+  test_compare(Application::SUCCESS, true_app.run(args));
+  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(0, true_app.stdout_result().size());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_true_fubar_eq_doh_BINARY(void *)
+{
+  Application true_app("true");
+
+  const char *args[]= { "--fubar=doh", 0 };
+  test_compare(Application::SUCCESS, true_app.run(args));
+  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(0, true_app.stdout_result().size());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_true_fubar_eq_doh_option_BINARY(void *)
+{
+  Application true_app("true");
+
+  true_app.add_option("--fubar=", "doh");
+
+  test_compare(Application::SUCCESS, true_app.run());
+  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(0, true_app.stdout_result().size());
+
+  return TEST_SUCCESS;
+}
+
+
+static test_return_t GET_TEST(void *)
+{
+  libtest::http::GET get("http://foo.example.com/");
+
+  test_compare(false, get.execute());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t POST_TEST(void *)
+{
+  libtest::vchar_t body;
+  libtest::http::POST post("http://foo.example.com/", body);
+
+  test_compare(false, post.execute());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t TRACE_TEST(void *)
+{
+  libtest::vchar_t body;
+  libtest::http::TRACE trace("http://foo.example.com/", body);
+
+  test_compare(false, trace.execute());
+
+  return TEST_SUCCESS;
+}
+
+
+static test_return_t vchar_t_TEST(void *)
+{
+  libtest::vchar_t response;
+  libtest::make_vector(response, test_literal_param("fubar\n"));
+  test_compare(response, response);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_echo_fubar_BINARY(void *)
+{
+  Application true_app("echo");
+
+  const char *args[]= { "fubar", 0 };
+  test_compare(Application::SUCCESS, true_app.run(args));
+  test_compare(Application::SUCCESS, true_app.wait());
+
+  libtest::vchar_t response;
+  make_vector(response, test_literal_param("fubar\n"));
+  test_compare(response, true_app.stdout_result());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_echo_fubar_BINARY2(void *)
+{
+  Application true_app("echo");
+
+  true_app.add_option("fubar");
+
+  test_compare(Application::SUCCESS, true_app.run());
+  test_compare(Application::SUCCESS, true_app.wait());
+  libtest::vchar_t response;
+  make_vector(response, test_literal_param("fubar\n"));
+  test_compare(response, true_app.stdout_result());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t true_BINARY(void *)
+{
+  const char *args[]= { 0 };
+  test_compare(EXIT_SUCCESS, exec_cmdline("true", args));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t true_fubar_BINARY(void *)
+{
+  const char *args[]= { "--fubar", 0 };
+  test_compare(EXIT_SUCCESS, exec_cmdline("true", args));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t echo_fubar_BINARY(void *)
+{
+  const char *args[]= { "fubar", 0 };
+  test_compare(EXIT_SUCCESS, exec_cmdline("echo", args));
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t wait_BINARY(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline("libtest/wait", args));
+  test_compare(EXIT_FAILURE, exec_cmdline("libtest/wait", args, true));
 
   return TEST_SUCCESS;
 }
@@ -320,7 +458,7 @@ static test_return_t wait_help_BINARY(void *)
 {
   const char *args[]= { "--quiet", "--help", 0 };
 
-  test_true(exec_cmdline("libtest/wait", args));
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
 
   return TEST_SUCCESS;
 }
@@ -329,23 +467,74 @@ static test_return_t wait_version_BINARY(void *)
 {
   const char *args[]= { "--quiet", "--version", 0 };
 
-  test_true(exec_cmdline("libtest/wait", args));
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_services_BINARY(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+
+  const char *args[]= { "--quiet", "/etc/services", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
 
   return TEST_SUCCESS;
 }
 
+static test_return_t wait_services_BINARY2(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+
+  const char *args[]= { "/etc/services", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_wait_services_BINARY2(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+
+  libtest::Application("libtest/wait", true);
+  const char *args[]= { "/etc/services", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_for_gearman(void *)
+{
+  test_skip(true, HAVE_LIBGEARMAN);
+  test_skip(true, has_gearmand_binary());
+  return TEST_SUCCESS;
+}
+
+
 test_st gearmand_tests[] ={
 #if 0
   {"pause", 0, pause_test },
 #endif
   {"gearmand startup-shutdown", 0, gearmand_cycle_test },
+  {"_compare(gearman_return_t)", 0, _compare_gearman_return_t_test },
   {0, 0, 0}
 };
 
+static test_return_t check_for_libmemcached(void *)
+{
+  test_skip(true, HAVE_LIBMEMCACHED);
+  test_skip(true, has_memcached_binary());
+  return TEST_SUCCESS;
+}
+
 test_st memcached_tests[] ={
   {"memcached startup-shutdown", 0, memcached_cycle_test },
   {"memcached(socket file) startup-shutdown", 0, memcached_socket_cycle_test },
   {"memcached_sasl() startup-shutdown", 0, memcached_sasl_test },
+  {"_compare(memcached_return_t)", 0, _compare_memcached_return_t_test },
   {0, 0, 0}
 };
 
@@ -386,15 +575,42 @@ test_st directories_tests[] ={
 
 test_st comparison_tests[] ={
   {"_compare(test_return_t)", 0, _compare_test_return_t_test },
-  {"_compare(memcached_return_t)", 0, _compare_memcached_return_t_test },
-  {"_compare(gearman_return_t)", 0, _compare_gearman_return_t_test },
   {0, 0, 0}
 };
 
 test_st cmdline_tests[] ={
+  {"true", 0, true_BINARY },
+  {"true --fubar", 0, true_fubar_BINARY },
+  {"echo fubar", 0, echo_fubar_BINARY },
   {"wait --quiet", 0, wait_BINARY },
   {"wait --quiet --help", 0, wait_help_BINARY },
   {"wait --quiet --version", 0, wait_version_BINARY },
+  {"wait --quiet /etc/services", 0, wait_services_BINARY },
+  {"wait /etc/services", 0, wait_services_BINARY2 },
+  {0, 0, 0}
+};
+
+test_st application_tests[] ={
+  {"vchar_t", 0, vchar_t_TEST },
+  {"true", 0, application_true_BINARY },
+  {"true --fubar", 0, application_true_fubar_BINARY },
+  {"true --fubar=doh", 0, application_true_fubar_eq_doh_BINARY },
+  {"true --fubar=doh add_option()", 0, application_true_fubar_eq_doh_option_BINARY },
+  {"echo fubar", 0, application_echo_fubar_BINARY },
+  {"echo fubar (as option)", 0, application_echo_fubar_BINARY2 },
+  {0, 0, 0}
+};
+
+static test_return_t check_for_curl(void *)
+{
+  test_skip(true, HAVE_LIBCURL);
+  return TEST_SUCCESS;
+}
+
+test_st http_tests[] ={
+  {"GET", 0, GET_TEST },
+  {"POST", 0, POST_TEST },
+  {"TRACE", 0, TRACE_TEST },
   {0, 0, 0}
 };
 
@@ -404,9 +620,11 @@ collection_st collection[] ={
   {"local", 0, 0, local_log},
   {"directories", 0, 0, directories_tests},
   {"comparison", 0, 0, comparison_tests},
-  {"gearmand", 0, 0, gearmand_tests},
-  {"memcached", 0, 0, memcached_tests},
+  {"gearmand", check_for_gearman, 0, gearmand_tests},
+  {"memcached", check_for_libmemcached, 0, memcached_tests},
   {"cmdline", 0, 0, cmdline_tests},
+  {"application", 0, 0, application_tests},
+  {"http", check_for_curl, 0, http_tests},
   {0, 0, 0, 0}
 };
 
diff --git a/libtest/vchar.cc b/libtest/vchar.cc
new file mode 100644 (file)
index 0000000..779cfbb
--- /dev/null
@@ -0,0 +1,58 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <libtest/common.h>
+
+namespace libtest {
+
+static std::string printer(const char *str, size_t length)
+{
+  std::ostringstream buf;
+  for (size_t x= 0; x < length; x++)
+  {
+    if (isprint(str[x]))
+    {
+      buf << str[x];
+    }
+    else
+    {
+      buf << "(" << int(str[x]) << ")";
+    }
+  }
+
+  return buf.str();
+}
+
+void make_vector(libtest::vchar_t& arg, const char *str, size_t length)
+{
+  arg.resize(length);
+  memcpy(&arg[0], str, length);
+}
+
+std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg)
+{
+  std::string tmp= libtest::printer(&arg[0], arg.size());
+  output << tmp <<  "[" << arg.size() << "]";
+
+  return output;
+}
+
+} // namespace libtest
diff --git a/libtest/vchar.hpp b/libtest/vchar.hpp
new file mode 100644 (file)
index 0000000..7bdb548
--- /dev/null
@@ -0,0 +1,41 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#pragma once
+
+#include <cstring>
+#include <iostream>
+#include <ostream>
+#include <sstream>
+#include <vector>
+
+namespace libtest {
+
+typedef std::vector<char*> vchar_ptr_t;
+typedef std::vector<char> vchar_t;
+
+void make_vector(libtest::vchar_t& arg, const char *str, size_t length);
+
+std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg);
+
+} // namespace libtest
+
index cf2277e6d94e58a71a9a5e32f8a0e35495ecfbdf..79659664409ce35edfe2964ae19188f307775084 100644 (file)
@@ -34,7 +34,6 @@
 static void version_command(const char *command_name, int major_version, int minor_version)
 {
   std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
-  exit(EXIT_SUCCESS);
 }
 
 static void help_command(const char *command_name,
@@ -50,7 +49,6 @@ static void help_command(const char *command_name,
   }
 
   std::cout << std::endl;
-  exit(EXIT_SUCCESS);
 }
 
 static void close_stdio(void)
@@ -102,11 +100,12 @@ static void options_parse(int argc, char *argv[])
 
   bool opt_version= false;
   bool opt_help= false;
+  bool opt_quiet= false;
   int option_index= 0;
 
   while (1)
   {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
     if (option_rv == -1) 
     {
       break;
@@ -118,19 +117,29 @@ static void options_parse(int argc, char *argv[])
       opt_help= true;
       break;
 
+    case OPT_VERSION: /* --version or -v */
+      opt_version= true;
+      break;
+
     case OPT_QUIET:
-      close_stdio();
+      opt_quiet= true;
       break;
 
     case '?':
       /* getopt_long already printed an error message. */
-      exit(EXIT_SUCCESS);
+      exit(EXIT_FAILURE);
 
     default:
-      abort();
+      help_command(argv[0], 1, 0, long_options);
+      exit(EXIT_FAILURE);
     }
   }
 
+  if (opt_quiet)
+  {
+    close_stdio();
+  }
+
   if (opt_version)
   {
     version_command(argv[0], 1, 0);
@@ -146,15 +155,25 @@ static void options_parse(int argc, char *argv[])
 
 int main(int argc, char *argv[])
 {
+  if (argc == 1)
+  {
+    return EXIT_FAILURE;
+  }
+
   options_parse(argc, argv);
 
-  if (argc == 2)
+  int ret= EXIT_FAILURE;
+  while (optind < argc)
   {
-    libtest::Wait wait(argv[1]);
+    libtest::Wait wait(argv[optind++]);
+
+    if (wait.successful() == false)
+    {
+      return EXIT_FAILURE;
+    }
 
-    if (wait.successful())
-      return EXIT_SUCCESS;
+    ret= EXIT_SUCCESS;
   }
 
-  return EXIT_FAILURE;
+  return ret;
 }
index 9e47fdd7c14adbc287501969eaf627b3a04aa1fa..689c5c52f08f0d9d83237413491f02c489b2beeb 100644 (file)
@@ -86,6 +86,12 @@ tests_memdump_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
 check_PROGRAMS+= tests/memdump
 noinst_PROGRAMS+= tests/memdump
 
+test-memerror: clients/memerror
+       tests/memerror
+
+valgrind-memerror: clients/memerror
+        @$(VALGRIND_COMMAND) tests/memerror
+
 test-memcp: clients/memcp
        @echo "Testing memcp"
        @@MEMC_BINARY@ -d -u root -P `pwd`/tests/Xumemc.pid -p 12555
index b3f6fbe0718bf3fea1a5924d5085c20f0676a51f..f2a724f82a18c4d76862946282cb851f5d9d6349 100644 (file)
@@ -2706,7 +2706,7 @@ test_return_t user_supplied_bug14(memcached_st *memc)
     value.push_back((char) (x % 127));
   }
 
-  for (size_t current_length= 0; current_length < value.size(); current_length++)
+  for (size_t current_length= 1; current_length < value.size(); current_length++)
   {
     memcached_return_t rc= memcached_set(memc, test_literal_param("foo"),
                                          &value[0], current_length,
@@ -2720,7 +2720,9 @@ test_return_t user_supplied_bug14(memcached_st *memc)
 
     test_compare(MEMCACHED_SUCCESS, rc);
     test_compare(string_length, current_length);
-    test_memcmp(string, &value[0], string_length);
+    char buffer[1024];
+    snprintf(buffer, sizeof(buffer), "%u", uint32_t(string_length));
+    test_memcmp_hint(string, &value[0], string_length, buffer);
 
     free(string);
   }
@@ -4981,5 +4983,7 @@ test_return_t kill_HUP_TEST(memcached_st *original_memc)
                              test_literal_param(__func__), // Values
                              0, 0));
 
+  memcached_free(memc);
+
   return TEST_SUCCESS;
 }
index c8adad18153a5dabde1ea04a795ed0cec95f0b4e..4984818841cb4ed95e4bf3918d967fe931d32e32 100644 (file)
@@ -56,41 +56,45 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "-q", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "-q", "--help", 0 };
+  const char *args[]= { "-h", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 static test_return_t ascii_test(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "-p %d", int(default_port()));
-  const char *args[]= { "-q", buffer, " -a ", 0 };
+  snprintf(buffer, sizeof(buffer), "%d", int(default_port()));
+  const char *args[]= { "-p", buffer, " -a ", 0 };
+
+  test_true(exec_cmdline(executable, args, true) <= EXIT_FAILURE);
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 static test_return_t binary_test(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "-p %d", int(default_port()));
-  const char *args[]= { "-q", buffer, " -b ", 0 };
+  snprintf(buffer, sizeof(buffer), "%d", int(default_port()));
+  const char *args[]= { "-p", buffer, " -b ", 0 };
+
+  test_true(exec_cmdline(executable, args, true) <= EXIT_FAILURE);
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 test_st memcapable_tests[] ={
   {"--quiet", 0, quiet_test},
-  {"--help", 0, help_test},
+  {"-h", 0, help_test},
   {"-a, ascii", 0, ascii_test},
   {"-b, binary", 0, binary_test},
   {0, 0, 0}
index ea64352eea809672a5fa74a8fac73e6c160c4e86..4b1096aca9b110b64c0402e2427d00a989015440 100644 (file)
@@ -56,15 +56,17 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -72,7 +74,7 @@ static test_return_t cat_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "foo", 0 };
+  const char *args[]= { buffer, "foo", 0 };
 
   memcached_st *memc= memcached(buffer, strlen(buffer));
   test_true(memc);
@@ -84,7 +86,7 @@ static test_return_t cat_test(void *)
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_SUCCESS, rc);
@@ -98,7 +100,7 @@ static test_return_t NOT_FOUND_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "foo", 0 };
+  const char *args[]= { buffer, "foo", 0 };
 
   memcached_st *memc= memcached(buffer, strlen(buffer));
   test_true(memc);
@@ -109,7 +111,7 @@ static test_return_t NOT_FOUND_test(void *)
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_NOTFOUND, rc);
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
 
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_NOTFOUND, rc);
index a929b6db5a438aff9ee0aed323277eabffd1d811..698041e69043ae895deb9e83b7332004b5b8ce78 100644 (file)
@@ -56,15 +56,17 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -72,9 +74,10 @@ static test_return_t server_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, 0 };
+  const char *args[]= { buffer, 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
index 0aeb0a99b82a908243b36b4e47f6f3870c65cf50..790d1a68b1669a7475818537e3c666b6c36f571a 100644 (file)
@@ -56,7 +56,8 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
@@ -64,7 +65,8 @@ static test_return_t help_test(void *)
 {
   const char *args[]= { "--help", "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
@@ -74,7 +76,8 @@ static test_return_t server_test(void *)
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
   const char *args[]= { buffer, 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
@@ -82,7 +85,7 @@ static test_return_t FOUND_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, 0 };
+  const char *args[]= { buffer, 0 };
 
   memcached_st *memc= memcached(buffer, strlen(buffer));
   test_true(memc);
@@ -97,7 +100,7 @@ static test_return_t FOUND_test(void *)
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
   memcached_free(memc);
 
index 88ddcbadf311a8e3e82c7513420f17c1e89f3227..00863475838620c3d9639029062737b566ebacb0 100644 (file)
@@ -52,42 +52,56 @@ using namespace libtest;
 
 static std::string executable;
 
-static test_return_t quiet_test(void *)
+static test_return_t help_TEST(void *)
 {
-  const char *args[]= { "--quiet", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
-static test_return_t help_test(void *)
+static test_return_t version_TEST(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--version", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 static test_return_t error_test(void *)
 {
-  const char *args[]= { "--quiet", "MEMCACHED_SUCCESS", 0 };
+  const char *args[]= { "memcached_success", 0 };
+
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t SUCCESS_TEST(void *)
+{
+  const char *args[]= { "0", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 static test_return_t bad_input_test(void *)
 {
-  const char *args[]= { "--quiet", "bad input", 0 };
+  const char *args[]= { "bad input", 0 };
+
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
 test_st memerror_tests[] ={
-  {"--quiet", 0, quiet_test},
-  {"--help", 0, help_test},
+  {"--help", 0, help_TEST},
+  {"--version", 0, version_TEST},
   {"<error>", 0, error_test},
+  {"0", 0, SUCCESS_TEST},
   {"<bad input>", 0, bad_input_test},
   {0, 0, 0}
 };
index 6cafcbbab31894f19438110df62cd7af2b9a1162..9754470830201e44084bca16b895523e02424bd0 100644 (file)
@@ -56,15 +56,17 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -72,9 +74,10 @@ static test_return_t server_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, 0 };
+  const char *args[]= { buffer, 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
index f3a1f84bc3ed105cae57c2cfb667957ba94a4e24..382693cd8a90e1290472926069241170c8b8de67 100644 (file)
@@ -56,15 +56,16 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -72,7 +73,6 @@ static test_return_t rm_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "foo", 0 };
 
   memcached_st *memc= memcached(buffer, strlen(buffer));
   test_true(memc);
@@ -84,7 +84,8 @@ static test_return_t rm_test(void *)
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  test_true(exec_cmdline(executable, args));
+  const char *args[]= { buffer, "foo", 0 };
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_NOTFOUND, rc);
@@ -98,7 +99,7 @@ static test_return_t NOT_FOUND_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "foo", 0 };
+  const char *args[]= { buffer, "foo", 0 };
 
   memcached_st *memc= memcached(buffer, strlen(buffer));
   test_true(memc);
@@ -107,7 +108,7 @@ static test_return_t NOT_FOUND_test(void *)
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_NOTFOUND, rc);
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
   test_null(memcached_get(memc, test_literal_param("foo"), 0, 0, &rc));
   test_compare(MEMCACHED_NOTFOUND, rc);
index 21d66c5937672d8421bb02ff9fd44b01b8e047c8..f353978d2305a02ba7c87b32bb0a23aecffe47a2 100644 (file)
@@ -56,15 +56,17 @@ static test_return_t quiet_test(void *)
 {
   const char *args[]= { "--quiet", 0 };
 
-  test_true(exec_cmdline(executable, args));
+  test_compare(EXIT_FAILURE, exec_cmdline(executable, args, true));
+
   return TEST_SUCCESS;
 }
 
 static test_return_t help_test(void *)
 {
-  const char *args[]= { "--quiet", "--help", 0 };
+  const char *args[]= { "--help", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -72,9 +74,10 @@ static test_return_t server_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, 0 };
+  const char *args[]= { buffer, 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -82,9 +85,10 @@ static test_return_t server_concurrency_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", 0 };
+  const char *args[]= { buffer, "--concurrency=10", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -92,9 +96,10 @@ static test_return_t server_concurrency_initial_load_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", "--initial-load=1000", 0 };
+  const char *args[]= { buffer, "--concurrency=10", "--initial-load=1000", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -102,9 +107,10 @@ static test_return_t server_concurrency_initial_load_execute_number_test(void *)
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", 0 };
+  const char *args[]= { buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -112,9 +118,10 @@ static test_return_t server_concurrency_initial_load_execute_number_test_get_tes
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=get", 0 };
+  const char *args[]= { buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=get", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -122,9 +129,10 @@ static test_return_t server_concurrency_initial_load_execute_number_test_set_tes
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=set", 0 };
+  const char *args[]= { buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=set", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
@@ -132,9 +140,10 @@ static test_return_t server_concurrency_initial_load_execute_number_test_set_non
 {
   char buffer[1024];
   snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=set", "--non-blocking", 0 };
+  const char *args[]= { buffer, "--concurrency=10", "--initial-load=1000", "--execute-number=10", "--test=set", "--non-blocking", 0 };
+
+  test_compare(EXIT_SUCCESS, exec_cmdline(executable, args, true));
 
-  test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
index 3b129d18eb6d5b3871cd2c30ebb5a2ab2406ba14..683932973250f320f4d290366c2b5c7e55994f92 100644 (file)
@@ -77,7 +77,7 @@ bool daemon_is_ready(bool close_io)
     return false;
   }
 
-  if (not close_io)
+  if (close_io == false)
   {
     return true;;
   }
index 19d01fcf913c4d5d805d9e7e6eded819521ffd9e..e96f414f72e6280ba899414496b81ce376c3c5ac 100644 (file)
 #include "util/instance.hpp"
 
 #include <cstdio>
-#include <sstream>
 #include <iostream>
 #include <netdb.h>
+#include <netinet/in.h>
 #include <poll.h>
+#include <sstream>
 #include <sys/socket.h>
 #include <sys/types.h>
-#include <netinet/in.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 
 namespace datadifferential {
@@ -213,20 +217,31 @@ bool Instance::run()
         do
         {
           char buffer[BUFSIZ];
-          read_length= recv(_sockfd, buffer, sizeof(buffer), 0);
+          read_length= ::recv(_sockfd, buffer, sizeof(buffer), 0);
 
           if (read_length < 0)
           {
             switch(errno)
             {
             default:
-              std::cerr << "Error occured while reading data from " << _host.c_str() << std::endl;
+              _last_error.clear();
+              _last_error+= "Error occured while reading data from ";
+              _last_error+= _host;
               return false;
             }
           }
+          else if (read_length == 0)
+          {
+            _last_error.clear();
+            _last_error+= "Socket was shutdown while reading from ";
+            _last_error+= _host;
+
+            return false;
+          }
 
           operation->push(buffer, static_cast<size_t>(read_length));
           total_read+= static_cast<size_t>(read_length);
+
         } while (more_to_read());
       } // end has_response
 
@@ -276,7 +291,9 @@ bool Instance::more_to_read() const
 void Instance::close_socket()
 {
   if (_sockfd == INVALID_SOCKET)
+  {
     return;
+  }
 
   /* in case of death shutdown to avoid blocking at close() */
   if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN)
@@ -293,8 +310,10 @@ void Instance::close_socket()
 
 void Instance::free_addrinfo()
 {
-  if (not _addrinfo)
+  if (_addrinfo == NULL)
+  {
     return;
+  }
 
   freeaddrinfo(_addrinfo);
   _addrinfo= NULL;
index ad19e2b717072bc8e2f49ed68d4889ac20778fbd..def31a6b060ea0873bc2f51fb07c5382448bc538 100644 (file)
@@ -47,7 +47,9 @@ namespace util {
 bool Operation::response(std::string &arg)
 {
   if (_response.empty())
+  {
     return false;
+  }
 
   if (not memcmp("OK\r\n", &_response[0], 3))
   { }
index 7573fe656f639e905324165824ed3fa345e24e6a..b15bf0e4663b84214040c52828b59a34b801a973 100644 (file)
 #include <pthread.h>
 #include <semaphore.h>
 
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
 namespace datadifferential {
 namespace util {
 
index 873551e5f39539e278cc6c5c658b4db7eb50f57b..9f6786985f843631344fcd0b4ff04930c7df71a6 100644 (file)
@@ -51,5 +51,7 @@
 
 #define util_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0)
 
+#define util_string_make_from_array(__array) (__array), (strlen(__array))
+
 #define util_array_length(__array) sizeof(__array)/sizeof(&__array)