X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=clients%2Fmemcapable.cc;h=fc956fe07d891911041c80b9e04095fb14173535;hb=8c84f5e265f1fc68681f0856a7d96fa8aa034e80;hp=9bd310c524dd563c482ecaa3f7a200c8c8de3637;hpb=2ec5c18ff3cf16293ba0f53f91ad0f3a9d800b91;p=awesomized%2Flibmemcached diff --git a/clients/memcapable.cc b/clients/memcapable.cc index 9bd310c5..fc956fe0 100644 --- a/clients/memcapable.cc +++ b/clients/memcapable.cc @@ -1,4 +1,5 @@ /* LibMemcached + * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/ * Copyright (C) 2006-2009 Brian Aker * All rights reserved. * @@ -12,7 +13,7 @@ /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */ #undef NDEBUG -#include +#include #ifdef HAVE_POLL_H #include @@ -34,10 +35,13 @@ #include #include -#include -#include -#include -#include + +#include "libmemcached/socket.hpp" +#include "libmemcached/memcached/protocol_binary.h" +#include "libmemcached/byteorder.h" +#include "clients/utilities.h" + +#include #ifdef linux /* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to @@ -106,9 +110,13 @@ static struct addrinfo *lookuphost(const char *hostname, const char *port) if (error != 0) { if (error != EAI_SYSTEM) + { fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error)); + } else + { perror("getaddrinfo()"); + } } return ai; @@ -120,7 +128,7 @@ static struct addrinfo *lookuphost(const char *hostname, const char *port) */ static memcached_socket_t set_noblock(void) { -#ifdef WIN32 +#if defined(_WIN32) u_long arg = 1; if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR) { @@ -178,8 +186,9 @@ static memcached_socket_t connect_server(const char *hostname, const char *port) } } else - fprintf(stderr, "Failed to create socket: %s\n", - strerror(get_socket_errno())); + { + fprintf(stderr, "Failed to create socket: %s\n", strerror(get_socket_errno())); + } freeaddrinfo(ai); } @@ -244,10 +253,14 @@ static enum test_return ensure(bool val, const char *expression, const char *fil if (!val) { if (verbose) - fprintf(stderr, "\n%s:%d: %s", file, line, expression); + { + fprintf(stdout, "\n%s:%d: %s", file, line, expression); + } if (do_core) + { abort(); + } return TEST_FAIL; } @@ -271,9 +284,14 @@ static enum test_return retry_write(const void* buf, size_t len) size_t num_bytes= len - offset; ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes); if (nw == -1) + { verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN); + } else + { offset+= (size_t)nw; + } + } while (offset < len); return TEST_PASS; @@ -286,7 +304,7 @@ static enum test_return retry_write(const void* buf, size_t len) static enum test_return resend_packet(command *cmd) { size_t length= sizeof (protocol_binary_request_no_extras) + - ntohl(cmd->plain.message.header.request.bodylen); + ntohl(cmd->plain.message.header.request.bodylen); execute(retry_write(cmd, length)); return TEST_PASS; @@ -321,11 +339,13 @@ static enum test_return retry_read(void *buf, size_t len) ssize_t nr= timeout_io_op(sock, POLLIN, ((char*) buf) + offset, len - offset); switch (nr) { case -1 : - fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno)); + fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno)); verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN); break; + case 0: return TEST_FAIL; + default: offset+= (size_t)nr; } @@ -669,9 +689,13 @@ static enum test_return test_binary_set_impl(const char* key, uint8_t cc) for (int ii= 0; ii < 10; ii++) { if (ii == 0) + { execute(send_packet(&cmd)); + } else + { execute(resend_packet(&cmd)); + } if (cc == PROTOCOL_BINARY_CMD_SET) { @@ -799,17 +823,25 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc) for (int ii= 0; ii < 10; ii++) { if (ii == 0) + { execute(send_packet(&cmd)); + } else + { execute(resend_packet(&cmd)); + } if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0) { uint16_t expected_result; if (ii == 0) + { expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT; + } else + { expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS; + } execute(send_binary_noop()); execute(recv_packet(&rsp)); @@ -820,7 +852,9 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc) execute(binary_set_item(key, key)); } else + { execute(test_binary_noop()); + } } /* verify that replace with CAS value works! */ @@ -1094,16 +1128,24 @@ static enum test_return test_binary_concat_impl(const char *key, uint8_t cc) const char *value; if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ) + { value="hello"; + } else + { value=" world"; + } execute(binary_set_item(key, value)); if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ) + { value=" world"; + } else + { value="hello"; + } raw_command(&cmd, cc, key, strlen(key), value, strlen(value)); execute(send_packet(&cmd)); @@ -1113,7 +1155,9 @@ static enum test_return test_binary_concat_impl(const char *key, uint8_t cc) verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS)); } else + { execute(test_binary_noop()); + } raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0); execute(send_packet(&cmd)); @@ -1258,7 +1302,7 @@ static enum test_return test_ascii_verbosity(void) execute(receive_error_response()); execute(send_string("verbosity noreply\r\n")); - execute(receive_error_response()); + execute(test_ascii_version()); execute(send_string("verbosity 0 noreply\r\n")); execute(test_ascii_version()); @@ -1285,7 +1329,9 @@ static enum test_return test_ascii_set_impl(const char* key, bool noreply) execute(send_string(buffer)); if (!noreply) + { execute(receive_response("STORED\r\n")); + } return test_ascii_version(); } @@ -1308,12 +1354,16 @@ static enum test_return test_ascii_add_impl(const char* key, bool noreply) execute(send_string(buffer)); if (!noreply) + { execute(receive_response("STORED\r\n")); + } execute(send_string(buffer)); if (!noreply) + { execute(receive_response("NOT_STORED\r\n")); + } return test_ascii_version(); } @@ -1344,11 +1394,15 @@ static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_ verify(*key != NULL); char *ptr= end + 1; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + errno= 0; *ndata = (ssize_t)strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(end != NULL); while (end and *end != '\n' and isspace(*end)) @@ -1379,11 +1433,16 @@ static enum test_return ascii_get_value(const char *key, const char *value) char *ptr= buffer + 6 + strlen(key) + 1; char *end; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + + errno= 0; val= strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); @@ -1408,14 +1467,18 @@ static enum test_return ascii_get_item(const char *key, const char *value, char buffer[1024]; size_t datasize= 0; if (value != NULL) + { datasize= strlen(value); + } verify(datasize < sizeof(buffer)); snprintf(buffer, sizeof(buffer), "get %s\r\n", key); execute(send_string(buffer)); if (exist) + { execute(ascii_get_value(key, value)); + } execute(retry_read(buffer, 5)); verify(memcmp(buffer, "END\r\n", 5) == 0); @@ -1437,15 +1500,23 @@ static enum test_return ascii_gets_value(const char *key, const char *value, char *ptr= buffer + 6 + strlen(key) + 1; char *end; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + + errno= 0; val= strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); + + errno= 0; *cas= strtoul(end, &end, 10); /* cas */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); @@ -1471,7 +1542,9 @@ static enum test_return ascii_gets_item(const char *key, const char *value, char buffer[1024]; size_t datasize= 0; if (value != NULL) + { datasize= strlen(value); + } verify(datasize < sizeof(buffer)); snprintf(buffer, sizeof(buffer), "gets %s\r\n", key); @@ -1505,9 +1578,13 @@ static enum test_return test_ascii_replace_impl(const char* key, bool noreply) execute(send_string(buffer)); if (noreply) + { execute(test_ascii_version()); + } else + { execute(receive_response("NOT_STORED\r\n")); + } execute(ascii_set_item(key, "value")); execute(ascii_get_item(key, "value", true)); @@ -1545,17 +1622,25 @@ static enum test_return test_ascii_cas_impl(const char* key, bool noreply) execute(send_string(buffer)); if (noreply) + { execute(test_ascii_version()); + } else + { execute(receive_response("STORED\r\n")); + } /* reexecute the same command should fail due to illegal cas */ execute(send_string(buffer)); if (noreply) + { execute(test_ascii_version()); + } else + { execute(receive_response("EXISTS\r\n")); + } return test_ascii_version(); } @@ -1647,14 +1732,17 @@ static enum test_return test_ascii_mget(void) }; for (uint32_t x= 0; x < nkeys; ++x) + { execute(ascii_set_item(keys[x], "value")); + } /* Ask for a key that doesn't exist as well */ execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 " "test_ascii_mget4 test_ascii_mget5 " "test_ascii_mget6\r\n")); - char *returned[nkeys]; + std::vector returned; + returned.resize(nkeys); for (uint32_t x= 0; x < nkeys; ++x) { @@ -1686,7 +1774,9 @@ static enum test_return test_ascii_mget(void) } for (uint32_t x= 0; x < nkeys; ++x) + { free(returned[x]); + } return TEST_PASS; } @@ -1738,7 +1828,9 @@ static enum test_return test_ascii_decr_impl(const char* key, bool noreply) execute(send_string(cmd)); if (noreply) + { execute(test_ascii_version()); + } else { char buffer[80]; @@ -1753,7 +1845,9 @@ static enum test_return test_ascii_decr_impl(const char* key, bool noreply) /* verify that it doesn't wrap */ execute(send_string(cmd)); if (noreply) + { execute(test_ascii_version()); + } else { char buffer[80]; @@ -1827,9 +1921,13 @@ static enum test_return test_ascii_concat_impl(const char *key, execute(ascii_set_item(key, value)); if (append) + { value=" world"; + } else + { value="hello"; + } char cmd[400]; snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n", @@ -1839,9 +1937,13 @@ static enum test_return test_ascii_concat_impl(const char *key, execute(send_string(cmd)); if (noreply) + { execute(test_ascii_version()); + } else + { execute(receive_response("STORED\r\n")); + } execute(ascii_get_item(key, "hello world", true)); @@ -1852,9 +1954,13 @@ static enum test_return test_ascii_concat_impl(const char *key, execute(send_string(cmd)); if (noreply) + { execute(test_ascii_version()); + } else + { execute(receive_response("NOT_STORED\r\n")); + } return TEST_PASS; } @@ -1973,8 +2079,8 @@ int main(int argc, char **argv) struct test_type_st tests= { true, true }; int total= 0; int failed= 0; - const char *hostname= "localhost"; - const char *port= "11211"; + const char *hostname= NULL; + const char *port= MEMCACHED_DEFAULT_PORT_STRING; int cmd; bool prompt= false; const char *testname= NULL; @@ -2038,23 +2144,31 @@ int main(int argc, char **argv) "\t-a\tOnly test the ascii protocol\n" "\t-b\tOnly test the binary protocol\n", argv[0]); - return EXIT_FAILURE; + return EXIT_SUCCESS; } } + if (hostname) + { + fprintf(stderr, "No hostname was provided.\n"); + return EXIT_FAILURE; + } + initialize_sockets(); sock= connect_server(hostname, port); if (sock == INVALID_SOCKET) { fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", - hostname, port, strerror(get_socket_errno())); + hostname?:"(null)", port?:"(null)", strerror(get_socket_errno())); return EXIT_FAILURE; } for (int ii= 0; testcases[ii].description != NULL; ++ii) { if (testname != NULL && strcmp(testcases[ii].description, testname) != 0) - continue; + { + continue; + } if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) || (testcases[ii].description[0] == 'b' && (tests.binary) == 0)) @@ -2078,7 +2192,9 @@ int main(int argc, char **argv) continue; } if (strncmp(buffer, "quit", 4) == 0) - exit(0); + { + exit(EXIT_SUCCESS); + } } fprintf(stdout, "%-40s", testcases[ii].description); @@ -2092,19 +2208,30 @@ int main(int argc, char **argv) reconnect= true; ++failed; if (verbose) + { fprintf(stderr, "\n"); + } } else if (ret == TEST_PASS_RECONNECT) + { reconnect= true; + } + + if (ret == TEST_FAIL) + { + fprintf(stderr, "%s\n", status_msg[ret]); + } + else + { + fprintf(stdout, "%s\n", status_msg[ret]); + } - fprintf(stderr, "%s\n", status_msg[ret]); if (reconnect) { closesocket(sock); if ((sock= connect_server(hostname, port)) == INVALID_SOCKET) { - fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", - hostname, port, strerror(get_socket_errno())); + fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", hostname?:"(null)", port?:"(null)", strerror(get_socket_errno())); fprintf(stderr, "%d of %d tests failed\n", failed, total); return EXIT_FAILURE; } @@ -2113,9 +2240,13 @@ int main(int argc, char **argv) closesocket(sock); if (failed == 0) + { fprintf(stdout, "All tests passed\n"); + } else + { fprintf(stderr, "%d of %d tests failed\n", failed, total); + } - return (failed == 0) ? 0 : 1; + return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }