From f8fd4b41acd1abf63eb305170638fa397afe06fa Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Fri, 10 Jun 2011 12:46:50 -0700 Subject: [PATCH] Extend out testing for hosts. --- libmemcached/connect.cc | 13 +++++++--- libmemcached/error.cc | 30 ++++++++++++++++++----- libmemcached/io.cc | 41 +++++++++++++++++++++++-------- libmemcached/purge.cc | 8 +++---- libmemcached/return.h | 4 ++-- libtest/test.c | 11 +++++++++ tests/mem_functions.cc | 5 ++-- tests/parser.cc | 53 +++++++++++++++++++++++++++++++---------- tests/parser.h | 5 +++- 9 files changed, 130 insertions(+), 40 deletions(-) diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc index eda4b88f..c9e91020 100644 --- a/libmemcached/connect.cc +++ b/libmemcached/connect.cc @@ -52,7 +52,14 @@ static memcached_return_t connect_poll(memcached_server_st *ptr) while (--loop_max) // Should only loop on cases of ERESTART or EINTR { - error= poll(fds, 1, ptr->root->connect_timeout); + if (ptr->root->poll_timeout) + { + error= poll(fds, 1, ptr->root->connect_timeout); + } + else + { + error= 0; + } switch (error) { @@ -76,6 +83,7 @@ static memcached_return_t connect_poll(memcached_server_st *ptr) } case 0: return MEMCACHED_TIMEOUT; + default: // A real error occurred and we need to completely bail WATCHPOINT_ERRNO(get_socket_errno()); switch (get_socket_errno()) @@ -457,8 +465,7 @@ static memcached_return_t network_connect(memcached_server_st *ptr) case EINPROGRESS: // nonblocking mode - first return case EALREADY: // nonblocking mode - subsequent returns { - memcached_return_t rc; - rc= connect_poll(ptr); + memcached_return_t rc= connect_poll(ptr); if (rc == MEMCACHED_TIMEOUT) timeout_error_occured= true; diff --git a/libmemcached/error.cc b/libmemcached/error.cc index 01975956..7914a165 100644 --- a/libmemcached/error.cc +++ b/libmemcached/error.cc @@ -75,6 +75,11 @@ static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t rc= MEMCACHED_ERRNO; } + if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN) + { + rc= MEMCACHED_CONNECTION_FAILURE; + } + memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t)); if (not error) // Bad business if this happens return; @@ -84,16 +89,29 @@ static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t error->rc= rc; error->local_errno= local_errno; - if (str) + if (str and local_errno) + { + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s", + memcached_strerror(&memc, rc), + strerror(local_errno), + int(error->size), str->c_str, at); + } + else if (local_errno) + { + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s", + memcached_strerror(&memc, rc), + strerror(local_errno), at); + } + else if (str) { - size_t length= str->size > (size_t)MAX_ERROR_LENGTH ? MAX_ERROR_LENGTH : str->size; - error->size= length; - memcpy(error->message, str->c_str, error->size); - error->message[error->size]= 0; + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s", + memcached_strerror(&memc, rc), + int(error->size), str->c_str, at); } else { - error->size= 0; + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s", + memcached_strerror(&memc, rc), at); } error->next= memc.error_messages; diff --git a/libmemcached/io.cc b/libmemcached/io.cc index 3a3cd45b..d2c3a03d 100644 --- a/libmemcached/io.cc +++ b/libmemcached/io.cc @@ -37,7 +37,7 @@ */ -#include "libmemcached/common.h" +#include typedef enum { MEM_READ, @@ -80,13 +80,22 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, { memcached_return_t rc= memcached_purge(ptr); if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED) + { return MEMCACHED_FAILURE; + } } size_t loop_max= 5; while (--loop_max) // While loop is for ERESTART or EINTR { - error= poll(&fds, 1, ptr->root->poll_timeout); + if (ptr->root->poll_timeout) // Mimic 0 causes timeout behavior (not all platforms do this) + { + error= poll(&fds, 1, ptr->root->poll_timeout); + } + else + { + error= 0; + } switch (error) { @@ -95,8 +104,10 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, WATCHPOINT_IF_LABELED_NUMBER(!read_or_write && loop_max < 4, "write() times we had to loop, decremented down from 5", loop_max); return MEMCACHED_SUCCESS; + case 0: // Timeout occured, we let the while() loop do its thing. - return MEMCACHED_TIMEOUT; + return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT); + default: WATCHPOINT_ERRNO(get_socket_errno()); switch (get_socket_errno()) @@ -106,6 +117,7 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, #endif case EINTR: break; + default: if (fds.revents & POLLERR) { @@ -120,7 +132,7 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, } memcached_quit_server(ptr, true); - return MEMCACHED_FAILURE; + return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT); } } } @@ -130,7 +142,7 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, ptr->cached_errno= get_socket_errno(); memcached_quit_server(ptr, true); - return MEMCACHED_FAILURE; + return memcached_set_error(*ptr, MEMCACHED_FAILURE, MEMCACHED_AT); } memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr) @@ -290,6 +302,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr, #endif if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS) continue; + /* fall through */ default: @@ -582,12 +595,15 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr, // UDP Sanity check, make sure that we are not sending somthing too big if (ptr->type == MEMCACHED_CONNECTION_UDP && write_length > MAX_UDP_DATAGRAM_LENGTH) { + *error= MEMCACHED_WRITE_FAILURE; return -1; } if (ptr->write_buffer_offset == 0 || (ptr->type == MEMCACHED_CONNECTION_UDP && ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH)) + { return 0; + } /* Looking for memory overflows */ #if defined(DEBUG) @@ -641,15 +657,19 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr, process_input_buffer(ptr)) continue; - memcached_return_t rc; - rc= io_wait(ptr, MEM_WRITE); - - if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_TIMEOUT) + memcached_return_t rc= io_wait(ptr, MEM_WRITE); + if (memcached_success(rc)) { continue; } + else if (rc == MEMCACHED_TIMEOUT) + { + *error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT); + return -1; + } memcached_quit_server(ptr, true); + *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT); return -1; } case ENOTCONN: @@ -662,10 +682,11 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr, } } - if (ptr->type == MEMCACHED_CONNECTION_UDP && + if (ptr->type == MEMCACHED_CONNECTION_UDP and (size_t)sent_length != write_length) { memcached_quit_server(ptr, true); + *error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT); return -1; } diff --git a/libmemcached/purge.cc b/libmemcached/purge.cc index 07cd135f..36a33ae9 100644 --- a/libmemcached/purge.cc +++ b/libmemcached/purge.cc @@ -2,7 +2,6 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr) { - uint32_t x; memcached_return_t ret= MEMCACHED_SUCCESS; memcached_st *root= (memcached_st *)ptr->root; @@ -26,7 +25,7 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr) { memcached_set_purging(root, true); - return MEMCACHED_WRITE_FAILURE; + return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT); } WATCHPOINT_ASSERT(ptr->fd != -1); @@ -48,7 +47,7 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr) result_ptr= memcached_result_create(root, &result); WATCHPOINT_ASSERT(result_ptr); - for (x= 0; x < no_msg; x++) + for (uint32_t x= 0; x < no_msg; x++) { memcached_result_reset(result_ptr); memcached_return_t rc= memcached_read_one_response(ptr, buffer, @@ -62,8 +61,9 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr) if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE) { WATCHPOINT_ERROR(rc); - ret = rc; + ret= rc; memcached_io_reset(ptr); + memcached_set_error(*ptr, rc, MEMCACHED_AT); } if (ptr->root->callbacks != NULL) diff --git a/libmemcached/return.h b/libmemcached/return.h index 57c0a19f..35ad69d9 100644 --- a/libmemcached/return.h +++ b/libmemcached/return.h @@ -40,8 +40,8 @@ enum memcached_return_t { MEMCACHED_SUCCESS, MEMCACHED_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only - MEMCACHED_CONNECTION_FAILURE, // DEPRECATED - MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED + MEMCACHED_CONNECTION_FAILURE, + MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE MEMCACHED_WRITE_FAILURE, MEMCACHED_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE, diff --git a/libtest/test.c b/libtest/test.c index afb2b965..d54dc92b 100644 --- a/libtest/test.c +++ b/libtest/test.c @@ -178,10 +178,21 @@ int main(int argc, char *argv[]) } if (argc > 1) + { collection_to_run= argv[1]; + } + else if (getenv("TEST_COLLECTION")) + { + collection_to_run= getenv("TEST_COLLECTION"); + } + + if (collection_to_run) + printf("Only testing %s\n", collection_to_run); if (argc == 3) + { wildcard= argv[2]; + } for (next= collection; next->name; next++) { diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index b48f0d08..093721b5 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -5757,7 +5757,7 @@ static test_return_t regression_bug_583031(memcached_st *) test_false(value); test_compare(0, length); - test_true_got(rc == MEMCACHED_TIMEOUT || rc == MEMCACHED_ERRNO || rc == MEMCACHED_FAILURE, memcached_strerror(memc, rc)); + test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(memc, rc)); memcached_free(memc); @@ -6114,7 +6114,8 @@ test_st regression_tests[]= { {"lp:?", 1, (test_callback_fn)regression_bug_ }, {"lp:728286", 1, (test_callback_fn)regression_bug_728286 }, {"lp:581030", 1, (test_callback_fn)regression_bug_581030 }, - {"lp:71231153", 1, (test_callback_fn)regression_bug_71231153 }, + {"lp:71231153 connect()", 1, (test_callback_fn)regression_bug_71231153_connect }, + {"lp:71231153 poll()", 1, (test_callback_fn)regression_bug_71231153_poll }, {0, 0, (test_callback_fn)0} }; diff --git a/tests/parser.cc b/tests/parser.cc index 113d6e00..13561bcc 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -547,24 +547,53 @@ test_return_t test_hostname_port_weight(memcached_st *) return TEST_SUCCESS; } -test_return_t regression_bug_71231153(memcached_st *) +/* + By setting the timeout value to zero, we force poll() to return immediatly. +*/ +test_return_t regression_bug_71231153_connect(memcached_st *) { if (libmemcached_util_ping("10.0.2.252", 0, NULL)) // If for whatever reason someone has a host at this address, skip return TEST_SKIPPED; - memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --CONNECT-TIMEOUT=1 --POLL-TIMEOUT=1")); - test_true(memc); - test_compare(1, memc->connect_timeout); - test_compare(1, memc->poll_timeout); + { // Test the connect-timeout, on a bad host we should get MEMCACHED_CONNECTION_FAILURE + memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --CONNECT-TIMEOUT=0")); + test_true(memc); + test_compare(0, memc->connect_timeout); + test_compare(MEMCACHED_DEFAULT_TIMEOUT, memc->poll_timeout); - memcached_return_t rc; - size_t value_len; - char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc); - test_false(value); - test_compare(0, value_len); - test_true_got(rc == MEMCACHED_TIMEOUT or rc == MEMCACHED_FAILURE or rc == MEMCACHED_ERRNO, memcached_strerror(memc, rc)); + memcached_return_t rc; + size_t value_len; + char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc); + test_false(value); + test_compare(0, value_len); + test_compare_got(MEMCACHED_CONNECTION_FAILURE, rc, memcached_strerror(NULL, rc)); - memcached_free(memc); + memcached_free(memc); + } + + return TEST_SUCCESS; +} + +test_return_t regression_bug_71231153_poll(memcached_st *) +{ + if (libmemcached_util_ping("10.0.2.252", 0, NULL)) // If for whatever reason someone has a host at this address, skip + return TEST_SKIPPED; + + { // Test the poll timeout, on a bad host we should get MEMCACHED_CONNECTION_FAILURE + memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --POLL-TIMEOUT=0")); + test_true(memc); + test_compare(MEMCACHED_DEFAULT_CONNECT_TIMEOUT, memc->connect_timeout); + test_compare(0, memc->poll_timeout); + + memcached_return_t rc; + size_t value_len; + char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc); + test_false(value); + test_compare(0, value_len); + test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(NULL, rc)); + + memcached_free(memc); + } return TEST_SUCCESS; } diff --git a/tests/parser.h b/tests/parser.h index 98d3c1be..15d57a64 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -101,7 +101,10 @@ LIBTEST_INTERNAL_API test_return_t test_hostname_port_weight(memcached_st *); LIBTEST_INTERNAL_API -test_return_t regression_bug_71231153(memcached_st *); +test_return_t regression_bug_71231153_connect(memcached_st *); + +LIBTEST_INTERNAL_API +test_return_t regression_bug_71231153_poll(memcached_st *); #ifdef __cplusplus } -- 2.30.2