"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.9/testapp.c" (21 Nov 2020, 80841 Bytes) of package /linux/www/memcached-1.6.9.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 latest Fossies "Diffs" side-by-side code changes report: 1.6.8_vs_1.6.9.

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