1
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
5
#include <sys/socket.h>
8
#include <netinet/in.h>
9
#include <netinet/tcp.h>
19
#include <netinet/in.h>
21
#include "protocol_binary.h"
26
#define TMP_TEMPLATE "/tmp/test_file.XXXXXXX"
28
enum test_return { TEST_SKIP, TEST_PASS, TEST_FAIL };
30
static pid_t server_pid;
31
static in_port_t port;
33
static bool allow_closed_read = false;
35
static enum test_return cache_create_test(void)
37
cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*),
39
assert(cache != NULL);
44
const uint64_t constructor_pattern = 0xdeadcafebabebeef;
46
static int cache_constructor(void *buffer, void *notused1, int notused2) {
47
uint64_t *ptr = buffer;
48
*ptr = constructor_pattern;
52
static enum test_return cache_constructor_test(void)
54
cache_t *cache = cache_create("test", sizeof(uint64_t), sizeof(uint64_t),
55
cache_constructor, NULL);
56
assert(cache != NULL);
57
uint64_t *ptr = cache_alloc(cache);
58
uint64_t pattern = *ptr;
59
cache_free(cache, ptr);
61
return (pattern == constructor_pattern) ? TEST_PASS : TEST_FAIL;
64
static int cache_fail_constructor(void *buffer, void *notused1, int notused2) {
68
static enum test_return cache_fail_constructor_test(void)
70
enum test_return ret = TEST_PASS;
72
cache_t *cache = cache_create("test", sizeof(uint64_t), sizeof(uint64_t),
73
cache_fail_constructor, NULL);
74
assert(cache != NULL);
75
uint64_t *ptr = cache_alloc(cache);
83
static void *destruct_data = 0;
85
static void cache_destructor(void *buffer, void *notused) {
86
destruct_data = buffer;
89
static enum test_return cache_destructor_test(void)
91
cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*),
92
NULL, cache_destructor);
93
assert(cache != NULL);
94
char *ptr = cache_alloc(cache);
95
cache_free(cache, ptr);
98
return (ptr == destruct_data) ? TEST_PASS : TEST_FAIL;
101
static enum test_return cache_reuse_test(void)
104
cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*),
106
char *ptr = cache_alloc(cache);
107
cache_free(cache, ptr);
108
for (ii = 0; ii < 100; ++ii) {
109
char *p = cache_alloc(cache);
111
cache_free(cache, ptr);
113
cache_destroy(cache);
117
static enum test_return cache_redzone_test(void)
120
cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*),
123
/* Ignore SIGABORT */
124
struct sigaction old_action;
125
struct sigaction action = { .sa_handler = SIG_IGN, .sa_flags = 0};
126
sigemptyset(&action.sa_mask);
127
sigaction(SIGABRT, &action, &old_action);
129
/* check memory debug.. */
130
char *p = cache_alloc(cache);
133
cache_free(cache, p);
134
assert(cache_error == -1);
137
p[sizeof(uint32_t)] = 0;
138
cache_free(cache, p);
139
assert(cache_error == 1);
141
/* restore signal handler */
142
sigaction(SIGABRT, &old_action, NULL);
144
cache_destroy(cache);
152
static enum test_return test_safe_strtoul(void) {
154
assert(safe_strtoul("123", &val));
156
assert(safe_strtoul("+123", &val));
158
assert(!safe_strtoul("", &val)); // empty
159
assert(!safe_strtoul("123BOGUS", &val)); // non-numeric
160
/* Not sure what it does, but this works with ICC :/
161
assert(!safe_strtoul("92837498237498237498029383", &val)); // out of range
165
assert(safe_strtoul("4294967295", &val)); // 2**32 - 1
166
assert(val == 4294967295L);
167
/* This actually works on 64-bit ubuntu
168
assert(!safe_strtoul("4294967296", &val)); // 2**32
170
assert(!safe_strtoul("-1", &val)); // negative
175
static enum test_return test_safe_strtoull(void) {
177
assert(safe_strtoull("123", &val));
179
assert(safe_strtoull("+123", &val));
181
assert(!safe_strtoull("", &val)); // empty
182
assert(!safe_strtoull("123BOGUS", &val)); // non-numeric
183
assert(!safe_strtoull("92837498237498237498029383", &val)); // out of range
186
assert(safe_strtoull("18446744073709551615", &val)); // 2**64 - 1
187
assert(val == 18446744073709551615ULL);
188
assert(!safe_strtoull("18446744073709551616", &val)); // 2**64
189
assert(!safe_strtoull("-1", &val)); // negative
193
static enum test_return test_safe_strtoll(void) {
195
assert(safe_strtoll("123", &val));
197
assert(safe_strtoll("+123", &val));
199
assert(safe_strtoll("-123", &val));
201
assert(!safe_strtoll("", &val)); // empty
202
assert(!safe_strtoll("123BOGUS", &val)); // non-numeric
203
assert(!safe_strtoll("92837498237498237498029383", &val)); // out of range
206
assert(!safe_strtoll("18446744073709551615", &val)); // 2**64 - 1
207
assert(safe_strtoll("9223372036854775807", &val)); // 2**63 - 1
208
assert(val == 9223372036854775807LL);
210
assert(safe_strtoll("-9223372036854775808", &val)); // -2**63
211
assert(val == -9223372036854775808LL);
213
assert(!safe_strtoll("-9223372036854775809", &val)); // -2**63 - 1
215
// We'll allow space to terminate the string. And leading space.
216
assert(safe_strtoll(" 123 foo", &val));
221
static enum test_return test_safe_strtol(void) {
223
assert(safe_strtol("123", &val));
225
assert(safe_strtol("+123", &val));
227
assert(safe_strtol("-123", &val));
229
assert(!safe_strtol("", &val)); // empty
230
assert(!safe_strtol("123BOGUS", &val)); // non-numeric
231
assert(!safe_strtol("92837498237498237498029383", &val)); // out of range
234
/* This actually works on 64-bit ubuntu
235
assert(!safe_strtol("2147483648", &val)); // (expt 2.0 31.0)
237
assert(safe_strtol("2147483647", &val)); // (- (expt 2.0 31) 1)
238
assert(val == 2147483647L);
239
/* This actually works on 64-bit ubuntu
240
assert(!safe_strtol("-2147483649", &val)); // (- (expt -2.0 31) 1)
243
// We'll allow space to terminate the string. And leading space.
244
assert(safe_strtol(" 123 foo", &val));
250
* Function to start the server and let it listen on a random port
252
* @param port_out where to store the TCP port number the server is
254
* @param daemon set to true if you want to run the memcached server
255
* as a daemon process
256
* @return the pid of the memcached server
258
static pid_t start_server(in_port_t *port_out, bool daemon, int timeout) {
259
char environment[80];
260
snprintf(environment, sizeof(environment),
261
"MEMCACHED_PORT_FILENAME=/tmp/ports.%lu", (long)getpid());
262
char *filename= environment + strlen("MEMCACHED_PORT_FILENAME=");
264
snprintf(pid_file, sizeof(pid_file), "/tmp/pid.%lu", (long)getpid());
270
/* I want to name the corefiles differently so that they don't
274
sprintf(coreadm, "coreadm -p core.%%f.%%p %lu", (unsigned long)getpid());
286
snprintf(tmo, sizeof(tmo), "%u", timeout);
290
putenv("LD_PRELOAD=watchmalloc.so.1");
291
putenv("MALLOC_DEBUG=WATCH");
295
argv[arg++] = "./timedrun";
298
argv[arg++] = "./memcached-debug";
303
/* Handle rpmbuild and the like doing this as root */
306
argv[arg++] = "root";
311
argv[arg++] = pid_file;
314
argv[arg++] = "-vvv";
317
assert(execv(argv[0], argv) != -1);
320
/* Yeah just let us "busy-wait" for the file to be created ;-) */
321
while (access(filename, F_OK) == -1) {
325
FILE *fp = fopen(filename, "r");
327
fprintf(stderr, "Failed to open the file containing port numbers: %s\n",
332
*port_out = (in_port_t)-1;
334
while ((fgets(buffer, sizeof(buffer), fp)) != NULL) {
335
if (strncmp(buffer, "TCP INET: ", 10) == 0) {
337
assert(safe_strtol(buffer + 10, &val));
338
*port_out = (in_port_t)val;
342
assert(remove(filename) == 0);
345
/* loop and wait for the pid file.. There is a potential race
346
* condition that the server just created the file but isn't
347
* finished writing the content, but I'll take the chance....
349
while (access(pid_file, F_OK) == -1) {
353
fp = fopen(pid_file, "r");
355
fprintf(stderr, "Failed to open pid file: %s\n",
359
assert(fgets(buffer, sizeof(buffer), fp) != NULL);
363
assert(safe_strtol(buffer, &val));
370
static enum test_return test_issue_44(void) {
372
pid_t pid = start_server(&port, true, 15);
373
assert(kill(pid, SIGHUP) == 0);
375
assert(kill(pid, SIGTERM) == 0);
380
static struct addrinfo *lookuphost(const char *hostname, in_port_t port)
382
struct addrinfo *ai = 0;
383
struct addrinfo hints = { .ai_family = AF_UNSPEC,
384
.ai_protocol = IPPROTO_TCP,
385
.ai_socktype = SOCK_STREAM };
386
char service[NI_MAXSERV];
389
(void)snprintf(service, NI_MAXSERV, "%d", port);
390
if ((error = getaddrinfo(hostname, service, &hints, &ai)) != 0) {
391
if (error != EAI_SYSTEM) {
392
fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
394
perror("getaddrinfo()");
401
static int connect_server(const char *hostname, in_port_t port)
403
struct addrinfo *ai = lookuphost(hostname, port);
406
if ((sock = socket(ai->ai_family, ai->ai_socktype,
407
ai->ai_protocol)) != -1) {
408
if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
409
fprintf(stderr, "Failed to connect socket: %s\n",
415
fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
423
static enum test_return test_vperror(void) {
425
int oldstderr = dup(STDERR_FILENO);
426
char tmpl[sizeof(TMP_TEMPLATE)+1];
427
strncpy(tmpl, TMP_TEMPLATE, sizeof(TMP_TEMPLATE)+1);
429
int newfile = mkstemp(tmpl);
431
rv = dup2(newfile, STDERR_FILENO);
432
assert(rv == STDERR_FILENO);
437
vperror("Old McDonald had a farm. %s", "EI EIO");
440
rv = dup2(oldstderr, STDERR_FILENO);
441
assert(rv == STDERR_FILENO);
444
/* Go read the file */
445
char buf[80] = { 0 };
446
FILE *efile = fopen(tmpl, "r");
448
char *prv = fgets(buf, sizeof(buf), efile);
454
char expected[80] = { 0 };
455
snprintf(expected, sizeof(expected),
456
"Old McDonald had a farm. EI EIO: %s\n", strerror(EIO));
461
"\nGot: ``%s''\n", expected, buf);
464
return strcmp(expected, buf) == 0 ? TEST_PASS : TEST_FAIL;
467
static void send_ascii_command(const char *buf) {
469
const char* ptr = buf;
470
size_t len = strlen(buf);
473
ssize_t nw = write(sock, ptr + offset, len - offset);
475
if (errno != EINTR) {
476
fprintf(stderr, "Failed to write: %s\n", strerror(errno));
482
} while (offset < len);
486
* This is a dead slow single byte read, but it should only read out
487
* _one_ response and I don't have an input buffer... The current
488
* implementation only supports single-line responses, so if you want to use
489
* it for get commands you need to implement that first ;-)
491
static void read_ascii_response(char *buffer, size_t size) {
493
bool need_more = true;
495
ssize_t nr = read(sock, buffer + offset, 1);
497
if (errno != EINTR) {
498
fprintf(stderr, "Failed to read: %s\n", strerror(errno));
503
if (buffer[offset] == '\n') {
505
buffer[offset + 1] = '\0';
508
assert(offset + 1 < size);
513
static enum test_return test_issue_92(void) {
517
sock = connect_server("127.0.0.1", port);
519
send_ascii_command("stats cachedump 1 0 0\r\n");
520
read_ascii_response(buffer, sizeof(buffer));
521
assert(strncmp(buffer, "END", strlen("END")) == 0);
523
send_ascii_command("stats cachedump 200 0 0\r\n");
524
read_ascii_response(buffer, sizeof(buffer));
525
assert(strncmp(buffer, "CLIENT_ERROR", strlen("CLIENT_ERROR")) == 0);
528
sock = connect_server("127.0.0.1", port);
532
static enum test_return start_memcached_server(void) {
533
server_pid = start_server(&port, false, 600);
534
sock = connect_server("127.0.0.1", port);
538
static enum test_return stop_memcached_server(void) {
540
assert(kill(server_pid, SIGTERM) == 0);
544
static void safe_send(const void* buf, size_t len, bool hickup)
547
const char* ptr = buf;
550
assert(val == (uint8_t)0x80);
551
fprintf(stderr, "About to send %lu bytes:", (unsigned long)len);
552
for (int ii = 0; ii < len; ++ii) {
554
fprintf(stderr, "\n ");
557
fprintf(stderr, " 0x%02x", val);
559
fprintf(stderr, "\n");
564
size_t num_bytes = len - offset;
566
if (num_bytes > 1024) {
567
num_bytes = (rand() % 1023) + 1;
571
ssize_t nw = write(sock, ptr + offset, num_bytes);
573
if (errno != EINTR) {
574
fprintf(stderr, "Failed to write: %s\n", strerror(errno));
583
} while (offset < len);
586
static bool safe_recv(void *buf, size_t len) {
592
ssize_t nr = read(sock, ((char*)buf) + offset, len - offset);
594
if (errno != EINTR) {
595
fprintf(stderr, "Failed to read: %s\n", strerror(errno));
599
if (nr == 0 && allow_closed_read) {
605
} while (offset < len);
610
static bool safe_recv_packet(void *buf, size_t size) {
611
protocol_binary_response_no_extras *response = buf;
612
assert(size > sizeof(*response));
613
if (!safe_recv(response, sizeof(*response))) {
616
response->message.header.response.keylen = ntohs(response->message.header.response.keylen);
617
response->message.header.response.status = ntohs(response->message.header.response.status);
618
response->message.header.response.bodylen = ntohl(response->message.header.response.bodylen);
620
size_t len = sizeof(*response);
624
if (!safe_recv(ptr, response->message.header.response.bodylen)) {
631
len += response->message.header.response.bodylen;
633
assert(val == (uint8_t)0x81);
634
fprintf(stderr, "Received %lu bytes:", (unsigned long)len);
635
for (int ii = 0; ii < len; ++ii) {
637
fprintf(stderr, "\n ");
640
fprintf(stderr, " 0x%02x", val);
642
fprintf(stderr, "\n");
647
static off_t storage_command(char*buf,
656
/* all of the storage commands use the same command layout */
657
protocol_binary_request_set *request = (void*)buf;
658
assert(bufsz > sizeof(*request) + keylen + dtalen);
660
memset(request, 0, sizeof(*request));
661
request->message.header.request.magic = PROTOCOL_BINARY_REQ;
662
request->message.header.request.opcode = cmd;
663
request->message.header.request.keylen = htons(keylen);
664
request->message.header.request.extlen = 8;
665
request->message.header.request.bodylen = htonl(keylen + 8 + dtalen);
666
request->message.header.request.opaque = 0xdeadbeef;
667
request->message.body.flags = flags;
668
request->message.body.expiration = exp;
670
off_t key_offset = sizeof(protocol_binary_request_no_extras) + 8;
672
memcpy(buf + key_offset, key, keylen);
674
memcpy(buf + key_offset + keylen, dta, dtalen);
677
return key_offset + keylen + dtalen;
680
static off_t raw_command(char* buf,
687
/* all of the storage commands use the same command layout */
688
protocol_binary_request_no_extras *request = (void*)buf;
689
assert(bufsz > sizeof(*request) + keylen + dtalen);
691
memset(request, 0, sizeof(*request));
692
request->message.header.request.magic = PROTOCOL_BINARY_REQ;
693
request->message.header.request.opcode = cmd;
694
request->message.header.request.keylen = htons(keylen);
695
request->message.header.request.bodylen = htonl(keylen + dtalen);
696
request->message.header.request.opaque = 0xdeadbeef;
698
off_t key_offset = sizeof(protocol_binary_request_no_extras);
701
memcpy(buf + key_offset, key, keylen);
704
memcpy(buf + key_offset + keylen, dta, dtalen);
707
return sizeof(*request) + keylen + dtalen;
710
static off_t flush_command(char* buf, size_t bufsz, uint8_t cmd, uint32_t exptime, bool use_extra) {
711
protocol_binary_request_flush *request = (void*)buf;
712
assert(bufsz > sizeof(*request));
714
memset(request, 0, sizeof(*request));
715
request->message.header.request.magic = PROTOCOL_BINARY_REQ;
716
request->message.header.request.opcode = cmd;
718
off_t size = sizeof(protocol_binary_request_no_extras);
720
request->message.header.request.extlen = 4;
721
request->message.body.expiration = htonl(exptime);
722
request->message.header.request.bodylen = htonl(4);
726
request->message.header.request.opaque = 0xdeadbeef;
731
static off_t arithmetic_command(char* buf,
739
protocol_binary_request_incr *request = (void*)buf;
740
assert(bufsz > sizeof(*request) + keylen);
742
memset(request, 0, sizeof(*request));
743
request->message.header.request.magic = PROTOCOL_BINARY_REQ;
744
request->message.header.request.opcode = cmd;
745
request->message.header.request.keylen = htons(keylen);
746
request->message.header.request.extlen = 20;
747
request->message.header.request.bodylen = htonl(keylen + 20);
748
request->message.header.request.opaque = 0xdeadbeef;
749
request->message.body.delta = htonll(delta);
750
request->message.body.initial = htonll(initial);
751
request->message.body.expiration = htonl(exp);
753
off_t key_offset = sizeof(protocol_binary_request_no_extras) + 20;
755
memcpy(buf + key_offset, key, keylen);
756
return key_offset + keylen;
759
static void validate_response_header(protocol_binary_response_no_extras *response,
760
uint8_t cmd, uint16_t status)
762
assert(response->message.header.response.magic == PROTOCOL_BINARY_RES);
763
assert(response->message.header.response.opcode == cmd);
764
assert(response->message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
765
assert(response->message.header.response.status == status);
766
assert(response->message.header.response.opaque == 0xdeadbeef);
768
if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
770
case PROTOCOL_BINARY_CMD_ADDQ:
771
case PROTOCOL_BINARY_CMD_APPENDQ:
772
case PROTOCOL_BINARY_CMD_DECREMENTQ:
773
case PROTOCOL_BINARY_CMD_DELETEQ:
774
case PROTOCOL_BINARY_CMD_FLUSHQ:
775
case PROTOCOL_BINARY_CMD_INCREMENTQ:
776
case PROTOCOL_BINARY_CMD_PREPENDQ:
777
case PROTOCOL_BINARY_CMD_QUITQ:
778
case PROTOCOL_BINARY_CMD_REPLACEQ:
779
case PROTOCOL_BINARY_CMD_SETQ:
780
assert("Quiet command shouldn't return on success" == NULL);
786
case PROTOCOL_BINARY_CMD_ADD:
787
case PROTOCOL_BINARY_CMD_REPLACE:
788
case PROTOCOL_BINARY_CMD_SET:
789
case PROTOCOL_BINARY_CMD_APPEND:
790
case PROTOCOL_BINARY_CMD_PREPEND:
791
assert(response->message.header.response.keylen == 0);
792
assert(response->message.header.response.extlen == 0);
793
assert(response->message.header.response.bodylen == 0);
794
assert(response->message.header.response.cas != 0);
796
case PROTOCOL_BINARY_CMD_FLUSH:
797
case PROTOCOL_BINARY_CMD_NOOP:
798
case PROTOCOL_BINARY_CMD_QUIT:
799
case PROTOCOL_BINARY_CMD_DELETE:
800
assert(response->message.header.response.keylen == 0);
801
assert(response->message.header.response.extlen == 0);
802
assert(response->message.header.response.bodylen == 0);
803
assert(response->message.header.response.cas == 0);
806
case PROTOCOL_BINARY_CMD_DECREMENT:
807
case PROTOCOL_BINARY_CMD_INCREMENT:
808
assert(response->message.header.response.keylen == 0);
809
assert(response->message.header.response.extlen == 0);
810
assert(response->message.header.response.bodylen == 8);
811
assert(response->message.header.response.cas != 0);
814
case PROTOCOL_BINARY_CMD_STAT:
815
assert(response->message.header.response.extlen == 0);
816
/* key and value exists in all packets except in the terminating */
817
assert(response->message.header.response.cas == 0);
820
case PROTOCOL_BINARY_CMD_VERSION:
821
assert(response->message.header.response.keylen == 0);
822
assert(response->message.header.response.extlen == 0);
823
assert(response->message.header.response.bodylen != 0);
824
assert(response->message.header.response.cas == 0);
827
case PROTOCOL_BINARY_CMD_GET:
828
case PROTOCOL_BINARY_CMD_GETQ:
829
assert(response->message.header.response.keylen == 0);
830
assert(response->message.header.response.extlen == 4);
831
assert(response->message.header.response.cas != 0);
834
case PROTOCOL_BINARY_CMD_GETK:
835
case PROTOCOL_BINARY_CMD_GETKQ:
836
assert(response->message.header.response.keylen != 0);
837
assert(response->message.header.response.extlen == 4);
838
assert(response->message.header.response.cas != 0);
842
/* Undefined command code */
846
assert(response->message.header.response.cas == 0);
847
assert(response->message.header.response.extlen == 0);
848
if (cmd != PROTOCOL_BINARY_CMD_GETK) {
849
assert(response->message.header.response.keylen == 0);
854
static enum test_return test_binary_noop(void) {
856
protocol_binary_request_no_extras request;
857
protocol_binary_response_no_extras response;
861
size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
862
PROTOCOL_BINARY_CMD_NOOP,
865
safe_send(buffer.bytes, len, false);
866
safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
867
validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_NOOP,
868
PROTOCOL_BINARY_RESPONSE_SUCCESS);
873
static enum test_return test_binary_quit_impl(uint8_t cmd) {
875
protocol_binary_request_no_extras request;
876
protocol_binary_response_no_extras response;
879
size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
880
cmd, NULL, 0, NULL, 0);
882
safe_send(buffer.bytes, len, false);
883
if (cmd == PROTOCOL_BINARY_CMD_QUIT) {
884
safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
885
validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_QUIT,
886
PROTOCOL_BINARY_RESPONSE_SUCCESS);
889
/* Socket should be closed now, read should return 0 */
890
assert(read(sock, buffer.bytes, sizeof(buffer.bytes)) == 0);
892
sock = connect_server("127.0.0.1", port);
897
static enum test_return test_binary_quit(void) {
898
return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
901
static enum test_return test_binary_quitq(void) {
902
return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
905
static enum test_return test_binary_set_impl(const char *key, uint8_t cmd) {
907
protocol_binary_request_no_extras request;
908
protocol_binary_response_no_extras response;
911
uint64_t value = 0xdeadbeefdeadcafe;
912
size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd,
913
key, strlen(key), &value, sizeof(value),
916
/* Set should work over and over again */
918
for (ii = 0; ii < 10; ++ii) {
919
safe_send(send.bytes, len, false);
920
if (cmd == PROTOCOL_BINARY_CMD_SET) {
921
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
922
validate_response_header(&receive.response, cmd,
923
PROTOCOL_BINARY_RESPONSE_SUCCESS);
927
if (cmd == PROTOCOL_BINARY_CMD_SETQ) {
928
return test_binary_noop();
931
send.request.message.header.request.cas = receive.response.message.header.response.cas;
932
safe_send(send.bytes, len, false);
933
if (cmd == PROTOCOL_BINARY_CMD_SET) {
934
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
935
validate_response_header(&receive.response, cmd,
936
PROTOCOL_BINARY_RESPONSE_SUCCESS);
937
assert(receive.response.message.header.response.cas != send.request.message.header.request.cas);
939
return test_binary_noop();
945
static enum test_return test_binary_set(void) {
946
return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
949
static enum test_return test_binary_setq(void) {
950
return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
954
static enum test_return test_binary_add_impl(const char *key, uint8_t cmd) {
955
uint64_t value = 0xdeadbeefdeadcafe;
957
protocol_binary_request_no_extras request;
958
protocol_binary_response_no_extras response;
961
size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd, key,
962
strlen(key), &value, sizeof(value),
965
/* Add should only work the first time */
967
for (ii = 0; ii < 10; ++ii) {
968
safe_send(send.bytes, len, false);
970
if (cmd == PROTOCOL_BINARY_CMD_ADD) {
971
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
972
validate_response_header(&receive.response, cmd,
973
PROTOCOL_BINARY_RESPONSE_SUCCESS);
976
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
977
validate_response_header(&receive.response, cmd,
978
PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS);
985
static enum test_return test_binary_add(void) {
986
return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
989
static enum test_return test_binary_addq(void) {
990
return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
993
static enum test_return test_binary_replace_impl(const char* key, uint8_t cmd) {
994
uint64_t value = 0xdeadbeefdeadcafe;
996
protocol_binary_request_no_extras request;
997
protocol_binary_response_no_extras response;
1000
size_t len = storage_command(send.bytes, sizeof(send.bytes), cmd,
1001
key, strlen(key), &value, sizeof(value),
1003
safe_send(send.bytes, len, false);
1004
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1005
validate_response_header(&receive.response, cmd,
1006
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1007
len = storage_command(send.bytes, sizeof(send.bytes),
1008
PROTOCOL_BINARY_CMD_ADD,
1009
key, strlen(key), &value, sizeof(value), 0, 0);
1010
safe_send(send.bytes, len, false);
1011
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1012
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1013
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1015
len = storage_command(send.bytes, sizeof(send.bytes), cmd,
1016
key, strlen(key), &value, sizeof(value), 0, 0);
1018
for (ii = 0; ii < 10; ++ii) {
1019
safe_send(send.bytes, len, false);
1020
if (cmd == PROTOCOL_BINARY_CMD_REPLACE) {
1021
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1022
validate_response_header(&receive.response,
1023
PROTOCOL_BINARY_CMD_REPLACE,
1024
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1028
if (cmd == PROTOCOL_BINARY_CMD_REPLACEQ) {
1035
static enum test_return test_binary_replace(void) {
1036
return test_binary_replace_impl("test_binary_replace",
1037
PROTOCOL_BINARY_CMD_REPLACE);
1040
static enum test_return test_binary_replaceq(void) {
1041
return test_binary_replace_impl("test_binary_replaceq",
1042
PROTOCOL_BINARY_CMD_REPLACEQ);
1045
static enum test_return test_binary_delete_impl(const char *key, uint8_t cmd) {
1047
protocol_binary_request_no_extras request;
1048
protocol_binary_response_no_extras response;
1051
size_t len = raw_command(send.bytes, sizeof(send.bytes), cmd,
1052
key, strlen(key), NULL, 0);
1054
safe_send(send.bytes, len, false);
1055
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1056
validate_response_header(&receive.response, cmd,
1057
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1058
len = storage_command(send.bytes, sizeof(send.bytes),
1059
PROTOCOL_BINARY_CMD_ADD,
1060
key, strlen(key), NULL, 0, 0, 0);
1061
safe_send(send.bytes, len, false);
1062
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1063
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1064
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1066
len = raw_command(send.bytes, sizeof(send.bytes),
1067
cmd, key, strlen(key), NULL, 0);
1068
safe_send(send.bytes, len, false);
1070
if (cmd == PROTOCOL_BINARY_CMD_DELETE) {
1071
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1072
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_DELETE,
1073
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1076
safe_send(send.bytes, len, false);
1077
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1078
validate_response_header(&receive.response, cmd,
1079
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1084
static enum test_return test_binary_delete(void) {
1085
return test_binary_delete_impl("test_binary_delete",
1086
PROTOCOL_BINARY_CMD_DELETE);
1089
static enum test_return test_binary_deleteq(void) {
1090
return test_binary_delete_impl("test_binary_deleteq",
1091
PROTOCOL_BINARY_CMD_DELETEQ);
1094
static enum test_return test_binary_get_impl(const char *key, uint8_t cmd) {
1096
protocol_binary_request_no_extras request;
1097
protocol_binary_response_no_extras response;
1100
size_t len = raw_command(send.bytes, sizeof(send.bytes), cmd,
1101
key, strlen(key), NULL, 0);
1103
safe_send(send.bytes, len, false);
1104
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1105
validate_response_header(&receive.response, cmd,
1106
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1108
len = storage_command(send.bytes, sizeof(send.bytes),
1109
PROTOCOL_BINARY_CMD_ADD,
1110
key, strlen(key), NULL, 0,
1112
safe_send(send.bytes, len, false);
1113
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1114
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1115
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1117
/* run a little pipeline test ;-) */
1120
for (ii = 0; ii < 10; ++ii) {
1122
protocol_binary_request_no_extras request;
1125
size_t l = raw_command(temp.bytes, sizeof(temp.bytes),
1126
cmd, key, strlen(key), NULL, 0);
1127
memcpy(send.bytes + len, temp.bytes, l);
1131
safe_send(send.bytes, len, false);
1132
for (ii = 0; ii < 10; ++ii) {
1133
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1134
validate_response_header(&receive.response, cmd,
1135
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1141
static enum test_return test_binary_get(void) {
1142
return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
1145
static enum test_return test_binary_getk(void) {
1146
return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
1149
static enum test_return test_binary_getq_impl(const char *key, uint8_t cmd) {
1150
const char *missing = "test_binary_getq_missing";
1152
protocol_binary_request_no_extras request;
1153
protocol_binary_response_no_extras response;
1155
} send, temp, receive;
1156
size_t len = storage_command(send.bytes, sizeof(send.bytes),
1157
PROTOCOL_BINARY_CMD_ADD,
1158
key, strlen(key), NULL, 0,
1160
size_t len2 = raw_command(temp.bytes, sizeof(temp.bytes), cmd,
1161
missing, strlen(missing), NULL, 0);
1162
/* I need to change the first opaque so that I can separate the two
1164
temp.request.message.header.request.opaque = 0xfeedface;
1165
memcpy(send.bytes + len, temp.bytes, len2);
1168
len2 = raw_command(temp.bytes, sizeof(temp.bytes), cmd,
1169
key, strlen(key), NULL, 0);
1170
memcpy(send.bytes + len, temp.bytes, len2);
1173
safe_send(send.bytes, len, false);
1174
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1175
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1176
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1177
/* The first GETQ shouldn't return anything */
1178
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1179
validate_response_header(&receive.response, cmd,
1180
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1185
static enum test_return test_binary_getq(void) {
1186
return test_binary_getq_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
1189
static enum test_return test_binary_getkq(void) {
1190
return test_binary_getq_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
1193
static enum test_return test_binary_incr_impl(const char* key, uint8_t cmd) {
1195
protocol_binary_request_no_extras request;
1196
protocol_binary_response_no_extras response_header;
1197
protocol_binary_response_incr response;
1200
size_t len = arithmetic_command(send.bytes, sizeof(send.bytes), cmd,
1201
key, strlen(key), 1, 0, 0);
1204
for (ii = 0; ii < 10; ++ii) {
1205
safe_send(send.bytes, len, false);
1206
if (cmd == PROTOCOL_BINARY_CMD_INCREMENT) {
1207
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1208
validate_response_header(&receive.response_header, cmd,
1209
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1210
assert(ntohll(receive.response.message.body.value) == ii);
1214
if (cmd == PROTOCOL_BINARY_CMD_INCREMENTQ) {
1220
static enum test_return test_binary_incr(void) {
1221
return test_binary_incr_impl("test_binary_incr",
1222
PROTOCOL_BINARY_CMD_INCREMENT);
1225
static enum test_return test_binary_incrq(void) {
1226
return test_binary_incr_impl("test_binary_incrq",
1227
PROTOCOL_BINARY_CMD_INCREMENTQ);
1230
static enum test_return test_binary_decr_impl(const char* key, uint8_t cmd) {
1232
protocol_binary_request_no_extras request;
1233
protocol_binary_response_no_extras response_header;
1234
protocol_binary_response_decr response;
1237
size_t len = arithmetic_command(send.bytes, sizeof(send.bytes), cmd,
1238
key, strlen(key), 1, 9, 0);
1241
for (ii = 9; ii >= 0; --ii) {
1242
safe_send(send.bytes, len, false);
1243
if (cmd == PROTOCOL_BINARY_CMD_DECREMENT) {
1244
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1245
validate_response_header(&receive.response_header, cmd,
1246
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1247
assert(ntohll(receive.response.message.body.value) == ii);
1251
/* decr on 0 should not wrap */
1252
safe_send(send.bytes, len, false);
1253
if (cmd == PROTOCOL_BINARY_CMD_DECREMENT) {
1254
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1255
validate_response_header(&receive.response_header, cmd,
1256
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1257
assert(ntohll(receive.response.message.body.value) == 0);
1265
static enum test_return test_binary_decr(void) {
1266
return test_binary_decr_impl("test_binary_decr",
1267
PROTOCOL_BINARY_CMD_DECREMENT);
1270
static enum test_return test_binary_decrq(void) {
1271
return test_binary_decr_impl("test_binary_decrq",
1272
PROTOCOL_BINARY_CMD_DECREMENTQ);
1275
static enum test_return test_binary_version(void) {
1277
protocol_binary_request_no_extras request;
1278
protocol_binary_response_no_extras response;
1282
size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
1283
PROTOCOL_BINARY_CMD_VERSION,
1286
safe_send(buffer.bytes, len, false);
1287
safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
1288
validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_VERSION,
1289
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1294
static enum test_return test_binary_flush_impl(const char *key, uint8_t cmd) {
1296
protocol_binary_request_no_extras request;
1297
protocol_binary_response_no_extras response;
1301
size_t len = storage_command(send.bytes, sizeof(send.bytes),
1302
PROTOCOL_BINARY_CMD_ADD,
1303
key, strlen(key), NULL, 0, 0, 0);
1304
safe_send(send.bytes, len, false);
1305
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1306
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1307
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1309
len = flush_command(send.bytes, sizeof(send.bytes), cmd, 2, true);
1310
safe_send(send.bytes, len, false);
1311
if (cmd == PROTOCOL_BINARY_CMD_FLUSH) {
1312
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1313
validate_response_header(&receive.response, cmd,
1314
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1317
len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_GET,
1318
key, strlen(key), NULL, 0);
1319
safe_send(send.bytes, len, false);
1320
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1321
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
1322
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1325
safe_send(send.bytes, len, false);
1326
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1327
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
1328
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1331
for (ii = 0; ii < 2; ++ii) {
1332
len = storage_command(send.bytes, sizeof(send.bytes),
1333
PROTOCOL_BINARY_CMD_ADD,
1334
key, strlen(key), NULL, 0, 0, 0);
1335
safe_send(send.bytes, len, false);
1336
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1337
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1338
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1340
len = flush_command(send.bytes, sizeof(send.bytes), cmd, 0, ii == 0);
1341
safe_send(send.bytes, len, false);
1342
if (cmd == PROTOCOL_BINARY_CMD_FLUSH) {
1343
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1344
validate_response_header(&receive.response, cmd,
1345
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1348
len = raw_command(send.bytes, sizeof(send.bytes),
1349
PROTOCOL_BINARY_CMD_GET,
1350
key, strlen(key), NULL, 0);
1351
safe_send(send.bytes, len, false);
1352
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1353
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GET,
1354
PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
1360
static enum test_return test_binary_flush(void) {
1361
return test_binary_flush_impl("test_binary_flush",
1362
PROTOCOL_BINARY_CMD_FLUSH);
1365
static enum test_return test_binary_flushq(void) {
1366
return test_binary_flush_impl("test_binary_flushq",
1367
PROTOCOL_BINARY_CMD_FLUSHQ);
1370
static enum test_return test_binary_concat_impl(const char *key, uint8_t cmd) {
1372
protocol_binary_request_no_extras request;
1373
protocol_binary_response_no_extras response;
1376
const char *value = "world";
1378
size_t len = raw_command(send.bytes, sizeof(send.bytes), cmd,
1379
key, strlen(key), value, strlen(value));
1382
safe_send(send.bytes, len, false);
1383
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1384
validate_response_header(&receive.response, cmd,
1385
PROTOCOL_BINARY_RESPONSE_NOT_STORED);
1387
len = storage_command(send.bytes, sizeof(send.bytes),
1388
PROTOCOL_BINARY_CMD_ADD,
1389
key, strlen(key), value, strlen(value), 0, 0);
1390
safe_send(send.bytes, len, false);
1391
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1392
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_ADD,
1393
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1395
len = raw_command(send.bytes, sizeof(send.bytes), cmd,
1396
key, strlen(key), value, strlen(value));
1397
safe_send(send.bytes, len, false);
1399
if (cmd == PROTOCOL_BINARY_CMD_APPEND || cmd == PROTOCOL_BINARY_CMD_PREPEND) {
1400
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1401
validate_response_header(&receive.response, cmd,
1402
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1404
len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_NOOP,
1406
safe_send(send.bytes, len, false);
1407
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1408
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_NOOP,
1409
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1412
len = raw_command(send.bytes, sizeof(send.bytes), PROTOCOL_BINARY_CMD_GETK,
1413
key, strlen(key), NULL, 0);
1415
safe_send(send.bytes, len, false);
1416
safe_recv_packet(receive.bytes, sizeof(receive.bytes));
1417
validate_response_header(&receive.response, PROTOCOL_BINARY_CMD_GETK,
1418
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1420
assert(receive.response.message.header.response.keylen == strlen(key));
1421
assert(receive.response.message.header.response.bodylen == (strlen(key) + 2*strlen(value) + 4));
1423
char *ptr = receive.bytes;
1424
ptr += sizeof(receive.response);
1427
assert(memcmp(ptr, key, strlen(key)) == 0);
1429
assert(memcmp(ptr, value, strlen(value)) == 0);
1430
ptr += strlen(value);
1431
assert(memcmp(ptr, value, strlen(value)) == 0);
1436
static enum test_return test_binary_append(void) {
1437
return test_binary_concat_impl("test_binary_append",
1438
PROTOCOL_BINARY_CMD_APPEND);
1441
static enum test_return test_binary_prepend(void) {
1442
return test_binary_concat_impl("test_binary_prepend",
1443
PROTOCOL_BINARY_CMD_PREPEND);
1446
static enum test_return test_binary_appendq(void) {
1447
return test_binary_concat_impl("test_binary_appendq",
1448
PROTOCOL_BINARY_CMD_APPENDQ);
1451
static enum test_return test_binary_prependq(void) {
1452
return test_binary_concat_impl("test_binary_prependq",
1453
PROTOCOL_BINARY_CMD_PREPENDQ);
1456
static enum test_return test_binary_stat(void) {
1458
protocol_binary_request_no_extras request;
1459
protocol_binary_response_no_extras response;
1463
size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
1464
PROTOCOL_BINARY_CMD_STAT,
1467
safe_send(buffer.bytes, len, false);
1469
safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
1470
validate_response_header(&buffer.response, PROTOCOL_BINARY_CMD_STAT,
1471
PROTOCOL_BINARY_RESPONSE_SUCCESS);
1472
} while (buffer.response.message.header.response.keylen != 0);
1477
static enum test_return test_binary_illegal(void) {
1479
while (cmd != 0x00) {
1481
protocol_binary_request_no_extras request;
1482
protocol_binary_response_no_extras response;
1485
size_t len = raw_command(buffer.bytes, sizeof(buffer.bytes),
1486
cmd, NULL, 0, NULL, 0);
1487
safe_send(buffer.bytes, len, false);
1488
safe_recv_packet(buffer.bytes, sizeof(buffer.bytes));
1489
validate_response_header(&buffer.response, cmd,
1490
PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND);
1497
volatile bool hickup_thread_running;
1499
static void *binary_hickup_recv_verification_thread(void *arg) {
1500
protocol_binary_response_no_extras *response = malloc(65*1024);
1501
if (response != NULL) {
1502
while (safe_recv_packet(response, 65*1024)) {
1503
/* Just validate the packet format */
1504
validate_response_header(response,
1505
response->message.header.response.opcode,
1506
response->message.header.response.status);
1510
hickup_thread_running = false;
1511
allow_closed_read = false;
1515
static enum test_return test_binary_pipeline_hickup_chunk(void *buffer, size_t buffersize) {
1518
uint64_t value = 0xfeedfacedeadbeef;
1520
while (hickup_thread_running &&
1521
offset + sizeof(protocol_binary_request_no_extras) < buffersize) {
1523
protocol_binary_request_no_extras request;
1524
char bytes[65 * 1024];
1526
uint8_t cmd = (uint8_t)(rand() & 0xff);
1528
size_t keylen = (rand() % 250) + 1;
1531
case PROTOCOL_BINARY_CMD_ADD:
1532
case PROTOCOL_BINARY_CMD_ADDQ:
1533
case PROTOCOL_BINARY_CMD_REPLACE:
1534
case PROTOCOL_BINARY_CMD_REPLACEQ:
1535
case PROTOCOL_BINARY_CMD_SET:
1536
case PROTOCOL_BINARY_CMD_SETQ:
1537
len = storage_command(command.bytes, sizeof(command.bytes), cmd,
1538
key, keylen , &value, sizeof(value),
1541
case PROTOCOL_BINARY_CMD_APPEND:
1542
case PROTOCOL_BINARY_CMD_APPENDQ:
1543
case PROTOCOL_BINARY_CMD_PREPEND:
1544
case PROTOCOL_BINARY_CMD_PREPENDQ:
1545
len = raw_command(command.bytes, sizeof(command.bytes), cmd,
1546
key, keylen, &value, sizeof(value));
1548
case PROTOCOL_BINARY_CMD_FLUSH:
1549
case PROTOCOL_BINARY_CMD_FLUSHQ:
1550
len = raw_command(command.bytes, sizeof(command.bytes), cmd,
1553
case PROTOCOL_BINARY_CMD_NOOP:
1554
len = raw_command(command.bytes, sizeof(command.bytes), cmd,
1557
case PROTOCOL_BINARY_CMD_DELETE:
1558
case PROTOCOL_BINARY_CMD_DELETEQ:
1559
len = raw_command(command.bytes, sizeof(command.bytes), cmd,
1560
key, keylen, NULL, 0);
1562
case PROTOCOL_BINARY_CMD_DECREMENT:
1563
case PROTOCOL_BINARY_CMD_DECREMENTQ:
1564
case PROTOCOL_BINARY_CMD_INCREMENT:
1565
case PROTOCOL_BINARY_CMD_INCREMENTQ:
1566
len = arithmetic_command(command.bytes, sizeof(command.bytes), cmd,
1567
key, keylen, 1, 0, 0);
1569
case PROTOCOL_BINARY_CMD_VERSION:
1570
len = raw_command(command.bytes, sizeof(command.bytes),
1571
PROTOCOL_BINARY_CMD_VERSION,
1574
case PROTOCOL_BINARY_CMD_GET:
1575
case PROTOCOL_BINARY_CMD_GETK:
1576
case PROTOCOL_BINARY_CMD_GETKQ:
1577
case PROTOCOL_BINARY_CMD_GETQ:
1578
len = raw_command(command.bytes, sizeof(command.bytes), cmd,
1579
key, keylen, NULL, 0);
1582
case PROTOCOL_BINARY_CMD_STAT:
1583
len = raw_command(command.bytes, sizeof(command.bytes),
1584
PROTOCOL_BINARY_CMD_STAT,
1588
case PROTOCOL_BINARY_CMD_QUITQ:
1589
case PROTOCOL_BINARY_CMD_QUIT:
1590
/* I don't want to pass on the quit commands ;-) */
1594
len = raw_command(command.bytes, sizeof(command.bytes),
1595
cmd, NULL, 0, NULL, 0);
1598
if ((len + offset) < buffersize) {
1599
memcpy(((char*)buffer) + offset, command.bytes, len);
1605
safe_send(buffer, offset, true);
1610
static enum test_return test_binary_pipeline_hickup(void)
1612
size_t buffersize = 65 * 1024;
1613
void *buffer = malloc(buffersize);
1618
allow_closed_read = true;
1619
hickup_thread_running = true;
1620
if ((ret = pthread_create(&tid, NULL,
1621
binary_hickup_recv_verification_thread, NULL)) != 0) {
1622
fprintf(stderr, "Can't create thread: %s\n", strerror(ret));
1626
/* Allow the thread to start */
1629
srand((int)time(NULL));
1630
for (ii = 0; ii < 2; ++ii) {
1631
test_binary_pipeline_hickup_chunk(buffer, buffersize);
1634
/* send quitq to shut down the read thread ;-) */
1635
size_t len = raw_command(buffer, buffersize, PROTOCOL_BINARY_CMD_QUITQ,
1637
safe_send(buffer, len, false);
1639
pthread_join(tid, NULL);
1644
typedef enum test_return (*TEST_FUNC)(void);
1646
const char *description;
1650
struct testcase testcases[] = {
1651
{ "cache_create", cache_create_test },
1652
{ "cache_constructor", cache_constructor_test },
1653
{ "cache_constructor_fail", cache_fail_constructor_test },
1654
{ "cache_destructor", cache_destructor_test },
1655
{ "cache_reuse", cache_reuse_test },
1656
{ "cache_redzone", cache_redzone_test },
1657
{ "strtol", test_safe_strtol },
1658
{ "strtoll", test_safe_strtoll },
1659
{ "strtoul", test_safe_strtoul },
1660
{ "strtoull", test_safe_strtoull },
1661
{ "issue_44", test_issue_44 },
1662
{ "vperror", test_vperror },
1663
/* The following tests all run towards the same server */
1664
{ "start_server", start_memcached_server },
1665
{ "issue_92", test_issue_92 },
1666
{ "binary_noop", test_binary_noop },
1667
{ "binary_quit", test_binary_quit },
1668
{ "binary_quitq", test_binary_quitq },
1669
{ "binary_set", test_binary_set },
1670
{ "binary_setq", test_binary_setq },
1671
{ "binary_add", test_binary_add },
1672
{ "binary_addq", test_binary_addq },
1673
{ "binary_replace", test_binary_replace },
1674
{ "binary_replaceq", test_binary_replaceq },
1675
{ "binary_delete", test_binary_delete },
1676
{ "binary_deleteq", test_binary_deleteq },
1677
{ "binary_get", test_binary_get },
1678
{ "binary_getq", test_binary_getq },
1679
{ "binary_getk", test_binary_getk },
1680
{ "binary_getkq", test_binary_getkq },
1681
{ "binary_incr", test_binary_incr },
1682
{ "binary_incrq", test_binary_incrq },
1683
{ "binary_decr", test_binary_decr },
1684
{ "binary_decrq", test_binary_decrq },
1685
{ "binary_version", test_binary_version },
1686
{ "binary_flush", test_binary_flush },
1687
{ "binary_flushq", test_binary_flushq },
1688
{ "binary_append", test_binary_append },
1689
{ "binary_appendq", test_binary_appendq },
1690
{ "binary_prepend", test_binary_prepend },
1691
{ "binary_prependq", test_binary_prependq },
1692
{ "binary_stat", test_binary_stat },
1693
{ "binary_illegal", test_binary_illegal },
1694
{ "binary_pipeline_hickup", test_binary_pipeline_hickup },
1695
{ "stop_server", stop_memcached_server },
1699
int main(int argc, char **argv)
1702
int ii = 0, num_cases = 0;
1704
for (num_cases = 0; testcases[num_cases].description; num_cases++) {
1708
printf("1..%d\n", num_cases);
1710
for (ii = 0; testcases[ii].description != NULL; ++ii) {
1713
/* the test program shouldn't run longer than 10 minutes... */
1716
enum test_return ret = testcases[ii].function();
1717
if (ret == TEST_SKIP) {
1718
fprintf(stdout, "ok # SKIP %d - %s\n", ii + 1, testcases[ii].description);
1719
} else if (ret == TEST_PASS) {
1720
fprintf(stdout, "ok %d - %s\n", ii + 1, testcases[ii].description);
1722
fprintf(stdout, "not ok %d - %s\n", ii + 1, testcases[ii].description);