"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/testapp.c" (21 Feb 2022, 78824 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "testapp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.6.12_vs_1.6.13.

    1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    2 #undef NDEBUG
    3 #include <pthread.h>
    4 #include <sys/types.h>
    5 #include <sys/socket.h>
    6 #include <sys/wait.h>
    7 #include <netdb.h>
    8 #include <arpa/inet.h>
    9 #include <netinet/in.h>
   10 #include <netinet/tcp.h>
   11 #include <signal.h>
   12 #include <stdio.h>
   13 #include <stdlib.h>
   14 #include <errno.h>
   15 #include <assert.h>
   16 #include <string.h>
   17 #include <unistd.h>
   18 #include <netinet/in.h>
   19 #include <fcntl.h>
   20 
   21 #include "config.h"
   22 #include "cache.h"
   23 #include "crc32c.h"
   24 #include "hash.h"
   25 #include "jenkins_hash.h"
   26 #include "stats_prefix.h"
   27 #include "util.h"
   28 #include "protocol_binary.h"
   29 #ifdef TLS
   30 #include <openssl/ssl.h>
   31 #endif
   32 
   33 #define TMP_TEMPLATE "/tmp/test_file.XXXXXXX"
   34 
   35 enum test_return { TEST_SKIP, TEST_PASS, TEST_FAIL };
   36 
   37 struct conn {
   38     int sock;
   39 #ifdef TLS
   40     SSL_CTX   *ssl_ctx;
   41     SSL    *ssl;
   42 #endif
   43     ssize_t (*read)(struct conn  *c, void *buf, size_t count);
   44     ssize_t (*write)(struct conn *c, const void *buf, size_t count);
   45 };
   46 
   47 hash_func hash;
   48 
   49 static ssize_t tcp_read(struct conn *c, void *buf, size_t count);
   50 static ssize_t tcp_write(struct conn *c, const void *buf, size_t count);
   51 #ifdef TLS
   52 static ssize_t ssl_read(struct conn *c, void *buf, size_t count);
   53 static ssize_t ssl_write(struct conn *c, const void *buf, size_t count);
   54 #endif
   55 
   56 ssize_t tcp_read(struct conn *c, void *buf, size_t count) {
   57     assert(c != NULL);
   58     return read(c->sock, buf, count);
   59 }
   60 
   61 ssize_t tcp_write(struct conn *c, const void *buf, size_t count) {
   62     assert(c != NULL);
   63     return write(c->sock, buf, count);
   64 }
   65 #ifdef TLS
   66 ssize_t ssl_read(struct conn *c, void *buf, size_t count) {
   67     assert(c != NULL);
   68     return SSL_read(c->ssl, buf, count);
   69 }
   70 
   71 ssize_t ssl_write(struct conn *c, const void *buf, size_t count) {
   72     assert(c != NULL);
   73     return SSL_write(c->ssl, buf, count);
   74 }
   75 #endif
   76 
   77 static pid_t server_pid;
   78 static in_port_t port;
   79 static struct conn *con = NULL;
   80 static bool allow_closed_read = false;
   81 static bool enable_ssl = false;
   82 
   83 static void close_conn() {
   84     if (con == NULL) return;
   85 #ifdef TLS
   86     if (con->ssl) {
   87         SSL_shutdown(con->ssl);
   88         SSL_free(con->ssl);
   89     }
   90     if (con->ssl_ctx)
   91         SSL_CTX_free(con->ssl_ctx);
   92 #endif
   93     if (con->sock > 0) close(con->sock);
   94     free(con);
   95     con = NULL;
   96 }
   97 
   98 static enum test_return cache_create_test(void)
   99 {
  100     cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*));
  101     assert(cache != NULL);
  102     cache_destroy(cache);
  103     return TEST_PASS;
  104 }
  105 
  106 static enum test_return cache_reuse_test(void)
  107 {
  108     int ii;
  109     cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*));
  110     if (cache == NULL) {
  111         return TEST_FAIL;
  112     }
  113     char *ptr = cache_alloc(cache);
  114     cache_free(cache, ptr);
  115     for (ii = 0; ii < 100; ++ii) {
  116         char *p = cache_alloc(cache);
  117         assert(p == ptr);
  118         cache_free(cache, ptr);
  119     }
  120     cache_destroy(cache);
  121     return TEST_PASS;
  122 }
  123 
  124 
  125 static enum test_return cache_bulkalloc(size_t datasize)
  126 {
  127     cache_t *cache = cache_create("test", datasize, sizeof(char*));
  128     if (cache == NULL) {
  129         return TEST_FAIL;
  130     }
  131 #define ITERATIONS 1024
  132     void *ptr[ITERATIONS];
  133 
  134     for (int ii = 0; ii < ITERATIONS; ++ii) {
  135         ptr[ii] = cache_alloc(cache);
  136         assert(ptr[ii] != 0);
  137         memset(ptr[ii], 0xff, datasize);
  138     }
  139 
  140     for (int ii = 0; ii < ITERATIONS; ++ii) {
  141         cache_free(cache, ptr[ii]);
  142     }
  143 
  144 #undef ITERATIONS
  145     cache_destroy(cache);
  146     return TEST_PASS;
  147 }
  148 
  149 static enum test_return test_issue_161(void)
  150 {
  151     enum test_return ret = cache_bulkalloc(1);
  152     if (ret == TEST_PASS) {
  153         ret = cache_bulkalloc(512);
  154     }
  155 
  156     return ret;
  157 }
  158 
  159 static enum test_return cache_redzone_test(void)
  160 {
  161 #ifndef HAVE_UMEM_H
  162     cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*));
  163 
  164     if (cache == NULL) {
  165         return TEST_FAIL;
  166     }
  167     /* Ignore SIGABRT */
  168     struct sigaction old_action;
  169     struct sigaction action = { .sa_handler = SIG_IGN, .sa_flags = 0};
  170     sigemptyset(&action.sa_mask);
  171     sigaction(SIGABRT, &action, &old_action);
  172 
  173     /* check memory debug.. */
  174     char *p = cache_alloc(cache);
  175     char old = *(p - 1);
  176     *(p - 1) = 0;
  177     cache_free(cache, p);
  178     assert(cache_error == -1);
  179     *(p - 1) = old;
  180 
  181     p[sizeof(uint32_t)] = 0;
  182     cache_free(cache, p);
  183     assert(cache_error == 1);
  184 
  185     /* restore signal handler */
  186     sigaction(SIGABRT, &old_action, NULL);
  187 
  188     cache_destroy(cache);
  189 
  190     return TEST_PASS;
  191 #else
  192     return TEST_SKIP;
  193 #endif
  194 }
  195 
  196 static enum test_return cache_limit_revised_downward_test(void)
  197 {
  198     int limit = 10, allocated_num = limit + 1, i;
  199     char ** alloc_objs = calloc(allocated_num, sizeof(char *));
  200 
  201     cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*));
  202     assert(cache != NULL);
  203 
  204     /* cache->limit is 0 and we can allocate limit+1 items */
  205     for (i = 0; i < allocated_num; i++) {
  206         alloc_objs[i] = cache_alloc(cache);
  207         assert(alloc_objs[i] != NULL);
  208     }
  209     assert(cache->total == allocated_num);
  210 
  211     /* revised downward cache->limit */
  212     cache_set_limit(cache, limit);
  213 
  214     /* If we free one item, the cache->total should decreased by one*/
  215     cache_free(cache, alloc_objs[0]);
  216 
  217     assert(cache->total == allocated_num-1);
  218     cache_destroy(cache);
  219 
  220     return TEST_PASS;
  221 }
  222 
  223 static enum test_return test_stats_prefix_find(void) {
  224     PREFIX_STATS *pfs1, *pfs2;
  225 
  226     stats_prefix_clear();
  227     pfs1 = stats_prefix_find("abc", 3);
  228     assert(pfs1 == NULL);
  229     pfs1 = stats_prefix_find("abc|", 4);
  230     assert(pfs1 == NULL);
  231 
  232     pfs1 = stats_prefix_find("abc:", 4);
  233     assert(pfs1 != NULL);
  234     assert(0ULL == (pfs1->num_gets + pfs1->num_sets + pfs1->num_deletes + pfs1->num_hits));
  235     pfs2 = stats_prefix_find("abc:", 4);
  236     assert(pfs1 == pfs2);
  237     pfs2 = stats_prefix_find("abc:d", 5);
  238     assert(pfs1 == pfs2);
  239     pfs2 = stats_prefix_find("xyz123:", 6);
  240     assert(pfs1 != pfs2);
  241     pfs2 = stats_prefix_find("ab:", 3);
  242     assert(pfs1 != pfs2);
  243     return TEST_PASS;
  244 }
  245 
  246 static enum test_return test_stats_prefix_record_get(void) {
  247     PREFIX_STATS *pfs;
  248     stats_prefix_clear();
  249 
  250     stats_prefix_record_get("abc:123", 7, false);
  251     pfs = stats_prefix_find("abc:123", 7);
  252     if (pfs == NULL) {
  253         return TEST_FAIL;
  254     }
  255     assert(1 == pfs->num_gets);
  256     assert(0 == pfs->num_hits);
  257     stats_prefix_record_get("abc:456", 7, false);
  258     assert(2 == pfs->num_gets);
  259     assert(0 == pfs->num_hits);
  260     stats_prefix_record_get("abc:456", 7, true);
  261     assert(3 == pfs->num_gets);
  262     assert(1 == pfs->num_hits);
  263     stats_prefix_record_get("def:", 4, true);
  264     assert(3 == pfs->num_gets);
  265     assert(1 == pfs->num_hits);
  266     return TEST_PASS;
  267 }
  268 
  269 static enum test_return test_stats_prefix_record_delete(void) {
  270     PREFIX_STATS *pfs;
  271     stats_prefix_clear();
  272 
  273     stats_prefix_record_delete("abc:123", 7);
  274     pfs = stats_prefix_find("abc:123", 7);
  275     if (pfs == NULL) {
  276         return TEST_FAIL;
  277     }
  278     assert(0 == pfs->num_gets);
  279     assert(0 == pfs->num_hits);
  280     assert(1 == pfs->num_deletes);
  281     assert(0 == pfs->num_sets);
  282     stats_prefix_record_delete("def:", 4);
  283     assert(1 == pfs->num_deletes);
  284     return TEST_PASS;
  285 }
  286 
  287 static enum test_return test_stats_prefix_record_set(void) {
  288     PREFIX_STATS *pfs;
  289     stats_prefix_clear();
  290 
  291     stats_prefix_record_set("abc:123", 7);
  292     pfs = stats_prefix_find("abc:123", 7);
  293     if (pfs == NULL) {
  294         return TEST_FAIL;
  295     }
  296     assert(0 == pfs->num_gets);
  297     assert(0 == pfs->num_hits);
  298     assert(0 == pfs->num_deletes);
  299     assert(1 == pfs->num_sets);
  300     stats_prefix_record_delete("def:", 4);
  301     assert(1 == pfs->num_sets);
  302     return TEST_PASS;
  303 }
  304 
  305 static enum test_return test_stats_prefix_dump(void) {
  306     int hashval = hash("abc", 3) % PREFIX_HASH_SIZE;
  307     char tmp[500];
  308     char *buf;
  309     const char *expected;
  310     int keynum;
  311     int length;
  312 
  313     stats_prefix_clear();
  314 
  315     assert(strcmp("END\r\n", (buf = stats_prefix_dump(&length))) == 0);
  316     assert(5 == length);
  317     stats_prefix_record_set("abc:123", 7);
  318     free(buf);
  319     expected = "PREFIX abc get 0 hit 0 set 1 del 0\r\nEND\r\n";
  320     assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0);
  321     assert(strlen(expected) == length);
  322     stats_prefix_record_get("abc:123", 7, false);
  323     free(buf);
  324     expected = "PREFIX abc get 1 hit 0 set 1 del 0\r\nEND\r\n";
  325     assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0);
  326     assert(strlen(expected) == length);
  327     stats_prefix_record_get("abc:123", 7, true);
  328     free(buf);
  329     expected = "PREFIX abc get 2 hit 1 set 1 del 0\r\nEND\r\n";
  330     assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0);
  331     assert(strlen(expected) == length);
  332     stats_prefix_record_delete("abc:123", 7);
  333     free(buf);
  334     expected = "PREFIX abc get 2 hit 1 set 1 del 1\r\nEND\r\n";
  335     assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0);
  336     assert(strlen(expected) == length);
  337 
  338     stats_prefix_record_delete("def:123", 7);
  339     free(buf);
  340     /* NOTE: Prefixes can be dumped in any order, so we verify that
  341        each expected line is present in the string. */
  342     buf = stats_prefix_dump(&length);
  343     assert(strstr(buf, "PREFIX abc get 2 hit 1 set 1 del 1\r\n") != NULL);
  344     assert(strstr(buf, "PREFIX def get 0 hit 0 set 0 del 1\r\n") != NULL);
  345     assert(strstr(buf, "END\r\n") != NULL);
  346     free(buf);
  347 
  348     /* Find a key that hashes to the same bucket as "abc" */
  349     bool found_match = false;
  350     for (keynum = 0; keynum < PREFIX_HASH_SIZE * 100; keynum++) {
  351         snprintf(tmp, sizeof(tmp), "%d:", keynum);
  352         /* -1 because only the prefix portion is used when hashing */
  353         if (hashval == hash(tmp, strlen(tmp) - 1) % PREFIX_HASH_SIZE) {
  354             found_match = true;
  355             break;
  356         }
  357     }
  358     assert(found_match);
  359     stats_prefix_record_set(tmp, strlen(tmp));
  360     buf = stats_prefix_dump(&length);
  361     assert(strstr(buf, "PREFIX abc get 2 hit 1 set 1 del 1\r\n") != NULL);
  362     assert(strstr(buf, "PREFIX def get 0 hit 0 set 0 del 1\r\n") != NULL);
  363     assert(strstr(buf, "END\r\n") != NULL);
  364     snprintf(tmp, sizeof(tmp), "PREFIX %d get 0 hit 0 set 1 del 0\r\n", keynum);
  365     assert(strstr(buf, tmp) != NULL);
  366     free(buf);
  367 
  368     /* Marking the end of these tests */
  369     stats_prefix_clear();
  370 
  371     return TEST_PASS;
  372 }
  373 
  374 static enum test_return test_safe_strtoul(void) {
  375     uint32_t val;
  376     assert(safe_strtoul("123", &val));
  377     assert(val == 123);
  378     assert(safe_strtoul("+123", &val));
  379     assert(val == 123);
  380     assert(!safe_strtoul("", &val));  // empty
  381     assert(!safe_strtoul("123BOGUS", &val));  // non-numeric
  382     assert(!safe_strtoul(" issue221", &val));  // non-numeric
  383     /* Not sure what it does, but this works with ICC :/
  384        assert(!safe_strtoul("92837498237498237498029383", &val)); // out of range
  385     */
  386 
  387     // extremes:
  388     assert(safe_strtoul("4294967295", &val)); // 2**32 - 1
  389     assert(val == 4294967295L);
  390     /* This actually works on 64-bit ubuntu
  391        assert(!safe_strtoul("4294967296", &val)); // 2**32
  392     */
  393     assert(!safe_strtoul("-1", &val));  // negative
  394     return TEST_PASS;
  395 }
  396 
  397 
  398 static enum test_return test_safe_strtoull(void) {
  399     uint64_t val;
  400     assert(safe_strtoull("123", &val));
  401     assert(val == 123);
  402     assert(safe_strtoull("+123", &val));
  403     assert(val == 123);
  404     assert(!safe_strtoull("", &val));  // empty
  405     assert(!safe_strtoull("123BOGUS", &val));  // non-numeric
  406     assert(!safe_strtoull("92837498237498237498029383", &val)); // out of range
  407     assert(!safe_strtoull(" issue221", &val));  // non-numeric
  408 
  409     // extremes:
  410     assert(safe_strtoull("18446744073709551615", &val)); // 2**64 - 1
  411     assert(val == 18446744073709551615ULL);
  412     assert(!safe_strtoull("18446744073709551616", &val)); // 2**64
  413     assert(!safe_strtoull("-1", &val));  // negative
  414     return TEST_PASS;
  415 }
  416 
  417 static enum test_return test_safe_strtoll(void) {
  418     int64_t val;
  419     assert(safe_strtoll("123", &val));
  420     assert(val == 123);
  421     assert(safe_strtoll("+123", &val));
  422     assert(val == 123);
  423     assert(safe_strtoll("-123", &val));
  424     assert(val == -123);
  425     assert(!safe_strtoll("", &val));  // empty
  426     assert(!safe_strtoll("123BOGUS", &val));  // non-numeric
  427     assert(!safe_strtoll("92837498237498237498029383", &val)); // out of range
  428     assert(!safe_strtoll(" issue221", &val));  // non-numeric
  429 
  430     // extremes:
  431     assert(!safe_strtoll("18446744073709551615", &val)); // 2**64 - 1
  432     assert(safe_strtoll("9223372036854775807", &val)); // 2**63 - 1
  433     assert(val == 9223372036854775807LL);
  434     /*
  435       assert(safe_strtoll("-9223372036854775808", &val)); // -2**63
  436       assert(val == -9223372036854775808LL);
  437     */
  438     assert(!safe_strtoll("-9223372036854775809", &val)); // -2**63 - 1
  439 
  440     // We'll allow space to terminate the string.  And leading space.
  441     assert(safe_strtoll(" 123 foo", &val));
  442     assert(val == 123);
  443     return TEST_PASS;
  444 }
  445 
  446 static enum test_return test_safe_strtol(void) {
  447     int32_t val;
  448     assert(safe_strtol("123", &val));
  449     assert(val == 123);
  450     assert(safe_strtol("+123", &val));
  451     assert(val == 123);
  452     assert(safe_strtol("-123", &val));
  453     assert(val == -123);
  454     assert(!safe_strtol("", &val));  // empty
  455     assert(!safe_strtol("123BOGUS", &val));  // non-numeric
  456     assert(!safe_strtol("92837498237498237498029383", &val)); // out of range
  457     assert(!safe_strtol(" issue221", &val));  // non-numeric
  458 
  459     // extremes:
  460     /* This actually works on 64-bit ubuntu
  461        assert(!safe_strtol("2147483648", &val)); // (expt 2.0 31.0)
  462     */
  463     assert(safe_strtol("2147483647", &val)); // (- (expt 2.0 31) 1)
  464     assert(val == 2147483647L);
  465     /* This actually works on 64-bit ubuntu
  466        assert(!safe_strtol("-2147483649", &val)); // (- (expt -2.0 31) 1)
  467     */
  468 
  469     // We'll allow space to terminate the string.  And leading space.
  470     assert(safe_strtol(" 123 foo", &val));
  471     assert(val == 123);
  472     return TEST_PASS;
  473 }
  474 
  475 /**
  476  * Function to start the server and let it listen on a random port
  477  *
  478  * @param port_out where to store the TCP port number the server is
  479  *                 listening on
  480  * @param daemon set to true if you want to run the memcached server
  481  *               as a daemon process
  482  * @return the pid of the memcached server
  483  */
  484 static pid_t start_server(in_port_t *port_out, bool daemon, int timeout) {
  485     char environment[80];
  486     snprintf(environment, sizeof(environment),
  487              "MEMCACHED_PORT_FILENAME=/tmp/ports.%lu", (long)getpid());
  488     char *filename= environment + strlen("MEMCACHED_PORT_FILENAME=");
  489     char pid_file[80];
  490     snprintf(pid_file, sizeof(pid_file), "/tmp/pid.%lu", (long)getpid());
  491 
  492     remove(filename);
  493     remove(pid_file);
  494 
  495 #ifdef __sun
  496     /* I want to name the corefiles differently so that they don't
  497        overwrite each other
  498     */
  499     char coreadm[128];
  500     snprintf(coreadm, sizeof(coreadm),
  501              "coreadm -p core.%%f.%%p %lu", (unsigned long)getpid());
  502     system(coreadm);
  503 #endif
  504 
  505     pid_t pid = fork();
  506     assert(pid != -1);
  507     if (pid == 0) {
  508         /* Child */
  509         char *argv[24];
  510         int arg = 0;
  511         char tmo[24];
  512         snprintf(tmo, sizeof(tmo), "%u", timeout);
  513 
  514         putenv(environment);
  515 #ifdef __sun
  516         putenv("LD_PRELOAD=watchmalloc.so.1");
  517         putenv("MALLOC_DEBUG=WATCH");
  518 #endif
  519 
  520         if (!daemon) {
  521             argv[arg++] = "./timedrun";
  522             argv[arg++] = tmo;
  523         }
  524         argv[arg++] = "./memcached-debug";
  525         argv[arg++] = "-A";
  526         argv[arg++] = "-p";
  527         argv[arg++] = "-1";
  528         argv[arg++] = "-U";
  529         argv[arg++] = "0";
  530 #ifdef TLS
  531         if (enable_ssl) {
  532             argv[arg++] = "-Z";
  533             argv[arg++] = "-o";
  534             argv[arg++] = "ssl_chain_cert=t/server_crt.pem";
  535             argv[arg++] = "-o";
  536             argv[arg++] = "ssl_key=t/server_key.pem";
  537         }
  538 #endif
  539         /* Handle rpmbuild and the like doing this as root */
  540         if (getuid() == 0) {
  541             argv[arg++] = "-u";
  542             argv[arg++] = "root";
  543         }
  544         if (daemon) {
  545             argv[arg++] = "-d";
  546             argv[arg++] = "-P";
  547             argv[arg++] = pid_file;
  548         }
  549 #ifdef MESSAGE_DEBUG
  550          argv[arg++] = "-vvv";
  551 #endif
  552 #ifdef HAVE_DROP_PRIVILEGES
  553         argv[arg++] = "-o";
  554         argv[arg++] = "relaxed_privileges";
  555 #endif
  556         argv[arg++] = NULL;
  557         assert(execv(argv[0], argv) != -1);
  558     }
  559 
  560     /* Yeah just let us "busy-wait" for the file to be created ;-) */
  561     useconds_t wait_timeout = 1000000 * 10;
  562     useconds_t wait = 1000;
  563     while (access(filename, F_OK) == -1 && wait_timeout > 0) {
  564         usleep(wait);
  565         wait_timeout -= (wait > wait_timeout ? wait_timeout : wait);
  566     }
  567 
  568     if (access(filename, F_OK) == -1) {
  569         fprintf(stderr, "Failed to start the memcached server.\n");
  570         assert(false);
  571     }
  572 
  573     FILE *fp = fopen(filename, "r");
  574     if (fp == NULL) {
  575         fprintf(stderr, "Failed to open the file containing port numbers: %s\n",
  576                 strerror(errno));
  577         assert(false);
  578     }
  579 
  580     *port_out = (in_port_t)-1;
  581     char buffer[80];
  582     while ((fgets(buffer, sizeof(buffer), fp)) != NULL) {
  583         if (strncmp(buffer, "TCP INET: ", 10) == 0) {
  584             int32_t val;
  585             assert(safe_strtol(buffer + 10, &val));
  586             *port_out = (in_port_t)val;
  587         }
  588     }
  589     fclose(fp);
  590     assert(remove(filename) == 0);
  591 
  592     if (daemon) {
  593         /* loop and wait for the pid file.. There is a potential race
  594          * condition that the server just created the file but isn't
  595          * finished writing the content, so we loop a few times
  596          * reading as well */
  597         while (access(pid_file, F_OK) == -1) {
  598             usleep(10);
  599         }
  600 
  601         fp = fopen(pid_file, "r");
  602         if (fp == NULL) {
  603             fprintf(stderr, "Failed to open pid file: %s\n",
  604                     strerror(errno));
  605             assert(false);
  606         }
  607 
  608         /* Avoid race by retrying 20 times */
  609         for (int x = 0; x < 20 && fgets(buffer, sizeof(buffer), fp) == NULL; x++) {
  610             usleep(10);
  611         }
  612         fclose(fp);
  613 
  614         int32_t val;
  615         assert(safe_strtol(buffer, &val));
  616         pid = (pid_t)val;
  617     }
  618 
  619     return pid;
  620 }
  621 
  622 static enum test_return test_issue_44(void) {
  623     in_port_t port;
  624     pid_t pid = start_server(&port, true, 600);
  625     assert(kill(pid, SIGHUP) == 0);
  626     sleep(1);
  627     assert(kill(pid, SIGTERM) == 0);
  628 
  629     return TEST_PASS;
  630 }
  631 
  632 static struct addrinfo *lookuphost(const char *hostname, in_port_t port)
  633 {
  634     struct addrinfo *ai = 0;
  635     struct addrinfo hints = { .ai_family = AF_UNSPEC,
  636                               .ai_protocol = IPPROTO_TCP,
  637                               .ai_socktype = SOCK_STREAM };
  638     char service[NI_MAXSERV];
  639     int error;
  640 
  641     (void)snprintf(service, NI_MAXSERV, "%d", port);
  642     if ((error = getaddrinfo(hostname, service, &hints, &ai)) != 0) {
  643        if (error != EAI_SYSTEM) {
  644           fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
  645        } else {
  646           perror("getaddrinfo()");
  647        }
  648     }
  649 
  650     return ai;
  651 }
  652 
  653 static struct conn *connect_server(const char *hostname, in_port_t port,
  654                             bool nonblock, const bool ssl)
  655 {
  656     struct conn *c;
  657     if (!(c = (struct conn *)calloc(1, sizeof(struct conn)))) {
  658         fprintf(stderr, "Failed to allocate the client connection: %s\n",
  659                 strerror(errno));
  660         return NULL;
  661     }
  662 
  663     struct addrinfo *ai = lookuphost(hostname, port);
  664     int sock = -1;
  665     if (ai != NULL) {
  666        if ((sock = socket(ai->ai_family, ai->ai_socktype,
  667                           ai->ai_protocol)) != -1) {
  668           if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
  669              fprintf(stderr, "Failed to connect socket: %s\n",
  670                      strerror(errno));
  671              close(sock);
  672              sock = -1;
  673           } else if (nonblock) {
  674               int flags = fcntl(sock, F_GETFL, 0);
  675               if (flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
  676                   fprintf(stderr, "Failed to enable nonblocking mode: %s\n",
  677                           strerror(errno));
  678                   close(sock);
  679                   sock = -1;
  680               }
  681           }
  682        } else {
  683           fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
  684        }
  685 
  686        freeaddrinfo(ai);
  687     }
  688     c->sock = sock;
  689 #ifdef TLS
  690     if (sock > 0 && ssl) {
  691         c->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
  692         if (c->ssl_ctx == NULL) {
  693             fprintf(stderr, "Failed to create the SSL context: %s\n",
  694                 strerror(errno));
  695             close(sock);
  696             sock = -1;
  697         }
  698         c->ssl = SSL_new(c->ssl_ctx);
  699         if (c->ssl == NULL) {
  700             fprintf(stderr, "Failed to create the SSL object: %s\n",
  701                 strerror(errno));
  702             close(sock);
  703             sock = -1;
  704         }
  705         SSL_set_fd (c->ssl, c->sock);
  706         int ret = SSL_connect(c->ssl);
  707         if (ret < 0) {
  708             int err = SSL_get_error(c->ssl, ret);
  709             if (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL) {
  710                 fprintf(stderr, "SSL connection failed with error code : %s\n",
  711                     strerror(errno));
  712                 close(sock);
  713                 sock = -1;
  714             }
  715         }
  716         c->read = ssl_read;
  717         c->write = ssl_write;
  718     } else
  719 #endif
  720     {
  721         c->read = tcp_read;
  722         c->write = tcp_write;
  723     }
  724     return c;
  725 }
  726 
  727 static enum test_return test_vperror(void) {
  728     int rv = 0;
  729     int oldstderr = dup(STDERR_FILENO);
  730     assert(oldstderr >= 0);
  731     char tmpl[sizeof(TMP_TEMPLATE)+1];
  732     strncpy(tmpl, TMP_TEMPLATE, sizeof(TMP_TEMPLATE)+1);
  733 
  734     int newfile = mkstemp(tmpl);
  735     assert(newfile > 0);
  736     rv = dup2(newfile, STDERR_FILENO);
  737     assert(rv == STDERR_FILENO);
  738     rv = close(newfile);
  739     assert(rv == 0);
  740 
  741     errno = EIO;
  742     vperror("Old McDonald had a farm.  %s", "EI EIO");
  743 
  744     /* Restore stderr */
  745     rv = dup2(oldstderr, STDERR_FILENO);
  746     assert(rv == STDERR_FILENO);
  747 
  748 
  749     /* Go read the file */
  750     char buf[80] = { 0 };
  751     FILE *efile = fopen(tmpl, "r");
  752     assert(efile);
  753     char *prv = fgets(buf, sizeof(buf), efile);
  754     assert(prv);
  755     fclose(efile);
  756 
  757     unlink(tmpl);
  758 
  759     char expected[80] = { 0 };
  760     snprintf(expected, sizeof(expected),
  761              "Old McDonald had a farm.  EI EIO: %s\n", strerror(EIO));
  762 
  763     /*
  764     fprintf(stderr,
  765             "\nExpected:  ``%s''"
  766             "\nGot:       ``%s''\n", expected, buf);
  767     */
  768 
  769     return strcmp(expected, buf) == 0 ? TEST_PASS : TEST_FAIL;
  770 }
  771 
  772 static void send_ascii_command(const char *buf) {
  773     off_t offset = 0;
  774     const char* ptr = buf;
  775     size_t len = strlen(buf);
  776 
  777     do {
  778         ssize_t nw = con->write((void*)con, ptr + offset, len - offset);
  779         if (nw == -1) {
  780             if (errno != EINTR) {
  781                 fprintf(stderr, "Failed to write: %s\n", strerror(errno));
  782                 abort();
  783             }
  784         } else {
  785             offset += nw;
  786         }
  787     } while (offset < len);
  788 }
  789 
  790 /*
  791  * This is a dead slow single byte read, but it should only read out
  792  * _one_ response and I don't have an input buffer... The current
  793  * implementation only supports single-line responses, so if you want to use
  794  * it for get commands you need to implement that first ;-)
  795  */
  796 static void read_ascii_response(char *buffer, size_t size) {
  797     off_t offset = 0;
  798     bool need_more = true;
  799     do {
  800         ssize_t nr = con->read(con, buffer + offset, 1);
  801         if (nr == -1) {
  802             if (errno != EINTR) {
  803                 fprintf(stderr, "Failed to read: %s\n", strerror(errno));
  804                 abort();
  805             }
  806         } else {
  807             assert(nr == 1);
  808             if (buffer[offset] == '\n') {
  809                 need_more = false;
  810                 buffer[offset + 1] = '\0';
  811             }
  812             offset += nr;
  813             assert(offset + 1 < size);
  814         }
  815     } while (need_more);
  816 }
  817 
  818 static enum test_return test_issue_92(void) {
  819     char buffer[1024];
  820 
  821     close_conn();
  822     con = connect_server("127.0.0.1", port, false, enable_ssl);
  823     assert(con);
  824 
  825     send_ascii_command("stats cachedump 1 0 0\r\n");
  826 
  827     read_ascii_response(buffer, sizeof(buffer));
  828     assert(strncmp(buffer, "END", strlen("END")) == 0);
  829 
  830     send_ascii_command("stats cachedump 200 0 0\r\n");
  831     read_ascii_response(buffer, sizeof(buffer));
  832     assert(strncmp(buffer, "CLIENT_ERROR", strlen("CLIENT_ERROR")) == 0);
  833 
  834     close_conn();
  835     con = connect_server("127.0.0.1", port, false, enable_ssl);
  836     assert(con);
  837     return TEST_PASS;
  838 }
  839 
  840 static enum test_return test_crc32c(void) {
  841     uint32_t crc_hw, crc_sw;
  842 
  843     char buffer[256];
  844     for (int x = 0; x < 256; x++)
  845         buffer[x] = x;
  846 
  847     /* Compare hardware to software implementation */
  848     crc_hw = crc32c(0, buffer, 256);
  849     crc_sw = crc32c_sw(0, buffer, 256);
  850     assert(crc_hw == 0x9c44184b);
  851     assert(crc_sw == 0x9c44184b);
  852 
  853     /* Test that passing a CRC in also works */
  854     crc_hw = crc32c(crc_hw, buffer, 256);
  855     crc_sw = crc32c_sw(crc_sw, buffer, 256);
  856     assert(crc_hw == 0xae10ee5a);
  857     assert(crc_sw == 0xae10ee5a);
  858 
  859     /* Test odd offsets/sizes */
  860     crc_hw = crc32c(crc_hw, buffer + 1, 256 - 2);
  861     crc_sw = crc32c_sw(crc_sw, buffer + 1, 256 - 2);
  862     assert(crc_hw == 0xed37b906);
  863     assert(crc_sw == 0xed37b906);
  864 
  865     return TEST_PASS;
  866 }
  867 
  868 static enum test_return test_issue_102(void) {
  869     char buffer[4096];
  870     memset(buffer, ' ', sizeof(buffer));
  871     buffer[sizeof(buffer) - 1] = '\0';
  872 
  873     close_conn();
  874     con = connect_server("127.0.0.1", port, false, enable_ssl);
  875     assert(con);
  876 
  877     send_ascii_command(buffer);
  878     /* verify that the server closed the connection */
  879     assert(con->read(con, buffer, sizeof(buffer)) == 0);
  880 
  881     close_conn();
  882     con = connect_server("127.0.0.1", port, false, enable_ssl);
  883     assert(con);
  884 
  885     snprintf(buffer, sizeof(buffer), "gets ");
  886     size_t offset = 5;
  887     while (offset < 4000) {
  888         offset += snprintf(buffer + offset, sizeof(buffer) - offset,
  889                            "%010u ", (unsigned int)offset);
  890     }
  891 
  892     send_ascii_command(buffer);
  893     usleep(250);
  894 
  895     send_ascii_command("\r\n");
  896     char rsp[80];
  897     read_ascii_response(rsp, sizeof(rsp));
  898     assert(strncmp(rsp, "END", strlen("END")) == 0);
  899     buffer[3]= ' ';
  900     send_ascii_command(buffer);
  901     usleep(250);
  902     send_ascii_command("\r\n");
  903     read_ascii_response(rsp, sizeof(rsp));
  904     assert(strncmp(rsp, "END", strlen("END")) == 0);
  905 
  906     memset(buffer, ' ', sizeof(buffer));
  907     int len = snprintf(buffer + 101, sizeof(buffer) - 101, "gets foo");
  908     buffer[101 + len] = ' ';
  909     buffer[sizeof(buffer) - 1] = '\0';
  910     send_ascii_command(buffer);
  911     /* verify that the server closed the connection */
  912     assert(con->read(con, buffer, sizeof(buffer)) == 0);
  913 
  914     close_conn();
  915     con = connect_server("127.0.0.1", port, false, enable_ssl);
  916     assert(con);
  917 
  918     return TEST_PASS;
  919 }
  920 
  921 static enum test_return start_memcached_server(void) {
  922     server_pid = start_server(&port, false, 600);
  923     close_conn();
  924     con = connect_server("127.0.0.1", port, false, enable_ssl);
  925     assert(con);
  926     return TEST_PASS;
  927 }
  928 
  929 static enum test_return stop_memcached_server(void) {
  930     close_conn();
  931     if (server_pid != -1) {
  932         assert(kill(server_pid, SIGTERM) == 0);
  933     }
  934 
  935     return TEST_PASS;
  936 }
  937 
  938 static enum test_return shutdown_memcached_server(void) {
  939     char buffer[1024];
  940 
  941     close_conn();
  942     con = connect_server("127.0.0.1", port, false, enable_ssl);
  943     assert(con);
  944 
  945     send_ascii_command("shutdown\r\n");
  946     /* verify that the server closed the connection */
  947     assert(con->read(con, buffer, sizeof(buffer)) == 0);
  948 
  949     close_conn();
  950 
  951     /* We set server_pid to -1 so that we don't later call kill() */
  952     if (kill(server_pid, 0) == 0) {
  953         server_pid = -1;
  954     }
  955 
  956     return TEST_PASS;
  957 }
  958 
  959 static void safe_send(const void* buf, size_t len, bool hickup)
  960 {
  961     off_t offset = 0;
  962     const char* ptr = buf;
  963 #ifdef MESSAGE_DEBUG
  964     uint8_t val = *ptr;
  965     assert(val == (uint8_t)0x80);
  966     fprintf(stderr, "About to send %lu bytes:", (unsigned long)len);
  967     for (int ii = 0; ii < len; ++ii) {
  968         if (ii % 4 == 0) {
  969             fprintf(stderr, "\n   ");
  970         }
  971         val = *(ptr + ii);
  972         fprintf(stderr, " 0x%02x", val);
  973     }
  974     fprintf(stderr, "\n");
  975     usleep(500);
  976 #endif
  977 
  978     do {
  979         size_t num_bytes = len - offset;
  980         if (hickup) {
  981             if (num_bytes > 1024) {
  982                 num_bytes = (rand() % 1023) + 1;
  983             }
  984         }
  985         ssize_t nw = con->write(con, ptr + offset, num_bytes);
  986         if (nw == -1) {
  987             if (errno != EINTR) {
  988                 fprintf(stderr, "Failed to write: %s\n", strerror(errno));
  989                 abort();
  990             }
  991         } else {
  992             if (hickup) {
  993                 usleep(100);
  994             }
  995             offset += nw;
  996         }
  997     } while (offset < len);
  998 }
  999 
 1000 static bool safe_recv(void *buf, size_t len) {
 1001     if (len == 0) {
 1002         return true;
 1003     }
 1004     off_t offset = 0;
 1005     do {
 1006         ssize_t nr = con->read(con, ((char*)buf) + offset, len - offset);
 1007         if (nr == -1) {
 1008             if (errno != EINTR) {
 1009                 fprintf(stderr, "Failed to read: %s\n", strerror(errno));
 1010                 abort();
 1011             }
 1012         } else {
 1013             if (nr == 0 && allow_closed_read) {
 1014                 return false;
 1015             }
 1016             assert(nr != 0);
 1017             offset += nr;
 1018         }
 1019     } while (offset < len);
 1020 
 1021     return true;
 1022 }
 1023 
 1024 static bool safe_recv_packet(void *buf, size_t size) {
 1025     protocol_binary_response_no_extras *response = buf;
 1026     assert(size > sizeof(*response));
 1027     if (!safe_recv(response, sizeof(*response))) {
 1028         return false;
 1029     }
 1030     response->message.header.response.keylen = ntohs(response->message.header.response.keylen);
 1031     response->message.header.response.status = ntohs(response->message.header.response.status);
 1032     response->message.header.response.bodylen = ntohl(response->message.header.response.bodylen);
 1033 
 1034     size_t len = sizeof(*response);
 1035 
 1036     char *ptr = buf;
 1037     ptr += len;
 1038     if (!safe_recv(ptr, response->message.header.response.bodylen)) {
 1039         return false;
 1040     }
 1041 
 1042 #ifdef MESSAGE_DEBUG
 1043     usleep(500);
 1044     ptr = buf;
 1045     len += response->message.header.response.bodylen;
 1046     uint8_t val = *ptr;
 1047     assert(val == (uint8_t)0x81);
 1048     fprintf(stderr, "Received %lu bytes:", (unsigned long)len);
 1049     for (int ii = 0; ii < len; ++ii) {
 1050         if (ii % 4 == 0) {
 1051             fprintf(stderr, "\n   ");
 1052         }
 1053         val = *(ptr + ii);
 1054         fprintf(stderr, " 0x%02x", val);
 1055     }
 1056     fprintf(stderr, "\n");
 1057 #endif
 1058     return true;
 1059 }
 1060 
 1061 static off_t storage_command(char*buf,
 1062                              size_t bufsz,
 1063                              uint8_t cmd,
 1064                              const void* key,
 1065                              size_t keylen,
 1066                              const void* dta,
 1067                              size_t dtalen,
 1068                              uint32_t flags,
 1069                              uint32_t exp) {
 1070     /* all of the storage commands use the same command layout */
 1071     protocol_binary_request_set *request = (void*)buf;
 1072     assert(bufsz > sizeof(*request) + keylen + dtalen);
 1073 
 1074     memset(request, 0, sizeof(*request));
 1075     request->message.header.request.magic = PROTOCOL_BINARY_REQ;
 1076     request->message.header.request.opcode = cmd;
 1077     request->message.header.request.keylen = htons(keylen);
 1078     request->message.header.request.extlen = 8;
 1079     request->message.header.request.bodylen = htonl(keylen + 8 + dtalen);
 1080     request->message.header.request.opaque = 0xdeadbeef;
 1081     request->message.body.flags = flags;
 1082     request->message.body.expiration = exp;
 1083 
 1084     off_t key_offset = sizeof(protocol_binary_request_no_extras) + 8;
 1085 
 1086     memcpy(buf + key_offset, key, keylen);
 1087     if (dta != NULL) {
 1088         memcpy(buf + key_offset + keylen, dta, dtalen);
 1089     }
 1090 
 1091     return key_offset + keylen + dtalen;
 1092 }
 1093 
 1094 static off_t ext_command(char* buf,
 1095                          size_t bufsz,
 1096                          uint8_t cmd,
 1097                          const void* ext,
 1098                          size_t extlen,
 1099                          const void* key,
 1100                          size_t keylen,
 1101                          const void* dta,
 1102                          size_t dtalen) {
 1103     protocol_binary_request_no_extras *request = (void*)buf;
 1104     assert(bufsz > sizeof(*request) + extlen + keylen + dtalen);
 1105 
 1106     memset(request, 0, sizeof(*request));
 1107     request->message.header.request.magic = PROTOCOL_BINARY_REQ;
 1108     request->message.header.request.opcode = cmd;
 1109     request->message.header.request.extlen = extlen;
 1110     request->message.header.request.keylen = htons(keylen);
 1111     request->message.header.request.bodylen = htonl(extlen + keylen + dtalen);
 1112     request->message.header.request.opaque = 0xdeadbeef;
 1113 
 1114     off_t ext_offset = sizeof(protocol_binary_request_no_extras);
 1115     off_t key_offset = ext_offset + extlen;
 1116     off_t dta_offset = key_offset + keylen;
 1117 
 1118     if (ext != NULL) {
 1119         memcpy(buf + ext_offset, ext, extlen);
 1120     }
 1121     if (key != NULL) {
 1122         memcpy(buf + key_offset, key, keylen);
 1123     }
 1124     if (dta != NULL) {
 1125         memcpy(buf + dta_offset, dta, dtalen);
 1126     }
 1127 
 1128     return sizeof(*request) + extlen + keylen + dtalen;
 1129 }
 1130 
 1131 static off_t raw_command(char* buf,
 1132                          size_t bufsz,
 1133                          uint8_t cmd,
 1134                          const void* key,
 1135                          size_t keylen,
 1136                          const void* dta,
 1137                          size_t dtalen) {
 1138     /* all of the storage commands use the same command layout */
 1139     return ext_command(buf, bufsz, cmd, NULL, 0, key, keylen, dta, dtalen);
 1140 }
 1141 
 1142 static off_t flush_command(char* buf, size_t bufsz, uint8_t cmd, uint32_t exptime, bool use_extra) {
 1143     protocol_binary_request_flush *request = (void*)buf;
 1144     assert(bufsz > sizeof(*request));
 1145 
 1146     memset(request, 0, sizeof(*request));
 1147     request->message.header.request.magic = PROTOCOL_BINARY_REQ;
 1148     request->message.header.request.opcode = cmd;
 1149 
 1150     off_t size = sizeof(protocol_binary_request_no_extras);
 1151     if (use_extra) {
 1152         request->message.header.request.extlen = 4;
 1153         request->message.body.expiration = htonl(exptime);
 1154         request->message.header.request.bodylen = htonl(4);
 1155         size += 4;
 1156     }
 1157 
 1158     request->message.header.request.opaque = 0xdeadbeef;
 1159 
 1160     return size;
 1161 }
 1162 
 1163 
 1164 static off_t touch_command(char* buf,
 1165                            size_t bufsz,
 1166                            uint8_t cmd,
 1167                            const void* key,
 1168                            size_t keylen,
 1169                            uint32_t exptime) {
 1170     protocol_binary_request_touch *request = (void*)buf;
 1171     assert(bufsz > sizeof(*request));
 1172 
 1173     memset(request, 0, sizeof(*request));
 1174     request->message.header.request.magic = PROTOCOL_BINARY_REQ;
 1175     request->message.header.request.opcode = cmd;
 1176 
 1177     request->message.header.request.keylen = htons(keylen);
 1178     request->message.header.request.extlen = 4;
 1179     request->message.body.expiration = htonl(exptime);
 1180     request->message.header.request.bodylen = htonl(keylen + 4);
 1181 
 1182     request->message.header.request.opaque = 0xdeadbeef;
 1183 
 1184     off_t key_offset = sizeof(protocol_binary_request_no_extras) + 4;
 1185 
 1186     memcpy(buf + key_offset, key, keylen);
 1187     return sizeof(protocol_binary_request_no_extras) + 4 + keylen;
 1188 }
 1189 
 1190 static off_t arithmetic_command(char* buf,
 1191                                 size_t bufsz,
 1192                                 uint8_t cmd,
 1193                                 const void* key,
 1194                                 size_t keylen,
 1195                                 uint64_t delta,
 1196                                 uint64_t initial,
 1197                                 uint32_t exp) {
 1198     protocol_binary_request_incr *request = (void*)buf;
 1199     assert(bufsz > sizeof(*request) + keylen);
 1200 
 1201     memset(request, 0, sizeof(*request));
 1202     request->message.header.request.magic = PROTOCOL_BINARY_REQ;
 1203     request->message.header.request.opcode = cmd;
 1204     request->message.header.request.keylen = htons(keylen);
 1205     request->message.header.request.extlen = 20;
 1206     request->message.header.request.bodylen = htonl(keylen + 20);
 1207     request->message.header.request.opaque = 0xdeadbeef;
 1208     request->message.body.delta = htonll(delta);
 1209     request->message.body.initial = htonll(initial);
 1210     request->message.body.expiration = htonl(exp);
 1211 
 1212     off_t key_offset = sizeof(protocol_binary_request_no_extras) + 20;
 1213 
 1214     memcpy(buf + key_offset, key, keylen);
 1215     return key_offset + keylen;
 1216 }
 1217 
 1218 static void validate_response_header(protocol_binary_response_no_extras *response,
 1219                                      uint8_t cmd, uint16_t status)
 1220 {
 1221     assert(response->message.header.response.magic == PROTOCOL_BINARY_RES);
 1222     assert(response->message.header.response.opcode == cmd);
 1223     assert(response->message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
 1224     assert(response->message.header.response.status == status);
 1225     assert(response->message.header.response.opaque == 0xdeadbeef);
 1226 
 1227     if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
 1228         switch (cmd) {
 1229         case PROTOCOL_BINARY_CMD_ADDQ:
 1230         case PROTOCOL_BINARY_CMD_APPENDQ:
 1231         case PROTOCOL_BINARY_CMD_DECREMENTQ:
 1232         case PROTOCOL_BINARY_CMD_DELETEQ:
 1233         case PROTOCOL_BINARY_CMD_FLUSHQ:
 1234         case PROTOCOL_BINARY_CMD_INCREMENTQ:
 1235         case PROTOCOL_BINARY_CMD_PREPENDQ:
 1236         case PROTOCOL_BINARY_CMD_QUITQ:
 1237         case PROTOCOL_BINARY_CMD_REPLACEQ:
 1238         case PROTOCOL_BINARY_CMD_SETQ:
 1239             assert("Quiet command shouldn't return on success" == NULL);
 1240         default:
 1241             break;
 1242         }
 1243 
 1244         switch (cmd) {
 1245         case PROTOCOL_BINARY_CMD_ADD:
 1246         case PROTOCOL_BINARY_CMD_REPLACE:
 1247         case PROTOCOL_BINARY_CMD_SET:
 1248         case PROTOCOL_BINARY_CMD_APPEND:
 1249         case PROTOCOL_BINARY_CMD_PREPEND:
 1250             assert(response->message.header.response.keylen == 0);
 1251             assert(response->message.header.response.extlen == 0);
 1252             assert(response->message.header.response.bodylen == 0);
 1253             assert(response->message.header.response.cas != 0);
 1254             break;
 1255         case PROTOCOL_BINARY_CMD_FLUSH:
 1256         case PROTOCOL_BINARY_CMD_NOOP:
 1257         case PROTOCOL_BINARY_CMD_QUIT:
 1258         case PROTOCOL_BINARY_CMD_DELETE:
 1259             assert(response->message.header.response.keylen == 0);
 1260             assert(response->message.header.response.extlen == 0);
 1261             assert(response->message.header.response.bodylen == 0);
 1262             assert(response->message.header.response.cas == 0);
 1263             break;
 1264 
 1265         case PROTOCOL_BINARY_CMD_DECREMENT:
 1266         case PROTOCOL_BINARY_CMD_INCREMENT:
 1267             assert(response->message.header.response.keylen == 0);
 1268             assert(response->message.header.response.extlen == 0);
 1269             assert(response->message.header.response.bodylen == 8);
 1270             assert(response->message.header.response.cas != 0);
 1271             break;
 1272 
 1273         case PROTOCOL_BINARY_CMD_STAT:
 1274             assert(response->message.header.response.extlen == 0);
 1275             /* key and value exists in all packets except in the terminating */
 1276             assert(response->message.header.response.cas == 0);
 1277             break;
 1278 
 1279         case PROTOCOL_BINARY_CMD_VERSION:
 1280             assert(response->message.header.response.keylen == 0);
 1281             assert(response->message.header.response.extlen == 0);
 1282             assert(response->message.header.response.bodylen != 0);
 1283             assert(response->message.header.response.cas == 0);
 1284             break;
 1285 
 1286         case PROTOCOL_BINARY_CMD_GET:
 1287         case PROTOCOL_BINARY_CMD_GETQ:
 1288         case PROTOCOL_BINARY_CMD_GAT:
 1289         case PROTOCOL_BINARY_CMD_GATQ:
 1290             assert(response->message.header.response.keylen == 0);
 1291             assert(response->message.header.response.extlen == 4);
 1292             assert(response->message.header.response.cas != 0);
 1293             break;
 1294 
 1295         case PROTOCOL_BINARY_CMD_GETK:
 1296         case PROTOCOL_BINARY_CMD_GETKQ:
 1297         case PROTOCOL_BINARY_CMD_GATK:
 1298         case PROTOCOL_BINARY_CMD_GATKQ:
 1299             assert(response->message.header.response.keylen != 0);
 1300             assert(response->message.header.response.extlen == 4);
 1301             assert(response->message.header.response.cas != 0);
 1302             break;
 1303 
 1304         default:
 1305             /* Undefined command code */
 1306             break;
 1307         }
 1308     } else {
 1309         assert(response->message.header.response.cas == 0);
 1310         assert(response->message.header.response.extlen == 0);
 1311         if (cmd != PROTOCOL_BINARY_CMD_GETK &&
 1312             cmd != PROTOCOL_BINARY_CMD_GATK) {
 1313             assert(response->message.header.response.keylen == 0);
 1314         }
 1315     }
 1316 }
 1317 
 1318 static enum test_return test_binary_noop(void) {
 1319     union {
 1320         protocol_binary_request_no_extras request;
 1321         protocol_binary_response_no_extras response;
 1322         char bytes[1024];
 1323     } buffer;
 1324 
 1325     size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
 1326                              PROTOCOL_BINARY_CMD_NOOP,
 1327                              NULL, 0, NULL, 0);
 1328 
 1329     safe_send(buffer.bytes, len, false);
 1330     safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
 1331     validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_NOOP,
 1332                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1333 
 1334     return TEST_PASS;
 1335 }
 1336 
 1337 static enum test_return test_binary_quit_impl(uint8_t cmd) {
 1338     union {
 1339         protocol_binary_request_no_extras request;
 1340         protocol_binary_response_no_extras response;
 1341         char bytes[1024];
 1342     } buffer;
 1343     size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
 1344                              cmd, NULL, 0, NULL, 0);
 1345 
 1346     safe_send(buffer.bytes, len, false);
 1347     if (cmd == PROTOCOL_BINARY_CMD_QUIT) {
 1348         safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
 1349         validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_QUIT,
 1350                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1351     }
 1352 
 1353     /* Socket should be closed now, read should return 0 */
 1354     assert(con->read(con, buffer.bytes, sizeof(buffer.bytes)) == 0);
 1355     close_conn();
 1356     con = connect_server("127.0.0.1", port, false, enable_ssl);
 1357     assert(con);
 1358 
 1359     return TEST_PASS;
 1360 }
 1361 
 1362 static enum test_return test_binary_quit(void) {
 1363     return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
 1364 }
 1365 
 1366 static enum test_return test_binary_quitq(void) {
 1367     return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
 1368 }
 1369 
 1370 static enum test_return test_binary_set_impl(const char *key, uint8_t cmd) {
 1371     union {
 1372         protocol_binary_request_no_extras request;
 1373         protocol_binary_response_no_extras response;
 1374         char bytes[1024];
 1375     } send, receive;
 1376     uint64_t value = 0xdeadbeefdeadcafe;
 1377     size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd,
 1378                                  key, strlen(key), &value, sizeof(value),
 1379                                  0, 0);
 1380 
 1381     /* Set should work over and over again */
 1382     int ii;
 1383     for (ii = 0; ii < 10; ++ii) {
 1384         safe_send(send.bytes, len, false);
 1385         if (cmd == PROTOCOL_BINARY_CMD_SET) {
 1386             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1387             validate_response_header(&receive.response, cmd,
 1388                                      PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1389         }
 1390     }
 1391 
 1392     if (cmd == PROTOCOL_BINARY_CMD_SETQ) {
 1393         return test_binary_noop();
 1394     }
 1395 
 1396     send.request.message.header.request.cas = receive.response.message.header.response.cas;
 1397     safe_send(send.bytes, len, false);
 1398     if (cmd == PROTOCOL_BINARY_CMD_SET) {
 1399         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1400         validate_response_header(&receive.response, cmd,
 1401                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1402         assert(receive.response.message.header.response.cas != send.request.message.header.request.cas);
 1403     } else {
 1404         return test_binary_noop();
 1405     }
 1406 
 1407     return TEST_PASS;
 1408 }
 1409 
 1410 static enum test_return test_binary_set(void) {
 1411     return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
 1412 }
 1413 
 1414 static enum test_return test_binary_setq(void) {
 1415     return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
 1416 }
 1417 
 1418 
 1419 static enum test_return test_binary_add_impl(const char *key, uint8_t cmd) {
 1420     uint64_t value = 0xdeadbeefdeadcafe;
 1421     union {
 1422         protocol_binary_request_no_extras request;
 1423         protocol_binary_response_no_extras response;
 1424         char bytes[1024];
 1425     } send, receive;
 1426     size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd, key,
 1427                                  strlen(key), &value, sizeof(value),
 1428                                  0, 0);
 1429 
 1430     /* Add should only work the first time */
 1431     int ii;
 1432     for (ii = 0; ii < 10; ++ii) {
 1433         safe_send(send.bytes, len, false);
 1434         if (ii == 0) {
 1435             if (cmd == PROTOCOL_BINARY_CMD_ADD) {
 1436                 safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1437                 validate_response_header(&receive.response, cmd,
 1438                                          PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1439             }
 1440         } else {
 1441             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1442             validate_response_header(&receive.response, cmd,
 1443                                      PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS);
 1444         }
 1445     }
 1446 
 1447     return TEST_PASS;
 1448 }
 1449 
 1450 static enum test_return test_binary_add(void) {
 1451     return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
 1452 }
 1453 
 1454 static enum test_return test_binary_addq(void) {
 1455     return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
 1456 }
 1457 
 1458 static enum test_return test_binary_replace_impl(const char* key, uint8_t cmd) {
 1459     uint64_t value = 0xdeadbeefdeadcafe;
 1460     union {
 1461         protocol_binary_request_no_extras request;
 1462         protocol_binary_response_no_extras response;
 1463         char bytes[1024];
 1464     } send, receive;
 1465     size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd,
 1466                                  key, strlen(key), &value, sizeof(value),
 1467                                  0, 0);
 1468     safe_send(send.bytes, len, false);
 1469     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1470     validate_response_header(&receive.response, cmd,
 1471                              PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1472     len = storage_command(send.bytes, sizeof(send.bytes),
 1473                           PROTOCOL_BINARY_CMD_ADD,
 1474                           key, strlen(key), &value, sizeof(value), 0, 0);
 1475     safe_send(send.bytes, len, false);
 1476     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1477     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1478                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1479 
 1480     len = storage_command(send.bytes, sizeof(send.bytes), cmd,
 1481                           key, strlen(key), &value, sizeof(value), 0, 0);
 1482     int ii;
 1483     for (ii = 0; ii < 10; ++ii) {
 1484         safe_send(send.bytes, len, false);
 1485         if (cmd == PROTOCOL_BINARY_CMD_REPLACE) {
 1486             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1487             validate_response_header(&receive.response,
 1488                                      PROTOCOL_BINARY_CMD_REPLACE,
 1489                                      PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1490         }
 1491     }
 1492 
 1493     if (cmd == PROTOCOL_BINARY_CMD_REPLACEQ) {
 1494         test_binary_noop();
 1495     }
 1496 
 1497     return TEST_PASS;
 1498 }
 1499 
 1500 static enum test_return test_binary_replace(void) {
 1501     return test_binary_replace_impl("test_binary_replace",
 1502                                     PROTOCOL_BINARY_CMD_REPLACE);
 1503 }
 1504 
 1505 static enum test_return test_binary_replaceq(void) {
 1506     return test_binary_replace_impl("test_binary_replaceq",
 1507                                     PROTOCOL_BINARY_CMD_REPLACEQ);
 1508 }
 1509 
 1510 static enum test_return test_binary_delete_impl(const char *key, uint8_t cmd) {
 1511     union {
 1512         protocol_binary_request_no_extras request;
 1513         protocol_binary_response_no_extras response;
 1514         char bytes[1024];
 1515     } send, receive;
 1516     size_t len = raw_command(send.bytes, sizeof(send.bytes), cmd,
 1517                              key, strlen(key), NULL, 0);
 1518 
 1519     safe_send(send.bytes, len, false);
 1520     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1521     validate_response_header(&receive.response, cmd,
 1522                              PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1523     len = storage_command(send.bytes, sizeof(send.bytes),
 1524                           PROTOCOL_BINARY_CMD_ADD,
 1525                           key, strlen(key), NULL, 0, 0, 0);
 1526     safe_send(send.bytes, len, false);
 1527     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1528     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1529                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1530 
 1531     len = raw_command(send.bytes, sizeof(send.bytes),
 1532                       cmd, key, strlen(key), NULL, 0);
 1533     safe_send(send.bytes, len, false);
 1534 
 1535     if (cmd == PROTOCOL_BINARY_CMD_DELETE) {
 1536         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1537         validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_DELETE,
 1538                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1539     }
 1540 
 1541     safe_send(send.bytes, len, false);
 1542     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1543     validate_response_header(&receive.response, cmd,
 1544                              PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1545 
 1546     return TEST_PASS;
 1547 }
 1548 
 1549 static enum test_return test_binary_delete(void) {
 1550     return test_binary_delete_impl("test_binary_delete",
 1551                                    PROTOCOL_BINARY_CMD_DELETE);
 1552 }
 1553 
 1554 static enum test_return test_binary_deleteq(void) {
 1555     return test_binary_delete_impl("test_binary_deleteq",
 1556                                    PROTOCOL_BINARY_CMD_DELETEQ);
 1557 }
 1558 
 1559 static enum test_return test_binary_get_impl(const char *key, uint8_t cmd) {
 1560     union {
 1561         protocol_binary_request_no_extras request;
 1562         protocol_binary_response_no_extras response;
 1563         char bytes[1024];
 1564     } send, receive;
 1565 
 1566     uint32_t expiration = htonl(3600);
 1567     size_t extlen = 0;
 1568     if (cmd == PROTOCOL_BINARY_CMD_GAT || cmd == PROTOCOL_BINARY_CMD_GATK)
 1569         extlen = sizeof(expiration);
 1570 
 1571     size_t len = ext_command(send.bytes, sizeof(send.bytes), cmd,
 1572                              extlen ? &expiration : NULL, extlen,
 1573                              key, strlen(key), NULL, 0);
 1574 
 1575     safe_send(send.bytes, len, false);
 1576     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1577     validate_response_header(&receive.response, cmd,
 1578                              PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1579 
 1580     len = storage_command(send.bytes, sizeof(send.bytes),
 1581                           PROTOCOL_BINARY_CMD_ADD,
 1582                           key, strlen(key), NULL, 0,
 1583                           0, 0);
 1584     safe_send(send.bytes, len, false);
 1585     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1586     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1587                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1588 
 1589     /* run a little pipeline test ;-) */
 1590     len = 0;
 1591     int ii;
 1592     for (ii = 0; ii < 10; ++ii) {
 1593         union {
 1594             protocol_binary_request_no_extras request;
 1595             char bytes[1024];
 1596         } temp;
 1597         size_t l = ext_command(temp.bytes, sizeof(temp.bytes), cmd,
 1598                                extlen ? &expiration : NULL, extlen,
 1599                                key, strlen(key), NULL, 0);
 1600         memcpy(send.bytes + len, temp.bytes, l);
 1601         len += l;
 1602     }
 1603 
 1604     safe_send(send.bytes, len, false);
 1605     for (ii = 0; ii < 10; ++ii) {
 1606         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1607         validate_response_header(&receive.response, cmd,
 1608                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1609     }
 1610 
 1611     return TEST_PASS;
 1612 }
 1613 
 1614 static enum test_return test_binary_get(void) {
 1615     return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
 1616 }
 1617 
 1618 static enum test_return test_binary_getk(void) {
 1619     return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
 1620 }
 1621 
 1622 static enum test_return test_binary_gat(void) {
 1623     return test_binary_get_impl("test_binary_gat", PROTOCOL_BINARY_CMD_GAT);
 1624 }
 1625 
 1626 static enum test_return test_binary_gatk(void) {
 1627     return test_binary_get_impl("test_binary_gatk", PROTOCOL_BINARY_CMD_GATK);
 1628 }
 1629 
 1630 static enum test_return test_binary_getq_impl(const char *key, uint8_t cmd) {
 1631     const char *missing = "test_binary_getq_missing";
 1632     union {
 1633         protocol_binary_request_no_extras request;
 1634         protocol_binary_response_no_extras response;
 1635         char bytes[1024];
 1636     } send, temp, receive;
 1637 
 1638     uint32_t expiration = htonl(3600);
 1639     size_t extlen = 0;
 1640     if (cmd == PROTOCOL_BINARY_CMD_GATQ || cmd == PROTOCOL_BINARY_CMD_GATKQ)
 1641         extlen = sizeof(expiration);
 1642 
 1643     size_t len = storage_command(send.bytes, sizeof(send.bytes),
 1644                                  PROTOCOL_BINARY_CMD_ADD,
 1645                                  key, strlen(key), NULL, 0,
 1646                                  0, 0);
 1647     size_t len2 = ext_command(temp.bytes, sizeof(temp.bytes), cmd,
 1648                               extlen ? &expiration : NULL, extlen,
 1649                               missing, strlen(missing), NULL, 0);
 1650     /* I need to change the first opaque so that I can separate the two
 1651      * return packets */
 1652     temp.request.message.header.request.opaque = 0xfeedface;
 1653     memcpy(send.bytes + len, temp.bytes, len2);
 1654     len += len2;
 1655 
 1656     len2 = ext_command(temp.bytes, sizeof(temp.bytes), cmd,
 1657                        extlen ? &expiration : NULL, extlen,
 1658                        key, strlen(key), NULL, 0);
 1659     memcpy(send.bytes + len, temp.bytes, len2);
 1660     len += len2;
 1661 
 1662     safe_send(send.bytes, len, false);
 1663     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1664     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1665                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1666     /* The first GETQ shouldn't return anything */
 1667     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1668     validate_response_header(&receive.response, cmd,
 1669                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1670 
 1671     return TEST_PASS;
 1672 }
 1673 
 1674 static enum test_return test_binary_getq(void) {
 1675     return test_binary_getq_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
 1676 }
 1677 
 1678 static enum test_return test_binary_getkq(void) {
 1679     return test_binary_getq_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
 1680 }
 1681 
 1682 static enum test_return test_binary_gatq(void) {
 1683     return test_binary_getq_impl("test_binary_gatq", PROTOCOL_BINARY_CMD_GATQ);
 1684 }
 1685 
 1686 static enum test_return test_binary_gatkq(void) {
 1687     return test_binary_getq_impl("test_binary_gatkq", PROTOCOL_BINARY_CMD_GATKQ);
 1688 }
 1689 
 1690 static enum test_return test_binary_incr_impl(const char* key, uint8_t cmd) {
 1691     union {
 1692         protocol_binary_request_no_extras request;
 1693         protocol_binary_response_no_extras response_header;
 1694         protocol_binary_response_incr response;
 1695         char bytes[1024];
 1696     } send, receive;
 1697     size_t len = arithmetic_command(send.bytes, sizeof(send.bytes), cmd,
 1698                                     key, strlen(key), 1, 0, 0);
 1699 
 1700     int ii;
 1701     for (ii = 0; ii < 10; ++ii) {
 1702         safe_send(send.bytes, len, false);
 1703         if (cmd == PROTOCOL_BINARY_CMD_INCREMENT) {
 1704             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1705             validate_response_header(&receive.response_header, cmd,
 1706                                      PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1707             assert(ntohll(receive.response.message.body.value) == ii);
 1708         }
 1709     }
 1710 
 1711     if (cmd == PROTOCOL_BINARY_CMD_INCREMENTQ) {
 1712         test_binary_noop();
 1713     }
 1714     return TEST_PASS;
 1715 }
 1716 
 1717 static enum test_return test_binary_incr(void) {
 1718     return test_binary_incr_impl("test_binary_incr",
 1719                                  PROTOCOL_BINARY_CMD_INCREMENT);
 1720 }
 1721 
 1722 static enum test_return test_binary_incrq(void) {
 1723     return test_binary_incr_impl("test_binary_incrq",
 1724                                  PROTOCOL_BINARY_CMD_INCREMENTQ);
 1725 }
 1726 
 1727 static enum test_return test_binary_decr_impl(const char* key, uint8_t cmd) {
 1728     union {
 1729         protocol_binary_request_no_extras request;
 1730         protocol_binary_response_no_extras response_header;
 1731         protocol_binary_response_decr response;
 1732         char bytes[1024];
 1733     } send, receive;
 1734     size_t len = arithmetic_command(send.bytes, sizeof(send.bytes), cmd,
 1735                                     key, strlen(key), 1, 9, 0);
 1736 
 1737     int ii;
 1738     for (ii = 9; ii >= 0; --ii) {
 1739         safe_send(send.bytes, len, false);
 1740         if (cmd == PROTOCOL_BINARY_CMD_DECREMENT) {
 1741             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1742             validate_response_header(&receive.response_header, cmd,
 1743                                      PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1744             assert(ntohll(receive.response.message.body.value) == ii);
 1745         }
 1746     }
 1747 
 1748     /* decr on 0 should not wrap */
 1749     safe_send(send.bytes, len, false);
 1750     if (cmd == PROTOCOL_BINARY_CMD_DECREMENT) {
 1751         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1752         validate_response_header(&receive.response_header, cmd,
 1753                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1754         assert(ntohll(receive.response.message.body.value) == 0);
 1755     } else {
 1756         test_binary_noop();
 1757     }
 1758 
 1759     return TEST_PASS;
 1760 }
 1761 
 1762 static enum test_return test_binary_decr(void) {
 1763     return test_binary_decr_impl("test_binary_decr",
 1764                                  PROTOCOL_BINARY_CMD_DECREMENT);
 1765 }
 1766 
 1767 static enum test_return test_binary_decrq(void) {
 1768     return test_binary_decr_impl("test_binary_decrq",
 1769                                  PROTOCOL_BINARY_CMD_DECREMENTQ);
 1770 }
 1771 
 1772 static enum test_return test_binary_version(void) {
 1773     union {
 1774         protocol_binary_request_no_extras request;
 1775         protocol_binary_response_no_extras response;
 1776         char bytes[1024];
 1777     } buffer;
 1778 
 1779     size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
 1780                              PROTOCOL_BINARY_CMD_VERSION,
 1781                              NULL, 0, NULL, 0);
 1782 
 1783     safe_send(buffer.bytes, len, false);
 1784     safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
 1785     validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_VERSION,
 1786                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1787 
 1788     return TEST_PASS;
 1789 }
 1790 
 1791 static enum test_return test_binary_flush_impl(const char *key, uint8_t cmd) {
 1792     union {
 1793         protocol_binary_request_no_extras request;
 1794         protocol_binary_response_no_extras response;
 1795         char bytes[1024];
 1796     } send, receive;
 1797 
 1798     size_t len = storage_command(send.bytes, sizeof(send.bytes),
 1799                                  PROTOCOL_BINARY_CMD_ADD,
 1800                                  key, strlen(key), NULL, 0, 0, 0);
 1801     safe_send(send.bytes, len, false);
 1802     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1803     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1804                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1805 
 1806     len = flush_command(send.bytes, sizeof(send.bytes), cmd, 2, true);
 1807     safe_send(send.bytes, len, false);
 1808     if (cmd == PROTOCOL_BINARY_CMD_FLUSH) {
 1809         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1810         validate_response_header(&receive.response, cmd,
 1811                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1812     }
 1813 
 1814     len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_GET,
 1815                       key, strlen(key), NULL, 0);
 1816     safe_send(send.bytes, len, false);
 1817     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1818     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
 1819                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1820 
 1821     sleep(2);
 1822     safe_send(send.bytes, len, false);
 1823     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1824     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
 1825                              PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1826 
 1827     int ii;
 1828     for (ii = 0; ii < 2; ++ii) {
 1829         len = storage_command(send.bytes, sizeof(send.bytes),
 1830                               PROTOCOL_BINARY_CMD_ADD,
 1831                               key, strlen(key), NULL, 0, 0, 0);
 1832         safe_send(send.bytes, len, false);
 1833         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1834         validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1835                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1836 
 1837         len = flush_command(send.bytes, sizeof(send.bytes), cmd, 0, ii == 0);
 1838         safe_send(send.bytes, len, false);
 1839         if (cmd == PROTOCOL_BINARY_CMD_FLUSH) {
 1840             safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1841             validate_response_header(&receive.response, cmd,
 1842                                      PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1843         }
 1844 
 1845         len = raw_command(send.bytes, sizeof(send.bytes),
 1846                           PROTOCOL_BINARY_CMD_GET,
 1847                           key, strlen(key), NULL, 0);
 1848         safe_send(send.bytes, len, false);
 1849         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1850         validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
 1851                                  PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
 1852     }
 1853 
 1854     return TEST_PASS;
 1855 }
 1856 
 1857 static enum test_return test_binary_flush(void) {
 1858     return test_binary_flush_impl("test_binary_flush",
 1859                                   PROTOCOL_BINARY_CMD_FLUSH);
 1860 }
 1861 
 1862 static enum test_return test_binary_flushq(void) {
 1863     return test_binary_flush_impl("test_binary_flushq",
 1864                                   PROTOCOL_BINARY_CMD_FLUSHQ);
 1865 }
 1866 
 1867 static enum test_return test_binary_concat_impl(const char *key, uint8_t cmd) {
 1868     union {
 1869         protocol_binary_request_no_extras request;
 1870         protocol_binary_response_no_extras response;
 1871         char bytes[1024];
 1872     } send, receive;
 1873     const char *value = "world";
 1874 
 1875     size_t len = raw_command(send.bytes, sizeof(send.bytes), cmd,
 1876                               key, strlen(key), value, strlen(value));
 1877 
 1878 
 1879     safe_send(send.bytes, len, false);
 1880     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1881     validate_response_header(&receive.response, cmd,
 1882                              PROTOCOL_BINARY_RESPONSE_NOT_STORED);
 1883 
 1884     len = storage_command(send.bytes, sizeof(send.bytes),
 1885                           PROTOCOL_BINARY_CMD_ADD,
 1886                           key, strlen(key), value, strlen(value), 0, 0);
 1887     safe_send(send.bytes, len, false);
 1888     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1889     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
 1890                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1891 
 1892     len = raw_command(send.bytes, sizeof(send.bytes), cmd,
 1893                       key, strlen(key), value, strlen(value));
 1894     safe_send(send.bytes, len, false);
 1895 
 1896     if (cmd == PROTOCOL_BINARY_CMD_APPEND || cmd == PROTOCOL_BINARY_CMD_PREPEND) {
 1897         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1898         validate_response_header(&receive.response, cmd,
 1899                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1900     } else {
 1901         len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_NOOP,
 1902                           NULL, 0, NULL, 0);
 1903         safe_send(send.bytes, len, false);
 1904         safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1905         validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_NOOP,
 1906                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1907     }
 1908 
 1909     len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_GETK,
 1910                       key, strlen(key), NULL, 0);
 1911 
 1912     safe_send(send.bytes, len, false);
 1913     safe_recv_packet(receive.bytes, sizeof(receive.bytes));
 1914     validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GETK,
 1915                              PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1916 
 1917     assert(receive.response.message.header.response.keylen == strlen(key));
 1918     assert(receive.response.message.header.response.bodylen == (strlen(key) + 2*strlen(value) + 4));
 1919 
 1920     char *ptr = receive.bytes;
 1921     ptr += sizeof(receive.response);
 1922     ptr += 4;
 1923 
 1924     assert(memcmp(ptr, key, strlen(key)) == 0);
 1925     ptr += strlen(key);
 1926     assert(memcmp(ptr, value, strlen(value)) == 0);
 1927     ptr += strlen(value);
 1928     assert(memcmp(ptr, value, strlen(value)) == 0);
 1929 
 1930     return TEST_PASS;
 1931 }
 1932 
 1933 static enum test_return test_binary_append(void) {
 1934     return test_binary_concat_impl("test_binary_append",
 1935                                    PROTOCOL_BINARY_CMD_APPEND);
 1936 }
 1937 
 1938 static enum test_return test_binary_prepend(void) {
 1939     return test_binary_concat_impl("test_binary_prepend",
 1940                                    PROTOCOL_BINARY_CMD_PREPEND);
 1941 }
 1942 
 1943 static enum test_return test_binary_appendq(void) {
 1944     return test_binary_concat_impl("test_binary_appendq",
 1945                                    PROTOCOL_BINARY_CMD_APPENDQ);
 1946 }
 1947 
 1948 static enum test_return test_binary_prependq(void) {
 1949     return test_binary_concat_impl("test_binary_prependq",
 1950                                    PROTOCOL_BINARY_CMD_PREPENDQ);
 1951 }
 1952 
 1953 static enum test_return test_binary_stat(void) {
 1954     union {
 1955         protocol_binary_request_no_extras request;
 1956         protocol_binary_response_no_extras response;
 1957         char bytes[1024];
 1958     } buffer;
 1959 
 1960     size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
 1961                              PROTOCOL_BINARY_CMD_STAT,
 1962                              NULL, 0, NULL, 0);
 1963 
 1964     safe_send(buffer.bytes, len, false);
 1965     do {
 1966         safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
 1967         validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_STAT,
 1968                                  PROTOCOL_BINARY_RESPONSE_SUCCESS);
 1969     } while (buffer.response.message.header.response.keylen != 0);
 1970 
 1971     return TEST_PASS;
 1972 }
 1973 
 1974 static enum test_return test_binary_illegal(void) {
 1975     uint8_t cmd = 0x25;
 1976     while (cmd != 0x00) {
 1977         union {
 1978             protocol_binary_request_no_extras request;
 1979             protocol_binary_response_no_extras response;
 1980             char bytes[1024];
 1981         } buffer;
 1982         size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
 1983                                  cmd, NULL, 0, NULL, 0);
 1984         safe_send(buffer.bytes, len, false);
 1985         safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
 1986         validate_response_header(&buffer.response, cmd,
 1987                                  PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND);
 1988         ++cmd;
 1989     }
 1990 
 1991     return TEST_PASS;
 1992 }
 1993 
 1994 volatile bool hickup_thread_running;
 1995 
 1996 static void *binary_hickup_recv_verification_thread(void *arg) {
 1997     protocol_binary_response_no_extras *response = malloc(65*1024);
 1998     if (response != NULL) {
 1999         while (safe_recv_packet(response, 65*1024)) {
 2000             /* Just validate the packet format */
 2001             validate_response_header(response,
 2002                                      response->message.header.response.opcode,
 2003                                      response->message.header.response.status);
 2004         }
 2005         free(response);
 2006     }
 2007     hickup_thread_running = false;
 2008     allow_closed_read = false;
 2009     return NULL;
 2010 }
 2011 
 2012 static enum test_return test_binary_pipeline_hickup_chunk(void *buffer, size_t buffersize) {
 2013     off_t offset = 0;
 2014     char *key[256];
 2015     uint64_t value = 0xfeedfacedeadbeef;
 2016 
 2017     while (hickup_thread_running &&
 2018            offset + sizeof(protocol_binary_request_no_extras) < buffersize) {
 2019         union {
 2020             protocol_binary_request_no_extras request;
 2021             char bytes[65 * 1024];
 2022         } command;
 2023         uint8_t cmd = (uint8_t)(rand() & 0xff);
 2024         size_t len;
 2025         size_t keylen = (rand() % 250) + 1;
 2026 
 2027         switch (cmd) {
 2028         case PROTOCOL_BINARY_CMD_ADD:
 2029         case PROTOCOL_BINARY_CMD_ADDQ:
 2030         case PROTOCOL_BINARY_CMD_REPLACE:
 2031         case PROTOCOL_BINARY_CMD_REPLACEQ:
 2032         case PROTOCOL_BINARY_CMD_SET:
 2033         case PROTOCOL_BINARY_CMD_SETQ:
 2034             len = storage_command(command.bytes, sizeof(command.bytes), cmd,
 2035                                   key, keylen , &value, sizeof(value),
 2036                                   0, 0);
 2037             break;
 2038         case PROTOCOL_BINARY_CMD_APPEND:
 2039         case PROTOCOL_BINARY_CMD_APPENDQ:
 2040         case PROTOCOL_BINARY_CMD_PREPEND:
 2041         case PROTOCOL_BINARY_CMD_PREPENDQ:
 2042             len = raw_command(command.bytes, sizeof(command.bytes), cmd,
 2043                               key, keylen, &value, sizeof(value));
 2044             break;
 2045         case PROTOCOL_BINARY_CMD_FLUSH:
 2046         case PROTOCOL_BINARY_CMD_FLUSHQ:
 2047             len = raw_command(command.bytes, sizeof(command.bytes), cmd,
 2048                               NULL, 0, NULL, 0);
 2049             break;
 2050         case PROTOCOL_BINARY_CMD_NOOP:
 2051             len = raw_command(command.bytes, sizeof(command.bytes), cmd,
 2052                               NULL, 0, NULL, 0);
 2053             break;
 2054         case PROTOCOL_BINARY_CMD_DELETE:
 2055         case PROTOCOL_BINARY_CMD_DELETEQ:
 2056             len = raw_command(command.bytes, sizeof(command.bytes), cmd,
 2057                              key, keylen, NULL, 0);
 2058             break;
 2059         case PROTOCOL_BINARY_CMD_DECREMENT:
 2060         case PROTOCOL_BINARY_CMD_DECREMENTQ:
 2061         case PROTOCOL_BINARY_CMD_INCREMENT:
 2062         case PROTOCOL_BINARY_CMD_INCREMENTQ:
 2063             len = arithmetic_command(command.bytes, sizeof(command.bytes), cmd,
 2064                                      key, keylen, 1, 0, 0);
 2065             break;
 2066         case PROTOCOL_BINARY_CMD_VERSION:
 2067             len = raw_command(command.bytes, sizeof(command.bytes),
 2068                              PROTOCOL_BINARY_CMD_VERSION,
 2069                              NULL, 0, NULL, 0);
 2070             break;
 2071         case PROTOCOL_BINARY_CMD_GET:
 2072         case PROTOCOL_BINARY_CMD_GETK:
 2073         case PROTOCOL_BINARY_CMD_GETKQ:
 2074         case PROTOCOL_BINARY_CMD_GETQ:
 2075             len = raw_command(command.bytes, sizeof(command.bytes), cmd,
 2076                              key, keylen, NULL, 0);
 2077             break;
 2078 
 2079         case PROTOCOL_BINARY_CMD_TOUCH:
 2080         case PROTOCOL_BINARY_CMD_GAT:
 2081         case PROTOCOL_BINARY_CMD_GATQ:
 2082         case PROTOCOL_BINARY_CMD_GATK:
 2083         case PROTOCOL_BINARY_CMD_GATKQ:
 2084             len = touch_command(command.bytes, sizeof(command.bytes), cmd,
 2085                                 key, keylen, 10);
 2086             break;
 2087 
 2088         case PROTOCOL_BINARY_CMD_STAT:
 2089             len = raw_command(command.bytes, sizeof(command.bytes),
 2090                               PROTOCOL_BINARY_CMD_STAT,
 2091                               NULL, 0, NULL, 0);
 2092             break;
 2093 
 2094         case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
 2095         case PROTOCOL_BINARY_CMD_SASL_AUTH:
 2096         case PROTOCOL_BINARY_CMD_SASL_STEP:
 2097             /* Ignoring SASL */
 2098         case PROTOCOL_BINARY_CMD_QUITQ:
 2099         case PROTOCOL_BINARY_CMD_QUIT:
 2100             /* I don't want to pass on the quit commands ;-) */
 2101             cmd |= 0xf0;
 2102             /* FALLTHROUGH */
 2103         default:
 2104             len = raw_command(command.bytes, sizeof(command.bytes),
 2105                               cmd, NULL, 0, NULL, 0);
 2106         }
 2107 
 2108         if ((len + offset) < buffersize) {
 2109             memcpy(((char*)buffer) + offset, command.bytes, len);
 2110             offset += len;
 2111         } else {
 2112             break;
 2113         }
 2114     }
 2115     safe_send(buffer, offset, true);
 2116 
 2117     return TEST_PASS;
 2118 }
 2119 
 2120 static enum test_return test_binary_pipeline_hickup(void)
 2121 {
 2122     size_t buffersize = 65 * 1024;
 2123     void *buffer = malloc(buffersize);
 2124     int ii;
 2125 
 2126     pthread_t tid;
 2127     int ret;
 2128     allow_closed_read = true;
 2129     hickup_thread_running = true;
 2130     if ((ret = pthread_create(&tid, NULL,
 2131                               binary_hickup_recv_verification_thread, NULL)) != 0) {
 2132         fprintf(stderr, "Can't create thread: %s\n", strerror(ret));
 2133         free(buffer);
 2134         return TEST_FAIL;
 2135     }
 2136 
 2137     /* Allow the thread to start */
 2138     usleep(250);
 2139 
 2140     srand((int)time(NULL));
 2141     for (ii = 0; ii < 2; ++ii) {
 2142         test_binary_pipeline_hickup_chunk(buffer, buffersize);
 2143     }
 2144 
 2145     /* send quitq to shut down the read thread ;-) */
 2146     size_t len = raw_command(buffer, buffersize, PROTOCOL_BINARY_CMD_QUITQ,
 2147                              NULL, 0, NULL, 0);
 2148     safe_send(buffer, len, false);
 2149 
 2150     pthread_join(tid, NULL);
 2151     free(buffer);
 2152     return TEST_PASS;
 2153 }
 2154 
 2155 
 2156 static enum test_return test_issue_101(void) {
 2157     enum { max = 2 };
 2158     enum test_return ret = TEST_PASS;
 2159     struct conn *conns[max];
 2160     int ii = 0;
 2161     pid_t child = 0;
 2162 
 2163     if (getenv("SKIP_TEST_101") != NULL) {
 2164         return TEST_SKIP;
 2165     }
 2166 
 2167     const char *command = "stats\r\nstats\r\nstats\r\nstats\r\nstats\r\n";
 2168     size_t cmdlen = strlen(command);
 2169 
 2170     server_pid = start_server(&port, false, 1000);
 2171 
 2172     for (ii = 0; ii < max; ++ii) {
 2173         conns[ii] = NULL;
 2174         conns[ii] = connect_server("127.0.0.1", port, true, enable_ssl);
 2175         assert(conns[ii]);
 2176         assert(conns[ii]->sock > 0);
 2177     }
 2178 
 2179     /* Send command on the connection until it blocks */
 2180     for (ii = 0; ii < max; ++ii) {
 2181         bool more = true;
 2182         do {
 2183             ssize_t err = conns[ii]->write(conns[ii], command, cmdlen);
 2184             if (err == -1) {
 2185                 switch (errno) {
 2186                 case EINTR:
 2187                     break;
 2188                 case ENOMEM:
 2189                 case EWOULDBLOCK:
 2190                     more = false;
 2191                     break;
 2192                 default:
 2193                     ret = TEST_FAIL;
 2194                     goto cleanup;
 2195                 }
 2196             }
 2197         } while (more);
 2198     }
 2199 
 2200     child = fork();
 2201     if (child == (pid_t)-1) {
 2202         abort();
 2203     } else if (child > 0) {
 2204         int stat;
 2205         pid_t c;
 2206         while ((c = waitpid(child, &stat, 0)) == (pid_t)-1 && errno == EINTR);
 2207         assert(c == child);
 2208         assert(stat == 0);
 2209     } else {
 2210         con = connect_server("127.0.0.1", port, false, enable_ssl);
 2211         assert(con);
 2212         ret = test_binary_noop();
 2213         close_conn();
 2214         exit(0);
 2215     }
 2216 
 2217  cleanup:
 2218     /* close all connections */
 2219     for (ii = 0; ii < max; ++ii) {
 2220         struct conn *c = conns[ii];
 2221         if (c == NULL) continue;
 2222 #ifdef TLS
 2223         if (c->ssl) {
 2224             SSL_shutdown(c->ssl);
 2225             SSL_free(c->ssl);
 2226         }
 2227         if (c->ssl_ctx)
 2228             SSL_CTX_free(c->ssl_ctx);
 2229 #endif
 2230         if (c->sock > 0) close(c->sock);
 2231         free(conns[ii]);
 2232         conns[ii] = NULL;
 2233     }
 2234 
 2235     assert(kill(server_pid, SIGTERM) == 0);
 2236 
 2237     return ret;
 2238 }
 2239 
 2240 typedef enum test_return (*TEST_FUNC)(void);
 2241 struct testcase {
 2242     const char *description;
 2243     TEST_FUNC function;
 2244 };
 2245 
 2246 struct testcase testcases[] = {
 2247     { "cache_create", cache_create_test },
 2248     { "cache_reuse", cache_reuse_test },
 2249     { "cache_redzone", cache_redzone_test },
 2250     { "cache_limit_revised_downward", cache_limit_revised_downward_test },
 2251     { "stats_prefix_find", test_stats_prefix_find },
 2252     { "stats_prefix_record_get", test_stats_prefix_record_get },
 2253     { "stats_prefix_record_delete", test_stats_prefix_record_delete },
 2254     { "stats_prefix_record_set", test_stats_prefix_record_set },
 2255     { "stats_prefix_dump", test_stats_prefix_dump },
 2256     { "issue_161", test_issue_161 },
 2257     { "strtol", test_safe_strtol },
 2258     { "strtoll", test_safe_strtoll },
 2259     { "strtoul", test_safe_strtoul },
 2260     { "strtoull", test_safe_strtoull },
 2261     { "issue_44", test_issue_44 },
 2262     { "vperror", test_vperror },
 2263     { "issue_101", test_issue_101 },
 2264     { "crc32c", test_crc32c },
 2265     /* The following tests all run towards the same server */
 2266     { "start_server", start_memcached_server },
 2267     { "issue_92", test_issue_92 },
 2268     { "issue_102", test_issue_102 },
 2269     { "binary_noop", test_binary_noop },
 2270     { "binary_quit", test_binary_quit },
 2271     { "binary_quitq", test_binary_quitq },
 2272     { "binary_set", test_binary_set },
 2273     { "binary_setq", test_binary_setq },
 2274     { "binary_add", test_binary_add },
 2275     { "binary_addq", test_binary_addq },
 2276     { "binary_replace", test_binary_replace },
 2277     { "binary_replaceq", test_binary_replaceq },
 2278     { "binary_delete", test_binary_delete },
 2279     { "binary_deleteq", test_binary_deleteq },
 2280     { "binary_get", test_binary_get },
 2281     { "binary_getq", test_binary_getq },
 2282     { "binary_getk", test_binary_getk },
 2283     { "binary_getkq", test_binary_getkq },
 2284     { "binary_gat", test_binary_gat },
 2285     { "binary_gatq", test_binary_gatq },
 2286     { "binary_gatk", test_binary_gatk },
 2287     { "binary_gatkq", test_binary_gatkq },
 2288     { "binary_incr", test_binary_incr },
 2289     { "binary_incrq", test_binary_incrq },
 2290     { "binary_decr", test_binary_decr },
 2291     { "binary_decrq", test_binary_decrq },
 2292     { "binary_version", test_binary_version },
 2293     { "binary_flush", test_binary_flush },
 2294     { "binary_flushq", test_binary_flushq },
 2295     { "binary_append", test_binary_append },
 2296     { "binary_appendq", test_binary_appendq },
 2297     { "binary_prepend", test_binary_prepend },
 2298     { "binary_prependq", test_binary_prependq },
 2299     { "binary_stat", test_binary_stat },
 2300     { "binary_illegal", test_binary_illegal },
 2301     { "binary_pipeline_hickup", test_binary_pipeline_hickup },
 2302     { "shutdown", shutdown_memcached_server },
 2303     { "stop_server", stop_memcached_server },
 2304     { NULL, NULL }
 2305 };
 2306 
 2307 /* Stub out function defined in memcached.c */
 2308 void STATS_LOCK(void);
 2309 void STATS_UNLOCK(void);
 2310 void STATS_LOCK(void)
 2311 {}
 2312 void STATS_UNLOCK(void)
 2313 {}
 2314 
 2315 int main(int argc, char **argv)
 2316 {
 2317     int exitcode = 0;
 2318     int ii = 0, num_cases = 0;
 2319 #ifdef TLS
 2320     if (getenv("SSL_TEST") != NULL) {
 2321         SSLeay_add_ssl_algorithms();
 2322         SSL_load_error_strings();
 2323         enable_ssl = true;
 2324     }
 2325 #endif
 2326     /* Initialized directly instead of using hash_init to avoid pulling in
 2327        the definition of settings struct from memcached.h */
 2328     hash = jenkins_hash;
 2329     stats_prefix_init(':');
 2330 
 2331     crc32c_init();
 2332 
 2333     for (num_cases = 0; testcases[num_cases].description; num_cases++) {
 2334         /* Just counting */
 2335     }
 2336 
 2337     printf("1..%d\n", num_cases);
 2338 
 2339     for (ii = 0; testcases[ii].description != NULL; ++ii) {
 2340         fflush(stdout);
 2341 #ifndef DEBUG
 2342         /* the test program shouldn't run longer than 10 minutes... */
 2343         alarm(600);
 2344 #endif
 2345         enum test_return ret = testcases[ii].function();
 2346         if (ret == TEST_SKIP) {
 2347             fprintf(stdout, "ok # SKIP %d - %s\n", ii + 1, testcases[ii].description);
 2348         } else if (ret == TEST_PASS) {
 2349             fprintf(stdout, "ok %d - %s\n", ii + 1, testcases[ii].description);
 2350         } else {
 2351             fprintf(stdout, "not ok %d - %s\n", ii + 1, testcases[ii].description);
 2352             exitcode = 1;
 2353         }
 2354         fflush(stdout);
 2355     }
 2356 
 2357     return exitcode;
 2358 }