X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=clients%2Fmemcapable.c;h=3de6baf18205837c32738e1c95bc112df283a790;hb=3ec0260542c2f66cf2668323e44fa3b55b97138b;hp=2527861739c00c3e7f618558944968c99433aa1f;hpb=14563e0f4a2840f6a038fc9fd44ae8bd48206be6;p=awesomized%2Flibmemcached diff --git a/clients/memcapable.c b/clients/memcapable.c index 25278617..3de6baf1 100644 --- a/clients/memcapable.c +++ b/clients/memcapable.c @@ -303,6 +303,7 @@ 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)); verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN); break; case 0: @@ -321,7 +322,7 @@ static enum test_return retry_read(void *buf, size_t len) */ static enum test_return recv_packet(response *rsp) { - execute(retry_read(rsp, sizeof (protocol_binary_response_no_extras))); + execute(retry_read(rsp, sizeof(protocol_binary_response_no_extras))); /* Fix the byte order in the packet header */ rsp->plain.message.header.response.keylen= @@ -693,10 +694,12 @@ static enum test_return test_binary_set_impl(const char* key, uint8_t cc) cmd.plain.message.header.request.cas= htonll(rsp.plain.message.header.response.cas - 1); execute(resend_packet(&cmd)); + execute(send_binary_noop()); execute(recv_packet(&rsp)); verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)); + execute(receive_binary_noop()); - return test_binary_noop(); + return TEST_PASS; } static enum test_return test_binary_set(void) @@ -733,7 +736,9 @@ static enum test_return test_binary_add_impl(const char* key, uint8_t cc) else expected_result= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS; + execute(send_binary_noop()); execute(recv_packet(&rsp)); + execute(receive_binary_noop()); verify(validate_response_header(&rsp, cc, expected_result)); } else @@ -790,7 +795,9 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc) else expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS; + execute(send_binary_noop()); execute(recv_packet(&rsp)); + execute(receive_binary_noop()); verify(validate_response_header(&rsp, cc, expected_result)); if (ii == 0) @@ -817,7 +824,9 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc) cmd.plain.message.header.request.cas= htonll(rsp.plain.message.header.response.cas - 1); execute(resend_packet(&cmd)); + execute(send_binary_noop()); execute(recv_packet(&rsp)); + execute(receive_binary_noop()); verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)); return TEST_PASS; @@ -841,8 +850,10 @@ static enum test_return test_binary_delete_impl(const char *key, uint8_t cc) /* The delete shouldn't work the first time, because the item isn't there */ execute(send_packet(&cmd)); + execute(send_binary_noop()); execute(recv_packet(&rsp)); verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)); + execute(receive_binary_noop()); execute(binary_set_item(key, key)); /* The item should be present now, resend*/ @@ -1256,8 +1267,7 @@ static enum test_return test_ascii_set_impl(const char* key, bool noreply) { /* @todo add tests for bogus format! */ char buffer[1024]; - sprintf(buffer, "set %s 0 0 5%s\r\nvalue\r\n", key, - noreply ? " noreply" : ""); + snprintf(buffer, sizeof(buffer), "set %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : ""); execute(send_string(buffer)); if (!noreply) @@ -1280,8 +1290,7 @@ static enum test_return test_ascii_add_impl(const char* key, bool noreply) { /* @todo add tests for bogus format! */ char buffer[1024]; - sprintf(buffer, "add %s 0 0 5%s\r\nvalue\r\n", key, - noreply ? " noreply" : ""); + snprintf(buffer, sizeof(buffer), "add %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : ""); execute(send_string(buffer)); if (!noreply) @@ -1305,6 +1314,41 @@ static enum test_return test_ascii_add_noreply(void) return test_ascii_add_impl("test_ascii_add_noreply", true); } +static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_t *ndata) +{ + char buffer[1024]; + + execute(receive_line(buffer, sizeof(buffer))); + verify(strncmp(buffer, "VALUE ", 6) == 0); + char *end= strchr(buffer + 6, ' '); + verify(end != NULL); + *end= '\0'; + *key= strdup(buffer + 6); + verify(*key != NULL); + char *ptr= end + 1; + + unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(ptr != end); + verify(val == 0); + verify(end != NULL); + *ndata = (ssize_t)strtoul(end, &end, 10); /* size */ + verify(ptr != end); + verify(end != NULL); + while (*end != '\n' && isspace(*end)) + ++end; + verify(*end == '\n'); + + *value= malloc((size_t)*ndata); + verify(*value != NULL); + + execute(retry_read(*value, (size_t)*ndata)); + + execute(retry_read(buffer, 2)); + verify(memcmp(buffer, "\r\n", 2) == 0); + + return TEST_PASS; +} + static enum test_return ascii_get_value(const char *key, const char *value) { @@ -1348,7 +1392,7 @@ static enum test_return ascii_get_item(const char *key, const char *value, datasize= strlen(value); verify(datasize < sizeof(buffer)); - sprintf(buffer, "get %s\r\n", key); + snprintf(buffer, sizeof(buffer), "get %s\r\n", key); execute(send_string(buffer)); if (exist) @@ -1409,7 +1453,7 @@ static enum test_return ascii_gets_item(const char *key, const char *value, datasize= strlen(value); verify(datasize < sizeof(buffer)); - sprintf(buffer, "gets %s\r\n", key); + snprintf(buffer, sizeof(buffer), "gets %s\r\n", key); execute(send_string(buffer)); if (exist) @@ -1425,7 +1469,7 @@ static enum test_return ascii_set_item(const char *key, const char *value) { char buffer[300]; size_t len= strlen(value); - sprintf(buffer, "set %s 0 0 %u\r\n", key, (unsigned int)len); + snprintf(buffer, sizeof(buffer), "set %s 0 0 %u\r\n", key, (unsigned int)len); execute(send_string(buffer)); execute(retry_write(value, len)); execute(send_string("\r\n")); @@ -1436,8 +1480,7 @@ static enum test_return ascii_set_item(const char *key, const char *value) static enum test_return test_ascii_replace_impl(const char* key, bool noreply) { char buffer[1024]; - sprintf(buffer, "replace %s 0 0 5%s\r\nvalue\r\n", key, - noreply ? " noreply" : ""); + snprintf(buffer, sizeof(buffer), "replace %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : ""); execute(send_string(buffer)); if (noreply) @@ -1477,8 +1520,7 @@ static enum test_return test_ascii_cas_impl(const char* key, bool noreply) execute(ascii_set_item(key, "value")); execute(ascii_gets_item(key, "value", true, &cas)); - sprintf(buffer, "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, - noreply ? " noreply" : ""); + snprintf(buffer, sizeof(buffer), "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, noreply ? " noreply" : ""); execute(send_string(buffer)); if (noreply) @@ -1518,7 +1560,7 @@ static enum test_return test_ascii_delete_impl(const char *key, bool noreply) execute(receive_error_response()); char buffer[1024]; - sprintf(buffer, "delete %s%s\r\n", key, noreply ? " noreply" : ""); + snprintf(buffer, sizeof(buffer), "delete %s%s\r\n", key, noreply ? " noreply" : ""); execute(send_string(buffer)); if (noreply) @@ -1573,31 +1615,65 @@ static enum test_return test_ascii_gets(void) static enum test_return test_ascii_mget(void) { - execute(ascii_set_item("test_ascii_mget1", "value")); - execute(ascii_set_item("test_ascii_mget2", "value")); - execute(ascii_set_item("test_ascii_mget3", "value")); - execute(ascii_set_item("test_ascii_mget4", "value")); - execute(ascii_set_item("test_ascii_mget5", "value")); + const uint32_t nkeys= 5; + const char * const keys[]= { + "test_ascii_mget1", + "test_ascii_mget2", + /* test_ascii_mget_3 does not exist :) */ + "test_ascii_mget4", + "test_ascii_mget5", + "test_ascii_mget6" + }; + + 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")); - execute(ascii_get_value("test_ascii_mget1", "value")); - execute(ascii_get_value("test_ascii_mget2", "value")); - execute(ascii_get_value("test_ascii_mget3", "value")); - execute(ascii_get_value("test_ascii_mget4", "value")); - execute(ascii_get_value("test_ascii_mget5", "value")); + + char *returned[nkeys]; + + for (uint32_t x= 0; x < nkeys; ++x) + { + ssize_t nbytes = 0; + char *v= NULL; + execute(ascii_get_unknown_value(&returned[x], &v, &nbytes)); + verify(nbytes == 5); + verify(memcmp(v, "value", 5) == 0); + free(v); + } char buffer[5]; execute(retry_read(buffer, 5)); verify(memcmp(buffer, "END\r\n", 5) == 0); - return TEST_PASS; + + /* verify that we got all the keys we expected */ + for (uint32_t x= 0; x < nkeys; ++x) + { + bool found= false; + for (uint32_t y= 0; y < nkeys; ++y) + { + if (strcmp(keys[x], returned[y]) == 0) + { + found = true; + break; + } + } + verify(found); + } + + for (uint32_t x= 0; x < nkeys; ++x) + free(returned[x]); + + return TEST_PASS; } static enum test_return test_ascii_incr_impl(const char* key, bool noreply) { char cmd[300]; - sprintf(cmd, "incr %s 1%s\r\n", key, noreply ? " noreply" : ""); + snprintf(cmd, sizeof(cmd), "incr %s 1%s\r\n", key, noreply ? " noreply" : ""); execute(ascii_set_item(key, "0")); for (int x= 1; x < 11; ++x) @@ -1633,7 +1709,7 @@ static enum test_return test_ascii_incr_noreply(void) static enum test_return test_ascii_decr_impl(const char* key, bool noreply) { char cmd[300]; - sprintf(cmd, "decr %s 1%s\r\n", key, noreply ? " noreply" : ""); + snprintf(cmd, sizeof(cmd), "decr %s 1%s\r\n", key, noreply ? " noreply" : ""); execute(ascii_set_item(key, "9")); for (int x= 8; x > -1; --x) @@ -1735,10 +1811,10 @@ static enum test_return test_ascii_concat_impl(const char *key, value="hello"; char cmd[400]; - sprintf(cmd, "%s %s 0 0 %u%s\r\n%s\r\n", - append ? "append" : "prepend", - key, (unsigned int)strlen(value), noreply ? " noreply" : "", - value); + snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n", + append ? "append" : "prepend", + key, (unsigned int)strlen(value), noreply ? " noreply" : "", + value); execute(send_string(cmd)); if (noreply) @@ -1748,10 +1824,10 @@ static enum test_return test_ascii_concat_impl(const char *key, execute(ascii_get_item(key, "hello world", true)); - sprintf(cmd, "%s %s_notfound 0 0 %u%s\r\n%s\r\n", - append ? "append" : "prepend", - key, (unsigned int)strlen(value), noreply ? " noreply" : "", - value); + snprintf(cmd, sizeof(cmd), "%s %s_notfound 0 0 %u%s\r\n%s\r\n", + append ? "append" : "prepend", + key, (unsigned int)strlen(value), noreply ? " noreply" : "", + value); execute(send_string(cmd)); if (noreply) @@ -1869,8 +1945,10 @@ int main(int argc, char **argv) const char *hostname= "localhost"; const char *port= "11211"; int cmd; + bool prompt= false; + const char *testname= NULL; - while ((cmd= getopt(argc, argv, "t:vch:p:?")) != EOF) + while ((cmd= getopt(argc, argv, "t:vch:p:PT:?")) != EOF) { switch (cmd) { case 't': @@ -1889,11 +1967,21 @@ int main(int argc, char **argv) break; case 'p': port= optarg; break; + case 'P': prompt= true; + break; + case 'T': testname= optarg; + break; default: - fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n]\n" + fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n]" + " [-P] [-T testname]'\n" "\t-c\tGenerate coredump if a test fails\n" "\t-v\tVerbose test output (print out the assertion)\n" - "\t-t n\tSet the timeout for io-operations to n seconds\n", + "\t-t n\tSet the timeout for io-operations to n seconds\n" + "\t-P\tPrompt the user before starting a test.\n" + "\t\t\t\"skip\" will skip the test\n" + "\t\t\t\"quit\" will terminate memcapable\n" + "\t\t\tEverything else will start the test\n" + "\t-T n\tJust run the test named n\n", argv[0]); return 1; } @@ -1910,10 +1998,33 @@ int main(int argc, char **argv) for (int ii= 0; testcases[ii].description != NULL; ++ii) { + if (testname != NULL && strcmp(testcases[ii].description, testname) != 0) + continue; + ++total; fprintf(stdout, "%-40s", testcases[ii].description); fflush(stdout); + if (prompt) + { + fprintf(stdout, "\nPress when you are ready? "); + char buffer[80] = {0}; + if (fgets(buffer, sizeof(buffer), stdin) != NULL) { + if (strncmp(buffer, "skip", 4) == 0) + { + fprintf(stdout, "%-40s%s\n", testcases[ii].description, + status_msg[TEST_SKIP]); + fflush(stdout); + continue; + } + if (strncmp(buffer, "quit", 4) == 0) + exit(0); + } + + fprintf(stdout, "%-40s", testcases[ii].description); + fflush(stdout); + } + bool reconnect= false; enum test_return ret= testcases[ii].function(); if (ret == TEST_FAIL)