rc != MEMCACHED_E2BIG &&
rc != MEMCACHED_END &&
rc != MEMCACHED_ITEM &&
+ rc != MEMCACHED_ERROR &&
rc != MEMCACHED_NOTFOUND &&
rc != MEMCACHED_NOTSTORED &&
rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE &&
MEMCACHED_UNKNOWN_READ_FAILURE,
MEMCACHED_PROTOCOL_ERROR,
MEMCACHED_CLIENT_ERROR,
- MEMCACHED_SERVER_ERROR,
- MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, // DEPRECATED
+ MEMCACHED_SERVER_ERROR, // Server returns "SERVER_ERROR"
+ MEMCACHED_ERROR, // Server returns "ERROR"
MEMCACHED_DATA_EXISTS,
MEMCACHED_DATA_DOES_NOT_EXIST,
MEMCACHED_NOTSTORED,
MEMCACHED_IN_PROGRESS,
MEMCACHED_SERVER_TEMPORARILY_DISABLED,
MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE,
- MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
+ MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */
+ MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE= MEMCACHED_ERROR
};
#ifndef __cplusplus
static memcached_return_t ascii_dump(memcached_st *memc, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
{
- for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++)
+ /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */
+ for (uint32_t x= 0; x < 200; x++)
{
- memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key);
+ char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+ int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
+ if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0)
+ {
+ return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+ memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+ }
- bool exit_slab_loop= false;
- /* MAX_NUMBER_OF_SLAB_CLASSESdefined to 200 in Memcached 1.4.10 */
- for (uint32_t x= 0; x < 200 and (exit_slab_loop == false); x++)
+ // @NOTE the hard coded zero means "no limit"
+ libmemcached_io_vector_st vector[]=
{
- char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
- if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0)
- {
- return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
- memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
- }
+ { memcached_literal_param("stats cachedump ") },
+ { buffer, buffer_length },
+ { memcached_literal_param(" 0\r\n") }
+ };
- libmemcached_io_vector_st vector[]=
- {
- { memcached_literal_param("stats cachedump ") },
- { buffer, buffer_length },
- { memcached_literal_param(" 0 0\r\n") }
- };
+ // Send message to all servers
+ for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++)
+ {
+ memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key);
memcached_return_t vdo_rc;
if (memcached_success((vdo_rc= memcached_vdo(instance, vector, 3, true))))
{
- while (1)
+ // We have sent the message to the server successfully
+ }
+ else
+ {
+ return memcached_set_error(*instance, vdo_rc, MEMCACHED_AT);
+ }
+ }
+
+ // Collect the returned items
+ memcached_server_write_instance_st instance;
+ while ((instance= memcached_io_get_readable_server(memc)))
+ {
+ memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+ if (response_rc == MEMCACHED_ITEM)
+ {
+ char *string_ptr, *end_ptr;
+
+ string_ptr= buffer;
+ string_ptr+= 5; /* Move past ITEM */
+
+ for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
+
+ char *key= string_ptr;
+ key[(size_t)(end_ptr-string_ptr)]= 0;
+
+ for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
{
- memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
- fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, response_rc));
- if (response_rc == MEMCACHED_ITEM)
- {
- char *string_ptr, *end_ptr;
-
- string_ptr= buffer;
- string_ptr+= 5; /* Move past ITEM */
-
- for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
-
- char *key= string_ptr;
- key[(size_t)(end_ptr-string_ptr)]= 0;
-
- for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
- {
- memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context);
- if (callback_rc != MEMCACHED_SUCCESS)
- {
- // @todo build up a message for the error from the value
- memcached_set_error(*instance, callback_rc, MEMCACHED_AT);
- break;
- }
- }
- }
- else if (response_rc == MEMCACHED_END)
- {
- // No additional items were found
- exit_slab_loop= true;
- break;
- }
- else if (response_rc == MEMCACHED_SERVER_ERROR or response_rc == MEMCACHED_CLIENT_ERROR)
- {
- /* If we try to request stats cachedump for a slab class that is too big
- * the server will return an incorrect error message:
- * "MEMCACHED_SERVER_ERROR failed to allocate memory"
- * This isn't really a fatal error, so let's just skip it. I want to
- * fix the return value from the memcached server to a CLIENT_ERROR,
- * so let's add support for that as well right now.
- */
- exit_slab_loop= true;
- break;
- }
- else
+ memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context);
+ if (callback_rc != MEMCACHED_SUCCESS)
{
- memcached_set_error(*instance, response_rc, MEMCACHED_AT);
- exit_slab_loop= true;
+ // @todo build up a message for the error from the value
+ memcached_set_error(*instance, callback_rc, MEMCACHED_AT);
break;
}
}
}
+ else if (response_rc == MEMCACHED_END)
+ {
+ // All items have been returned
+ }
+ else if (response_rc == MEMCACHED_SERVER_ERROR or response_rc == MEMCACHED_CLIENT_ERROR or response_rc == MEMCACHED_ERROR)
+ {
+ /* If we try to request stats cachedump for a slab class that is too big
+ * the server will return an incorrect error message:
+ * "MEMCACHED_SERVER_ERROR failed to allocate memory"
+ * This isn't really a fatal error, so let's just skip it. I want to
+ * fix the return value from the memcached server to a CLIENT_ERROR,
+ * so let's add support for that as well right now.
+ */
+ assert(response_rc == MEMCACHED_SUCCESS); // Just fail
+ return response_rc;
+ }
else
{
- exit_slab_loop= true;
- memcached_set_error(*instance, vdo_rc, MEMCACHED_AT);
+ // IO error of some sort must have occurred
+ return memcached_set_error(*instance, response_rc, MEMCACHED_AT);
}
- fprintf(stderr, "Was able to request %u slab\n", x);
}
}
return MEMCACHED_PROTOCOL_ERROR;
}
#endif
+ // ERROR
+ else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R')
+ {
+ return MEMCACHED_ERROR;
+ }
// EXISTS
else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
{
rc != MEMCACHED_DELETED and
rc != MEMCACHED_E2BIG and
rc != MEMCACHED_END and
+ rc != MEMCACHED_ERROR and
rc != MEMCACHED_ITEM and
rc != MEMCACHED_NOTFOUND and
rc != MEMCACHED_NOTSTORED and
memcached_server_execute_fn callback,
void *context)
{
+ if (callback == NULL)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
+ bool some_errors= false;;
for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
{
memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
- unsigned int iferror= (*callback)(ptr, instance, context);
-
- if (iferror)
+ memcached_return_t rc= (*callback)(ptr, instance, context);
+ if (rc == MEMCACHED_INVALID_ARGUMENTS)
+ {
+ return rc;
+ }
+ else if (memcached_fatal(rc))
{
- continue;
+ some_errors= true;
}
}
+ (void)some_errors;
return MEMCACHED_SUCCESS;
}
};
-static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char *value)
+static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key, const char *value)
{
if (strlen(key) < 1)
else if (not strcmp("rusage_user", key))
{
char *walk_ptr;
- for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+ for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
*walk_ptr= 0;
walk_ptr++;
memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10);
else if (not strcmp("rusage_system", key))
{
char *walk_ptr;
- for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+ for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
*walk_ptr= 0;
walk_ptr++;
memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10);
return rc;
}
- if (memc_stat)
- {
- if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
- {
- WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
- WATCHPOINT_ASSERT(0);
- }
- }
-
if (check && check->func)
{
size_t key_length= strlen(buffer);
buffer+key_length+1, strlen(buffer+key_length+1),
check->context);
}
+
+ if (memc_stat)
+ {
+ if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
+ {
+ WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+ WATCHPOINT_ASSERT(0);
+ }
+ }
} while (1);
/*
if (memcached_success(rc))
{
char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
- while ((rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL)) == MEMCACHED_STAT)
+ while ((rc= memcached_response(instance, buffer, sizeof(buffer), NULL)) == MEMCACHED_STAT)
{
- char *string_ptr, *end_ptr;
- char *key, *value;
-
- string_ptr= buffer;
+ char *string_ptr= buffer;
string_ptr+= 5; /* Move past STAT */
+
+ char *end_ptr;
for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {};
- key= string_ptr;
- key[(size_t)(end_ptr-string_ptr)]= 0;
+ char *key= string_ptr;
+ key[size_t(end_ptr-string_ptr)]= 0;
string_ptr= end_ptr + 1;
for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++) {};
- value= string_ptr;
+ char *value= string_ptr;
value[(size_t)(end_ptr -string_ptr)]= 0;
- if (memc_stat)
- {
- unlikely((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
- {
- WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
- WATCHPOINT_ASSERT(0);
- }
- }
+#if 0
+ bool check_bool= bool(check);
+ bool check_func_bool= bool(check) ? bool(check->func) : false;
+ fprintf(stderr, "%s:%d %s %s %d:%d\n", __FILE__, __LINE__, key, value, check_bool, check_func_bool);
+#endif
- if (check && check->func)
+ if (check and check->func)
{
check->func(instance,
key, strlen(key),
value, strlen(value),
check->context);
}
+
+ if (memc_stat)
+ {
+ if((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
+ {
+ WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+ WATCHPOINT_ASSERT(0);
+ }
+ }
}
}
+ if (rc == MEMCACHED_ERROR)
+ {
+ return MEMCACHED_INVALID_ARGUMENTS;
+ }
+
if (rc == MEMCACHED_END)
{
return MEMCACHED_SUCCESS;
temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
}
+ // Special case where "args" is invalid
+ if (temp_return == MEMCACHED_INVALID_ARGUMENTS)
+ {
+ rc= MEMCACHED_INVALID_ARGUMENTS;
+ break;
+ }
+
if (memcached_failed(temp_return))
{
rc= MEMCACHED_SOME_ERRORS;
memcached_stat_st *,
memcached_return_t *error)
{
- if (not ptr)
+ if (ptr == NULL)
+ {
return NULL;
+ }
char **list= static_cast<char **>(libmemcached_malloc(ptr, sizeof(memcached_stat_keys)));
if (not list)
void *context)
{
memcached_return_t rc;
- struct local_context *check= (struct local_context *)context;
+ local_context *check= (struct local_context *)context;
- if (ptr->flags.binary_protocol)
+ if (memcached_is_binary(ptr))
{
rc= binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
}
{
memcached_version(memc);
- struct local_context check(func, context, args, args ? strlen(args) : 0);
+ local_context check(func, context, args, args ? strlen(args) : 0);
return memcached_server_execute(memc, call_stat_fn, (void *)&check);
}
case MEMCACHED_WRITE_FAILURE:
return "WRITE FAILURE";
- case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: // DEPRECATED
- return "CONNECTION SOCKET CREATE FAILURE";
+ case MEMCACHED_ERROR:
+ return "ERROR was returned by server";
case MEMCACHED_DATA_EXISTS:
return "CONNECTION DATA EXISTS";
*/
#include <config.h>
+
+#include <cstdlib>
+#include <climits>
+
#include <libtest/test.hpp>
#include <libmemcached-1.0/memcached.h>
#include "tests/libmemcached-1.0/dump.h"
static memcached_return_t callback_dump_counter(const memcached_st *,
- const char *key,
- size_t length,
+ const char*, // key,
+ size_t, // length,
void *context)
{
size_t *counter= (size_t *)context;
+#if 0
std::cerr.write(key, length);
std::cerr << std::endl;
-
+#endif
*counter= *counter +1;
return MEMCACHED_SUCCESS;
}
+static memcached_return_t item_counter(memcached_server_instance_st ,
+ const char *key, size_t key_length,
+ const char *value, size_t, // value_length,
+ void *context)
+{
+ if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0))
+ {
+ uint64_t* counter= (uint64_t*)context;
+ unsigned long number_value= strtoul(value, (char **)NULL, 10);
+ if (number_value == ULONG_MAX)
+ {
+ return MEMCACHED_FAILURE;
+ }
+ *counter= *counter +number_value;
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
test_return_t memcached_dump_TEST(memcached_st *memc)
{
test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
memcached_dump_fn callbacks[1];
callbacks[0]= &callback_dump_counter;
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_zero(counter);
+
test_compare_got(MEMCACHED_SUCCESS, memcached_dump(memc, callbacks, &count, 1), memcached_last_error_message(memc));
return TEST_SUCCESS;
}
memcached_quit(memc);
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_true_got(counter > 0, counter);
+
size_t count= 0;
memcached_dump_fn callbacks[1];
callbacks[0]= &callback_dump_counter;
memcached_dump(memc, callbacks, &count, 1),
memcached_last_error_message(memc));
-#if 0
test_compare(size_t(memcached_dump_TEST2_COUNT), count);
-#endif
return TEST_SUCCESS;
}
tests/ketama_test_cases.h \
tests/ketama_test_cases_spy.h \
tests/libmemcached-1.0/dump.h \
+ tests/libmemcached-1.0/stat.h \
tests/namespace.h \
tests/parser.h \
tests/pool.h \
tests/libmemcached-1.0/namespace.cc \
tests/libmemcached-1.0/parser.cc \
tests/libmemcached-1.0/server_add.cc \
+ tests/libmemcached-1.0/stat.cc \
tests/libmemcached-1.0/touch.cc \
tests/libmemcached-1.0/virtual_buckets.cc
#include "tests/namespace.h"
#include "tests/parser.h"
#include "tests/libmemcached-1.0/dump.h"
+#include "tests/libmemcached-1.0/stat.h"
#include "tests/touch.h"
#include "tests/callbacks.h"
#include "tests/pool.h"
{
uint32_t values[] = { 851992627U, 2337886783U, 4109241422U, 4001849190U,
982370485U, 1263635348U, 4242906218U, 3829656100U,
- 1891735253U, 334139633U, 2257084983U, 3088286104U,
+ 1891735253U, 334139633U, 2257084983U, 3351789013U,
13199785U, 2542027183U, 1097051614U, 199566778U,
2748246961U, 2465192557U, 1664094137U, 2405439045U,
1842224848U, 692413798U, 3479807801U, 919913813U,
{0, 0, 0}
};
+test_st memcached_stat_tests[] ={
+ {"memcached_stat() INVALID ARG", 0, (test_callback_fn*)memcached_stat_TEST},
+ {"memcached_stat()", 0, (test_callback_fn*)memcached_stat_TEST2},
+ {0, 0, 0}
+};
+
test_st behavior_tests[] ={
{"libmemcached_string_behavior()", false, (test_callback_fn*)libmemcached_string_behavior_test},
{"libmemcached_string_distribution()", false, (test_callback_fn*)libmemcached_string_distribution_test},
{"memcached_server_get_last_disconnect", 0, 0, memcached_server_get_last_disconnect_tests},
{"touch", 0, 0, touch_tests},
{"touch", (test_callback_fn*)pre_binary, 0, touch_tests},
+ {"memcached_stat()", 0, 0, memcached_stat_tests},
{0, 0, 0, 0}
};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+
+#include <cstdlib>
+#include <climits>
+
+#include <libtest/test.hpp>
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcached/util.h>
+
+using namespace libtest;
+
+#include "tests/libmemcached-1.0/stat.h"
+
+static memcached_return_t item_counter(memcached_server_instance_st ,
+ const char *key, size_t key_length,
+ const char *value, size_t, // value_length,
+ void *context)
+{
+ if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0))
+ {
+ uint64_t* counter= (uint64_t*)context;
+ unsigned long number_value= strtoul(value, (char **)NULL, 10);
+ if (number_value == ULONG_MAX)
+ {
+ return MEMCACHED_FAILURE;
+ }
+ *counter= *counter +number_value;
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
+test_return_t memcached_stat_TEST(memcached_st *memc)
+{
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_INVALID_ARGUMENTS,
+ memcached_stat_execute(memc, "BAD_ARG_VALUE", item_counter, &counter),
+ memcached_last_error_message(memc));
+
+ return TEST_SUCCESS;
+}
+
+#define memcached_dump_TEST2_COUNT 64
+test_return_t memcached_stat_TEST2(memcached_st *memc)
+{
+ test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+ /* The dump test relies on there being at least 32 items in memcached */
+ for (uint32_t x= 0; x < memcached_dump_TEST2_COUNT; x++)
+ {
+ char key[1024];
+
+ int length= snprintf(key, sizeof(key), "%s%u", __func__, x);
+
+ test_true(length > 0);
+
+ test_compare_hint(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, length,
+ NULL, 0, // Zero length values
+ time_t(0), uint32_t(0)),
+ memcached_last_error_message(memc));
+ }
+ memcached_quit(memc);
+
+ uint64_t counter= 0;
+ test_compare_got(MEMCACHED_SUCCESS,
+ memcached_stat_execute(memc, NULL, item_counter, &counter),
+ memcached_last_error_message(memc));
+ test_true_got(counter > 0, counter);
+
+ return TEST_SUCCESS;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t memcached_stat_TEST(memcached_st *);
+test_return_t memcached_stat_TEST2(memcached_st *);