From 1f5cf20c75c7187df1d648a5a200b52db3f17db1 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Mon, 21 Mar 2011 00:07:48 -0700 Subject: [PATCH] Import parser/etc --- libmemcached/array.c | 64 ++++++ libmemcached/array.h | 53 +++++ libmemcached/auto.c | 40 +++- libmemcached/auto.h | 103 ++++----- libmemcached/behavior.c | 14 +- libmemcached/common.h | 13 +- libmemcached/error.c | 166 +++++++++++++++ libmemcached/error.h | 65 ++++++ libmemcached/include.am | 7 +- libmemcached/is.h | 48 +++++ libmemcached/memcached.c | 71 ++++--- libmemcached/memcached.h | 6 + libmemcached/options.cc | 4 + libmemcached/options/parser.yy | 46 +++- libmemcached/options/scanner.l | 22 +- libmemcached/string.h | 11 + libmemcached/types.h | 3 + libtest/server.c | 2 +- tests/basic.cc | 130 ++++++++++++ tests/basic.h | 66 ++++++ tests/error_conditions.cc | 70 ++++++ tests/error_conditions.h | 50 +++++ tests/include.am | 4 + tests/mem_functions.c | 24 ++- tests/parser.cc | 375 +++++++++++++++++++-------------- tests/parser.h | 3 + 26 files changed, 1192 insertions(+), 268 deletions(-) create mode 100644 libmemcached/array.c create mode 100644 libmemcached/array.h create mode 100644 libmemcached/error.c create mode 100644 libmemcached/error.h create mode 100644 libmemcached/is.h create mode 100644 tests/basic.cc create mode 100644 tests/basic.h create mode 100644 tests/error_conditions.cc create mode 100644 tests/error_conditions.h diff --git a/libmemcached/array.c b/libmemcached/array.c new file mode 100644 index 00000000..f8facbaa --- /dev/null +++ b/libmemcached/array.c @@ -0,0 +1,64 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * LibMemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#include "libmemcached/common.h" + +struct memcached_array_st +{ + size_t size; + char c_str[]; +}; + +memcached_array_st *memcached_strcpy(const char *str, size_t str_length) +{ + memcached_array_st *array= (struct memcached_array_st *)malloc(sizeof(struct memcached_array_st) +str_length +1); + + array->size= str_length; + memcpy(array->c_str, str, str_length); + array->c_str[str_length]= 0; + + return array; +} + +void memcached_array_free(memcached_array_st *array) +{ + WATCHPOINT_ASSERT(array); + if (array) + free(array); +} diff --git a/libmemcached/array.h b/libmemcached/array.h new file mode 100644 index 00000000..78846b61 --- /dev/null +++ b/libmemcached/array.h @@ -0,0 +1,53 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * LibMemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#ifdef __cplusplus +extern "C" { +#endif + +LIBMEMCACHED_LOCAL +memcached_array_st *memcached_strcpy(const char *str, size_t str_length); + +LIBMEMCACHED_LOCAL +void memcached_array_free(memcached_array_st *array); + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/libmemcached/auto.c b/libmemcached/auto.c index a221144f..c2033b37 100644 --- a/libmemcached/auto.c +++ b/libmemcached/auto.c @@ -24,8 +24,8 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, memcached_server_write_instance_st instance; bool no_reply= ptr->flags.no_reply; - unlikely (memcached_server_count(ptr) == 0) - return MEMCACHED_NO_SERVERS; + if (memcached_server_count(ptr) == 0) + return memcached_set_error(ptr, MEMCACHED_NO_SERVERS, NULL); if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; @@ -91,8 +91,8 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd, memcached_server_write_instance_st instance; bool no_reply= ptr->flags.no_reply; - unlikely (memcached_server_count(ptr) == 0) - return MEMCACHED_NO_SERVERS; + if (memcached_server_count(ptr) == 0) + return memcached_set_error(ptr, MEMCACHED_NO_SERVERS, NULL); server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length); instance= memcached_server_instance_fetch(ptr, server_key); @@ -140,6 +140,10 @@ memcached_return_t memcached_increment(memcached_st *ptr, uint32_t offset, uint64_t *value) { + uint64_t local_value; + if (! value) + value= &local_value; + return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value); } @@ -148,6 +152,10 @@ memcached_return_t memcached_decrement(memcached_st *ptr, uint32_t offset, uint64_t *value) { + uint64_t local_value; + if (! value) + value= &local_value; + return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value); } @@ -161,6 +169,10 @@ memcached_return_t memcached_increment_by_key(memcached_st *ptr, unlikely (rc != MEMCACHED_SUCCESS) return rc; + uint64_t local_value; + if (! value) + value= &local_value; + LIBMEMCACHED_MEMCACHED_INCREMENT_START(); if (ptr->flags.binary_protocol) { @@ -189,6 +201,10 @@ memcached_return_t memcached_decrement_by_key(memcached_st *ptr, unlikely (rc != MEMCACHED_SUCCESS) return rc; + uint64_t local_value; + if (! value) + value= &local_value; + LIBMEMCACHED_MEMCACHED_DECREMENT_START(); if (ptr->flags.binary_protocol) { @@ -215,6 +231,10 @@ memcached_return_t memcached_increment_with_initial(memcached_st *ptr, time_t expiration, uint64_t *value) { + uint64_t local_value; + if (! value) + value= &local_value; + return memcached_increment_with_initial_by_key(ptr, key, key_length, key, key_length, offset, initial, expiration, value); @@ -234,6 +254,10 @@ memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr, unlikely (rc != MEMCACHED_SUCCESS) return rc; + uint64_t local_value; + if (! value) + value= &local_value; + LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START(); if (ptr->flags.binary_protocol) rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT, @@ -256,6 +280,10 @@ memcached_return_t memcached_decrement_with_initial(memcached_st *ptr, time_t expiration, uint64_t *value) { + uint64_t local_value; + if (! value) + value= &local_value; + return memcached_decrement_with_initial_by_key(ptr, key, key_length, key, key_length, offset, initial, expiration, value); @@ -275,6 +303,10 @@ memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr, unlikely (rc != MEMCACHED_SUCCESS) return rc; + uint64_t local_value; + if (! value) + value= &local_value; + LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START(); if (ptr->flags.binary_protocol) { diff --git a/libmemcached/auto.h b/libmemcached/auto.h index 227be9df..aa1b23dc 100644 --- a/libmemcached/auto.h +++ b/libmemcached/auto.h @@ -17,66 +17,69 @@ extern "C" { #endif LIBMEMCACHED_API -memcached_return_t memcached_increment(memcached_st *ptr, - const char *key, size_t key_length, - uint32_t offset, - uint64_t *value); + memcached_return_t memcached_increment(memcached_st *ptr, + const char *key, size_t key_length, + uint32_t offset, + uint64_t *value); LIBMEMCACHED_API -memcached_return_t memcached_decrement(memcached_st *ptr, - const char *key, size_t key_length, - uint32_t offset, - uint64_t *value); + memcached_return_t memcached_decrement(memcached_st *ptr, + const char *key, size_t key_length, + uint32_t offset, + uint64_t *value); LIBMEMCACHED_API -memcached_return_t memcached_increment_by_key(memcached_st *ptr, - const char *master_key, size_t master_key_length, - const char *key, size_t key_length, - uint64_t offset, - uint64_t *value); + memcached_return_t memcached_increment_by_key(memcached_st *ptr, + const char *master_key, size_t master_key_length, + const char *key, size_t key_length, + uint64_t offset, + uint64_t *value); LIBMEMCACHED_API -memcached_return_t memcached_decrement_by_key(memcached_st *ptr, - const char *master_key, size_t master_key_length, - const char *key, size_t key_length, - uint64_t offset, - uint64_t *value); + memcached_return_t memcached_decrement_by_key(memcached_st *ptr, + const char *master_key, size_t master_key_length, + const char *key, size_t key_length, + uint64_t offset, + uint64_t *value); LIBMEMCACHED_API -memcached_return_t memcached_increment_with_initial(memcached_st *ptr, - const char *key, - size_t key_length, - uint64_t offset, - uint64_t initial, - time_t expiration, - uint64_t *value); + memcached_return_t memcached_increment_with_initial(memcached_st *ptr, + const char *key, + size_t key_length, + uint64_t offset, + uint64_t initial, + time_t expiration, + uint64_t *value); + LIBMEMCACHED_API -memcached_return_t memcached_decrement_with_initial(memcached_st *ptr, - const char *key, - size_t key_length, - uint64_t offset, - uint64_t initial, - time_t expiration, - uint64_t *value); + memcached_return_t memcached_decrement_with_initial(memcached_st *ptr, + const char *key, + size_t key_length, + uint64_t offset, + uint64_t initial, + time_t expiration, + uint64_t *value); + LIBMEMCACHED_API -memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr, - const char *master_key, - size_t master_key_length, - const char *key, - size_t key_length, - uint64_t offset, - uint64_t initial, - time_t expiration, - uint64_t *value); + memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr, + const char *master_key, + size_t master_key_length, + const char *key, + size_t key_length, + uint64_t offset, + uint64_t initial, + time_t expiration, + uint64_t *value); + LIBMEMCACHED_API -memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr, - const char *master_key, - size_t master_key_length, - const char *key, - size_t key_length, - uint64_t offset, - uint64_t initial, - time_t expiration, - uint64_t *value); + memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr, + const char *master_key, + size_t master_key_length, + const char *key, + size_t key_length, + uint64_t offset, + uint64_t initial, + time_t expiration, + uint64_t *value); #ifdef __cplusplus } diff --git a/libmemcached/behavior.c b/libmemcached/behavior.c index da111351..5116b645 100644 --- a/libmemcached/behavior.c +++ b/libmemcached/behavior.c @@ -317,18 +317,18 @@ uint64_t memcached_behavior_get(memcached_st *ptr, /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(instance)) != MEMCACHED_SUCCESS) { - return EXIT_SUCCESS; + return 0; } if (memcached_io_wait_for_write(instance) != MEMCACHED_SUCCESS) { - return EXIT_SUCCESS; + return 0; } if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, &sock_size, &sock_length) < 0) { ptr->cached_errno= errno; - return EXIT_SUCCESS; /* Zero means error */ + return 0; /* Zero means error */ } } @@ -353,18 +353,18 @@ uint64_t memcached_behavior_get(memcached_st *ptr, /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(instance)) != MEMCACHED_SUCCESS) { - return EXIT_SUCCESS; + return 0; } if (memcached_io_wait_for_write(instance) != MEMCACHED_SUCCESS) { - return EXIT_SUCCESS; + return 0; } if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, &sock_size, &sock_length) < 0) { ptr->cached_errno= errno; - return EXIT_SUCCESS; /* Zero means error */ + return 0; /* Zero means error */ } } @@ -390,7 +390,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr, case MEMCACHED_BEHAVIOR_MAX: default: WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */ - return EXIT_SUCCESS; + return 0; } /* NOTREACHED */ diff --git a/libmemcached/common.h b/libmemcached/common.h index a7d95af7..26182b19 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -16,7 +16,7 @@ #ifndef __LIBMEMCACHED_COMMON_H__ #define __LIBMEMCACHED_COMMON_H__ -#include "config.h" +#include #include #include @@ -47,6 +47,7 @@ #include "libmemcached/memcached.h" #include "libmemcached/watchpoint.h" +#include "libmemcached/is.h" typedef struct memcached_server_st * memcached_server_write_instance_st; @@ -115,16 +116,6 @@ memcached_return_t run_distribution(memcached_st *ptr); #define memcached_server_response_decrement(A) (A)->cursor_active-- #define memcached_server_response_reset(A) (A)->cursor_active=0 -// These are private -#define memcached_is_allocated(__object) ((__object)->options.is_allocated) -#define memcached_is_initialized(__object) ((__object)->options.is_initialized) -#define memcached_is_purging(__object) ((__object)->state.is_purging) -#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input) -#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value)) -#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value)) -#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value)) -#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated(= (__value)) - LIBMEMCACHED_LOCAL void set_last_disconnected_host(memcached_server_write_instance_st ptr); diff --git a/libmemcached/error.c b/libmemcached/error.c new file mode 100644 index 00000000..206e1b41 --- /dev/null +++ b/libmemcached/error.c @@ -0,0 +1,166 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * LibMemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 "libmemcached/common.h" + +struct memcached_error_st +{ + memcached_st *root; + struct memcached_error_st *next; + memcached_return_t rc; + int local_errno; + size_t size; + char c_str[]; +}; + +static memcached_error_st *_set(memcached_st *memc, memcached_string_t *str) +{ + if (! memc) + return NULL; + + memcached_error_st *error; + error= (struct memcached_error_st *)libmemcached_malloc(memc, sizeof(struct memcached_error_st) +(str ? str->size :0) +1); + + if (! error) + return NULL; + + error->root= memc; + + if (str) + { + error->size= str->size; + memcpy(error->c_str, str->c_str, str->size); + } + error->c_str[(str ? str->size :0)]= 0; + + error->next= memc->error_messages; + memc->error_messages= error; + + return error; +} + +memcached_return_t memcached_set_error(memcached_st *memc, memcached_return_t rc, memcached_string_t *str) +{ + if (rc == MEMCACHED_SUCCESS) + return MEMCACHED_SUCCESS; + + memcached_error_st *error= _set(memc, str); + + if (error) + { + error->local_errno= 0; + error->rc= rc; + } + + return rc; +} + +memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str) +{ + memcached_error_st *error= _set(memc, str); + + if (error) + { + error->local_errno= local_errno; + error->rc= MEMCACHED_ERRNO; + } + + return error->rc; +} + +static void _error_free(memcached_error_st *error) +{ + if (! error) + return; + + _error_free(error->next); + + if (error && error->root) + { + libmemcached_free(error->root, error); + } + else if (error) + { + free(error); + } +} + +void memcached_error_free(memcached_st *self) +{ + if (! self) + return; + + _error_free(self->error_messages); +} + +const char *memcached_last_error_message(memcached_st *memc) +{ + if (! memc) + return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS); + + if (! memc->error_messages) + return memcached_strerror(memc, MEMCACHED_SUCCESS); + + if (! memc->error_messages->c_str) + { + return memcached_strerror(memc, memc->error_messages->rc); + } + + return memc->error_messages->c_str; +} + +memcached_return_t memcached_last_error(memcached_st *memc) +{ + if (! memc) + return MEMCACHED_INVALID_ARGUMENTS; + + if (! memc->error_messages) + return MEMCACHED_SUCCESS; + + return memc->error_messages->rc; +} + +memcached_return_t memcached_last_error_errno(memcached_st *memc) +{ + if (! memc) + return MEMCACHED_INVALID_ARGUMENTS; + + if (! memc->error_messages) + return MEMCACHED_SUCCESS; + + return memc->error_messages->local_errno; +} diff --git a/libmemcached/error.h b/libmemcached/error.h new file mode 100644 index 00000000..28038d09 --- /dev/null +++ b/libmemcached/error.h @@ -0,0 +1,65 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * LibMemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#ifdef __cplusplus +extern "C" { +#endif + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_set_error(memcached_st *memc, memcached_return_t rc, memcached_string_t *str); + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str); + +LIBMEMCACHED_LOCAL + void memcached_error_free(memcached_st *error); + +LIBMEMCACHED_API + const char *memcached_last_error_message(memcached_st *memc); + +LIBMEMCACHED_API + memcached_return_t memcached_last_error(memcached_st *memc); + +LIBMEMCACHED_API + memcached_return_t memcached_last_error_errno(memcached_st *memc); + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/libmemcached/include.am b/libmemcached/include.am index 75bcf600..b0d07319 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -17,6 +17,7 @@ noinst_HEADERS+= \ libmemcached/do.h \ libmemcached/internal.h \ libmemcached/io.h \ + libmemcached/is.h \ libmemcached/libmemcached_probes.h \ libmemcached/protocol/ascii_handler.h \ libmemcached/protocol/binary_handler.h \ @@ -26,6 +27,7 @@ noinst_HEADERS+= \ nobase_include_HEADERS+= \ libmemcached/allocators.h \ libmemcached/analyze.h \ + libmemcached/array.h \ libmemcached/auto.h \ libmemcached/behavior.h \ libmemcached/callback.h \ @@ -33,6 +35,7 @@ nobase_include_HEADERS+= \ libmemcached/constants.h \ libmemcached/delete.h \ libmemcached/dump.h \ + libmemcached/error.h \ libmemcached/exception.hpp \ libmemcached/fetch.h \ libmemcached/flush.h \ @@ -92,22 +95,24 @@ libmemcached_libmemcached_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} libmemcached_libmemcached_la_SOURCES+= \ libmemcached/allocators.c \ libmemcached/analyze.c \ + libmemcached/array.c \ libmemcached/auto.c \ libmemcached/behavior.c \ libmemcached/connect.c \ libmemcached/delete.c \ libmemcached/do.c \ libmemcached/dump.c \ + libmemcached/error.c \ libmemcached/fetch.c \ libmemcached/flush.c \ libmemcached/flush_buffers.c \ libmemcached/get.c \ libmemcached/hash.c \ - libmemcached/options.cc \ libmemcached/hosts.c \ libmemcached/io.c \ libmemcached/key.c \ libmemcached/memcached.c \ + libmemcached/options.cc \ libmemcached/parse.c \ libmemcached/purge.c \ libmemcached/quit.c \ diff --git a/libmemcached/is.h b/libmemcached/is.h new file mode 100644 index 00000000..f155334b --- /dev/null +++ b/libmemcached/is.h @@ -0,0 +1,48 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * LibMemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +/* These are private */ +#define memcached_is_allocated(__object) ((__object)->options.is_allocated) +#define memcached_is_initialized(__object) ((__object)->options.is_initialized) +#define memcached_is_purging(__object) ((__object)->state.is_purging) +#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input) +#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value)) +#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value)) +#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value)) +#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated= (__value)) diff --git a/libmemcached/memcached.c b/libmemcached/memcached.c index b0333569..3a4e4c4a 100644 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@ -97,9 +97,42 @@ static inline bool _memcached_init(memcached_st *self) self->sasl.callbacks= NULL; self->sasl.is_allocated= false; + self->error_messages= NULL; + return true; } +static void _free(memcached_st *ptr, bool release_st) +{ + /* If we have anything open, lets close it now */ + memcached_quit(ptr); + memcached_server_list_free(memcached_server_list(ptr)); + memcached_result_free(&ptr->result); + + if (ptr->last_disconnected_server) + memcached_server_free(ptr->last_disconnected_server); + + if (ptr->on_cleanup) + ptr->on_cleanup(ptr); + + if (ptr->continuum) + libmemcached_free(ptr, ptr->continuum); + + memcached_error_free(ptr); + + if (ptr->sasl.callbacks) + { +#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT + memcached_destroy_sasl_auth_data(ptr); +#endif + } + + if (memcached_is_allocated(ptr) && release_st) + { + libmemcached_free(ptr, ptr); + } +} + memcached_st *memcached_create(memcached_st *ptr) { if (ptr == NULL) @@ -140,6 +173,18 @@ memcached_st *memcached_create(memcached_st *ptr) return ptr; } +void memcached_reset(memcached_st *ptr) +{ + WATCHPOINT_ASSERT(ptr); + if (! ptr) + return; + + bool stored_is_allocated= memcached_is_allocated(ptr); + _free(ptr, false); + memcached_create(ptr); + memcached_set_allocated(ptr, stored_is_allocated); +} + void memcached_servers_reset(memcached_st *ptr) { memcached_server_list_free(memcached_server_list(ptr)); @@ -165,31 +210,7 @@ void memcached_reset_last_disconnected_server(memcached_st *ptr) void memcached_free(memcached_st *ptr) { - /* If we have anything open, lets close it now */ - memcached_quit(ptr); - memcached_server_list_free(memcached_server_list(ptr)); - memcached_result_free(&ptr->result); - - if (ptr->last_disconnected_server) - memcached_server_free(ptr->last_disconnected_server); - - if (ptr->on_cleanup) - ptr->on_cleanup(ptr); - - if (ptr->continuum) - libmemcached_free(ptr, ptr->continuum); - - if (ptr->sasl.callbacks) - { -#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT - memcached_destroy_sasl_auth_data(ptr); -#endif - } - - if (memcached_is_allocated(ptr)) - { - libmemcached_free(ptr, ptr); - } + _free(ptr, true); } /* diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 56a5a78f..bef6354a 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include // Everything above this line must be in the order specified. @@ -127,6 +129,7 @@ struct memcached_st { memcached_trigger_delete_key_fn delete_trigger; memcached_callback_st *callbacks; struct memcached_sasl_st sasl; + struct memcached_error_st *error_messages; char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE]; struct { bool is_allocated:1; @@ -147,6 +150,9 @@ memcached_st *memcached_create(memcached_st *ptr); LIBMEMCACHED_API void memcached_free(memcached_st *ptr); +LIBMEMCACHED_API +void memcached_reset(memcached_st *ptr); + LIBMEMCACHED_API void memcached_reset_last_disconnected_server(memcached_st *ptr); diff --git a/libmemcached/options.cc b/libmemcached/options.cc index 1bf2ffa1..0d8c39f2 100644 --- a/libmemcached/options.cc +++ b/libmemcached/options.cc @@ -48,6 +48,10 @@ memcached_return_t memcached_parse_options(memcached_st *self, char const *optio memset(&pp, 0, sizeof(type_st)); + WATCHPOINT_ASSERT(self); + if (! self) + return MEMCACHED_INVALID_ARGUMENTS; + pp.buf= option_string; pp.memc= self; pp.length= length; diff --git a/libmemcached/options/parser.yy b/libmemcached/options/parser.yy index 3a7cee2e..8cd16d53 100644 --- a/libmemcached/options/parser.yy +++ b/libmemcached/options/parser.yy @@ -30,12 +30,12 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" #include -inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, const char *str) +inline void libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, const char *str) { -#if 0 - std::cerr << str << std::endl; -#endif - return 0; + memcached_string_t local_string; + local_string.size= strlen(str); + local_string.c_str= str; + memcached_set_error(parser->memc, MEMCACHED_FAILURE, &local_string); } @@ -98,6 +98,9 @@ inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, %token USE_UDP %token VERIFY_KEY +/* Callbacks */ +%token PREFIX_KEY + /* Hash types */ %token MD5 %token CRC @@ -119,12 +122,15 @@ inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, %token NUMBER %token FLOAT -%token IDENTIFIER -%token SERVER_WITH_PORT +%token HOSTNAME +%token HOSTNAME_WITH_PORT %token IPADDRESS %token IPADDRESS_WITH_PORT +%token STRING +%token QUOTED_STRING %type server +%type string %type distribution %type hash %type behavior_boolean @@ -152,6 +158,10 @@ expression: ; behaviors: + PREFIX_KEY '=' string + { + memcached_callback_set(parser->memc, MEMCACHED_CALLBACK_PREFIX_KEY, std::string($3.c_str, $3.length).c_str()); + } | DISTRIBUTION '=' distribution { memcached_behavior_set(parser->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $3); @@ -311,13 +321,19 @@ server_list: ; server: - SERVER_WITH_PORT NUMBER + HOSTNAME_WITH_PORT NUMBER { $$.c_str= $1.c_str; $$.length= $1.length -1; $$.port= $2; } - | IDENTIFIER + | HOSTNAME + { + $$.c_str= $1.c_str; + $$.length= $1.length; + $$.port= MEMCACHED_DEFAULT_PORT; + } + | STRING /* a match can be against "localhost" which is just a string */ { $$.c_str= $1.c_str; $$.length= $1.length; @@ -376,6 +392,18 @@ hash: } ; +string: + STRING + { + $$= $1; + } + | QUOTED_STRING + { + $$.c_str= $1.c_str +1; + $$.length= $1.length -2; + } + ; + distribution: CONSISTENT { diff --git a/libmemcached/options/scanner.l b/libmemcached/options/scanner.l index 1afc50eb..3a135ff9 100644 --- a/libmemcached/options/scanner.l +++ b/libmemcached/options/scanner.l @@ -148,6 +148,9 @@ USER-DATA { return USER_DATA; } USE_UDP { return USE_UDP; } USE-UDP { return USE_UDP; } +PREFIX-KEY { return PREFIX_KEY; } +PREFIX_KEY { return PREFIX_KEY; } + CONSISTENT { return CONSISTENT; } MODULA { return MODULA; } RANDOM { return RANDOM; } @@ -165,14 +168,15 @@ JENKINS { return JENKINS; } [[:alnum:]][[:alnum:].]*[[:alpha:]]: { yylval->string.c_str = yytext; yylval->string.length = yyleng; - return SERVER_WITH_PORT; + return HOSTNAME_WITH_PORT; } -[[:alnum:]][[:alnum:].]*[[:alpha:]] { +[[:alnum:]]+"."[[:alpha:].]+ { yylval->string.c_str = yytext; yylval->string.length = yyleng; - return IDENTIFIER; + return HOSTNAME; } + [[:digit:]]{1,3}"."[[:digit:]]{1,3}"."[[:digit:]]{1,3}"."[[:digit:]]{1,3}: { yylval->string.c_str = yytext; yylval->string.length = yyleng; @@ -185,6 +189,18 @@ JENKINS { return JENKINS; } return IPADDRESS; } +[[:alnum:]]+ { + yylval->string.c_str = yytext; + yylval->string.length = yyleng; + return STRING; + } + +\"[[:alnum:]]*\" { + yylval->string.c_str = yytext; + yylval->string.length = yyleng; + return QUOTED_STRING; + } + . { return UNKNOWN; } diff --git a/libmemcached/string.h b/libmemcached/string.h index 4b44e6ed..f6a13bb0 100644 --- a/libmemcached/string.h +++ b/libmemcached/string.h @@ -34,6 +34,11 @@ struct memcached_string_st { } options; }; +struct memcached_string_t { + size_t size; + const char *c_str; +}; + #ifdef __cplusplus extern "C" { #endif @@ -80,4 +85,10 @@ void memcached_string_set_length(memcached_string_st *self, size_t length); #endif +#ifdef __cplusplus +#define memcached_string_with_size(X) (X), (static_cast((sizeof(X) - 1))) +#else +#define memcached_string_with_size(X) (X), ((size_t)((sizeof(X) - 1))) +#endif + #endif /* __LIBMEMCACHED_STRING_H__ */ diff --git a/libmemcached/types.h b/libmemcached/types.h index 28a1535c..89c1203b 100644 --- a/libmemcached/types.h +++ b/libmemcached/types.h @@ -16,6 +16,8 @@ typedef struct memcached_st memcached_st; typedef struct memcached_stat_st memcached_stat_st; typedef struct memcached_analysis_st memcached_analysis_st; typedef struct memcached_result_st memcached_result_st; +typedef struct memcached_array_st memcached_array_st; +typedef struct memcached_error_st memcached_error_st; // All of the flavors of memcache_server_st typedef struct memcached_server_st memcached_server_st; @@ -26,6 +28,7 @@ typedef struct memcached_callback_st memcached_callback_st; // The following two structures are internal, and never exposed to users. typedef struct memcached_string_st memcached_string_st; +typedef struct memcached_string_t memcached_string_t; typedef struct memcached_continuum_item_st memcached_continuum_item_st; diff --git a/libtest/server.c b/libtest/server.c index 4349a668..c96ffb51 100644 --- a/libtest/server.c +++ b/libtest/server.c @@ -47,7 +47,7 @@ static void global_sleep(void) static void kill_file(const char *file_buffer) { - FILE *fp= fopen(file_buffer, "r"); + FILE *fp; while ((fp= fopen(file_buffer, "r"))) { diff --git a/tests/basic.cc b/tests/basic.cc new file mode 100644 index 00000000..fea343d5 --- /dev/null +++ b/tests/basic.cc @@ -0,0 +1,130 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 +#include +#include +#include "tests/basic.h" + +test_return_t basic_init_test(memcached_st *junk) +{ + (void)junk; + + memcached_st memc; + memcached_st *memc_ptr; + + memc_ptr= memcached_create(&memc); + test_true(memc_ptr); + test_false(memcached_is_allocated(&memc)); + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +test_return_t basic_clone_test(memcached_st *memc) +{ + memcached_st *memc_ptr; + + memc_ptr= memcached_clone(NULL, memc); + test_true(memc_ptr); + test_true(memcached_is_allocated(memc_ptr)); + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +test_return_t basic_reset_stack_test(memcached_st *junk) +{ + (void)junk; + memcached_st memc; + + memcached_create(&memc); + + memcached_reset(&memc); + test_false(memcached_is_allocated(&memc)); + + memcached_free(&memc); + test_false(memcached_is_allocated(&memc)); + + return TEST_SUCCESS; +} + +test_return_t basic_reset_heap_test(memcached_st *junk) +{ + (void)junk; + memcached_st *memc_ptr; + + memc_ptr= memcached_create(NULL); + test_true(memcached_is_allocated(memc_ptr)); + + memcached_reset(memc_ptr); + test_true(memcached_is_allocated(memc_ptr)); + + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +test_return_t basic_reset_stack_clone_test(memcached_st *memc) +{ + memcached_st clone; + memcached_st *memc_ptr; + + memset(&clone, 0, sizeof(clone)); + memc_ptr= memcached_clone(&clone, memc); + test_true(memc_ptr); + + memcached_reset(memc_ptr); + + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +test_return_t basic_reset_heap_clone_test(memcached_st *memc) +{ + memcached_st *memc_ptr; + + memc_ptr= memcached_clone(NULL, memc); + test_true(memc_ptr); + + memcached_reset(memc_ptr); + + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} diff --git a/tests/basic.h b/tests/basic.h new file mode 100644 index 00000000..7c1536ef --- /dev/null +++ b/tests/basic.h @@ -0,0 +1,66 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +LIBTEST_INTERNAL_API +test_return_t basic_init_test(memcached_st *junk); + +LIBTEST_INTERNAL_API +test_return_t basic_clone_test(memcached_st *memc); + +LIBTEST_INTERNAL_API +test_return_t basic_reset_stack_test(memcached_st *junk); + +LIBTEST_INTERNAL_API +test_return_t basic_reset_heap_test(memcached_st *junk); + +LIBTEST_INTERNAL_API +test_return_t basic_reset_stack_clone_test(memcached_st *memc); + +LIBTEST_INTERNAL_API +test_return_t basic_reset_heap_clone_test(memcached_st *memc); + +#ifdef __cplusplus +} +#endif diff --git a/tests/error_conditions.cc b/tests/error_conditions.cc new file mode 100644 index 00000000..b46b3ca2 --- /dev/null +++ b/tests/error_conditions.cc @@ -0,0 +1,70 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *junk) +{ + (void)junk; + memcached_st *memc_ptr; + + memc_ptr= memcached_create(NULL); + test_true(memc_ptr); + + memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL); + test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS); + + memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL); + test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS); + + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +#ifdef __cplusplus +} +#endif diff --git a/tests/error_conditions.h b/tests/error_conditions.h new file mode 100644 index 00000000..1bfa9ed2 --- /dev/null +++ b/tests/error_conditions.h @@ -0,0 +1,50 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * 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 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *junk); + +#ifdef __cplusplus +} +#endif diff --git a/tests/include.am b/tests/include.am index 6ed1cd9f..dcc19a91 100644 --- a/tests/include.am +++ b/tests/include.am @@ -28,6 +28,8 @@ EXTRA_DIST+= \ tests/output_plus.res noinst_HEADERS+= \ + tests/basic.h \ + tests/error_conditions.h \ tests/hash_results.h \ tests/ketama_test_cases.h \ tests/ketama_test_cases_spy.h \ @@ -47,6 +49,8 @@ noinst_PROGRAMS+= \ tests_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING) tests_testapp_SOURCES= \ + tests/basic.cc \ + tests/error_conditions.cc \ tests/mem_functions.c \ tests/parser.cc \ tests/print.cc \ diff --git a/tests/mem_functions.c b/tests/mem_functions.c index 2cb8cfb9..3aff82fd 100644 --- a/tests/mem_functions.c +++ b/tests/mem_functions.c @@ -36,6 +36,8 @@ #include #include "tests/parser.h" #include "tests/replication.h" +#include "tests/basic.h" +#include "tests/error_conditions.h" #include "tests/print.h" @@ -6101,6 +6103,16 @@ test_st behavior_tests[] ={ {0, 0, 0} }; +test_st basic_tests[] ={ + {"init", 1, (test_callback_fn)basic_init_test}, + {"clone", 1, (test_callback_fn)basic_clone_test}, + {"reset", 1, (test_callback_fn)basic_reset_stack_test}, + {"reset heap", 1, (test_callback_fn)basic_reset_heap_test}, + {"reset stack clone", 1, (test_callback_fn)basic_reset_stack_clone_test}, + {"reset heap clone", 1, (test_callback_fn)basic_reset_heap_clone_test}, + {0, 0, 0} +}; + test_st regression_binary_vs_block[] ={ {"block add", 1, (test_callback_fn)block_add_regression}, {"binary add", 1, (test_callback_fn)binary_add_regression}, @@ -6289,10 +6301,12 @@ test_st hash_tests[] ={ }; test_st error_conditions[] ={ - {"memcached_get_MEMCACHED_ERRNO", 0, (test_callback_fn)memcached_get_MEMCACHED_ERRNO }, - {"memcached_get_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND }, - {"memcached_get_by_key_MEMCACHED_ERRNO", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_ERRNO }, - {"memcached_get_by_key_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND }, + {"memcached_get(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_MEMCACHED_ERRNO }, + {"memcached_get(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND }, + {"memcached_get_by_key(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_ERRNO }, + {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND }, + {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND }, + {"memcached_increment(MEMCACHED_NO_SERVERS)", 0, (test_callback_fn)memcached_increment_MEMCACHED_NO_SERVERS }, {0, 0, (test_callback_fn)0} }; @@ -6305,6 +6319,7 @@ test_st parser_tests[] ={ {"number_options", 0, (test_callback_fn)parser_number_options_test }, {"server", 0, (test_callback_fn)server_test }, {"servers", 0, (test_callback_fn)servers_test }, + {"prefix_key", 0, (test_callback_fn)parser_key_prefix_test }, {0, 0, (test_callback_fn)0} }; @@ -6312,6 +6327,7 @@ collection_st collection[] ={ #if 0 {"hash_sanity", 0, 0, hash_sanity}, #endif + {"basic", 0, 0, basic_tests}, {"hsieh_availability", 0, 0, hsieh_availability}, {"murmur_availability", 0, 0, murmur_availability}, {"block", 0, 0, tests}, diff --git a/tests/parser.cc b/tests/parser.cc index 3ee37a2c..9eb81714 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -42,166 +42,273 @@ #include "tests/parser.h" #include "tests/print.h" +enum scanner_type_t +{ + NIL, + UNSIGNED, + SIGNED, + ARRAY +}; + + struct scanner_string_st { - const char *c_ptr; + const char *c_str; size_t size; }; -test_return_t server_test(memcached_st *junk) +static inline scanner_string_st scanner_string(const char *arg, size_t arg_size) { - (void)junk; - memcached_return_t rc; - memcached_st *memc; - memc= memcached_create(NULL); + scanner_string_st local= { arg, arg_size }; + return local; +} - scanner_string_st test_strings[]= { - { STRING_WITH_LEN("--server=localhost") }, - { STRING_WITH_LEN("--server=10.0.2.1") }, - { STRING_WITH_LEN("--server=example.com") }, - { STRING_WITH_LEN("--server=localhost:30") }, - { STRING_WITH_LEN("--server=10.0.2.1:20") }, - { STRING_WITH_LEN("--server=example.com:1024") }, - { NULL, 0} - }; - - for (scanner_string_st *ptr= test_strings; ptr->size; ptr++) - { - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - test_true(rc == MEMCACHED_SUCCESS); - memcached_servers_reset(memc); - } +#define make_scanner_string(X) scanner_string((X), static_cast(sizeof(X) - 1)) - memcached_free(memc); +static struct scanner_string_st scanner_string_null= { 0, 0}; + +struct scanner_variable_t { + enum scanner_type_t type; + struct scanner_string_st option; + struct scanner_string_st result; + test_return_t (*check_func)(memcached_st *memc, const scanner_string_st &hostname); +}; + +// Check and make sure the first host is what we expect it to be +static test_return_t __check_host(memcached_st *memc, const scanner_string_st &hostname) +{ + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, 0); + + test_true(instance); + + const char *first_hostname = memcached_server_name(instance); + test_true(first_hostname); + test_strcmp(first_hostname, hostname.c_str); return TEST_SUCCESS; } -test_return_t servers_test(memcached_st *junk) +// Check and make sure the prefix_key is what we expect it to be +static test_return_t __check_prefix_key(memcached_st *memc, const scanner_string_st &hostname) { - (void)junk; - memcached_st *memc; - memc= memcached_create(NULL); + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, 0); - scanner_string_st test_strings[]= { - { STRING_WITH_LEN("--servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225") }, - { STRING_WITH_LEN("--servers=a.example.com:81,localhost:82,b.example.com") }, - { STRING_WITH_LEN("--servers=localhost,localhost:80") }, - { NULL, 0} - }; + test_true(instance); - for (scanner_string_st *ptr= test_strings; ptr->size; ptr++) - { - memcached_return_t rc; - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - - test_true(rc == MEMCACHED_SUCCESS); + const char *first_hostname = memcached_server_name(instance); + test_true(first_hostname); + test_strcmp(first_hostname, hostname.c_str); - memcached_server_fn callbacks[1]; - callbacks[0]= server_print_callback; - memcached_server_cursor(memc, callbacks, NULL, 1); + return TEST_SUCCESS; +} - memcached_servers_reset(memc); - } +static test_return_t __check_IO_MSG_WATERMARK(memcached_st *memc, const scanner_string_st &value) +{ + uint64_t value_number; - scanner_string_st bad_test_strings[]= { - { STRING_WITH_LEN("-servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225") }, - { STRING_WITH_LEN("-- servers=a.example.com:81,localhost:82,b.example.com") }, - { STRING_WITH_LEN("--servers=localhost80") }, - { NULL, 0} - }; + value_number= atoll(value.c_str); - for (scanner_string_st *ptr= bad_test_strings; ptr->size; ptr++) - { - memcached_return_t rc; - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK) == value_number); + return TEST_SUCCESS; +} - test_false_with(rc == MEMCACHED_SUCCESS, ptr->c_ptr); +static test_return_t __check_AUTO_EJECT_HOSTS(memcached_st *memc, const scanner_string_st &value) +{ + (void)value; + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS)); + return TEST_SUCCESS; +} - memcached_server_fn callbacks[1]; - callbacks[0]= server_print_callback; - memcached_server_cursor(memc, callbacks, NULL, 1); +static test_return_t __check_CACHE_LOOKUPS(memcached_st *memc, const scanner_string_st &value) +{ + (void)value; + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS)); + return TEST_SUCCESS; +} - memcached_servers_reset(memc); - } +static test_return_t __check_NOREPLY(memcached_st *memc, const scanner_string_st &value) +{ + (void)value; + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NOREPLY)); + return TEST_SUCCESS; +} - memcached_free(memc); +static test_return_t __check_VERIFY_KEY(memcached_st *memc, const scanner_string_st &value) +{ + (void)value; + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)); + return TEST_SUCCESS; +} +static test_return_t __check_distribution_RANDOM(memcached_st *memc, const scanner_string_st &value) +{ + (void)value; + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION) == MEMCACHED_DISTRIBUTION_RANDOM); return TEST_SUCCESS; } -scanner_string_st test_number_options[]= { - { STRING_WITH_LEN("--CONNECT_TIMEOUT=456") }, - { STRING_WITH_LEN("--IO_MSG_WATERMARK=456") }, - { STRING_WITH_LEN("--IO_BYTES_WATERMARK=456") }, - { STRING_WITH_LEN("--IO_KEY_PREFETCH=456") }, - { STRING_WITH_LEN("--NUMBER_OF_REPLICAS=456") }, - { STRING_WITH_LEN("--POLL_TIMEOUT=456") }, - { STRING_WITH_LEN("--RCV_TIMEOUT=456") }, - { STRING_WITH_LEN("--RETRY_TIMEOUT=456") }, - { STRING_WITH_LEN("--SERVER_FAILURE_LIMIT=456") }, - { STRING_WITH_LEN("--SND_TIMEOUT=456") }, - { STRING_WITH_LEN("--SOCKET_RECV_SIZE=456") }, - { STRING_WITH_LEN("--SOCKET_SEND_SIZE=456") }, - { NULL, 0} +scanner_variable_t test_server_strings[]= { + { ARRAY, make_scanner_string("--server=localhost"), make_scanner_string("localhost"), __check_host }, + { ARRAY, make_scanner_string("--server=10.0.2.1"), make_scanner_string("10.0.2.1"), __check_host }, + { ARRAY, make_scanner_string("--server=example.com"), make_scanner_string("example.com"), __check_host }, + { ARRAY, make_scanner_string("--server=localhost:30"), make_scanner_string("localhost"), __check_host }, + { ARRAY, make_scanner_string("--server=10.0.2.1:20"), make_scanner_string("10.0.2.1"), __check_host }, + { ARRAY, make_scanner_string("--server=example.com:1024"), make_scanner_string("example.com"), __check_host }, + { NIL, scanner_string_null, scanner_string_null, NULL } }; -scanner_string_st test_boolean_options[]= { - { STRING_WITH_LEN("--AUTO_EJECT_HOSTS") }, - { STRING_WITH_LEN("--BINARY_PROTOCOL") }, - { STRING_WITH_LEN("--BUFFER_REQUESTS") }, - { STRING_WITH_LEN("--CACHE_LOOKUPS") }, - { STRING_WITH_LEN("--CORK") }, - { STRING_WITH_LEN("--HASH_WITH_PREFIX_KEY") }, - { STRING_WITH_LEN("--KETAMA") }, - { STRING_WITH_LEN("--KETAMA_WEIGHTED") }, - { STRING_WITH_LEN("--NOREPLY") }, - { STRING_WITH_LEN("--RANDOMIZE_REPLICA_READ") }, - { STRING_WITH_LEN("--SORT_HOSTS") }, - { STRING_WITH_LEN("--SUPPORT_CAS") }, - { STRING_WITH_LEN("--TCP_NODELAY") }, - { STRING_WITH_LEN("--TCP_KEEPALIVE") }, - { STRING_WITH_LEN("--TCP_KEEPIDLE") }, - { STRING_WITH_LEN("--USE_UDP") }, - { STRING_WITH_LEN("--VERIFY_KEY") }, - { NULL, 0} +scanner_variable_t test_servers_strings[]= { + { ARRAY, make_scanner_string("--servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--servers=localhost,localhost:80"), scanner_string_null, NULL }, + { NIL, scanner_string_null, scanner_string_null, NULL} }; -test_return_t parser_number_options_test(memcached_st *junk) + +scanner_variable_t bad_test_strings[]= { + { ARRAY, make_scanner_string("-servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("-- servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--servers=localhost+80"), scanner_string_null, NULL}, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + +scanner_variable_t test_number_options[]= { + { ARRAY, make_scanner_string("--CONNECT_TIMEOUT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--IO_MSG_WATERMARK=456"), make_scanner_string("456"), __check_IO_MSG_WATERMARK }, + { ARRAY, make_scanner_string("--IO_BYTES_WATERMARK=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--IO_KEY_PREFETCH=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--NUMBER_OF_REPLICAS=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--POLL_TIMEOUT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--RCV_TIMEOUT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--RETRY_TIMEOUT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SERVER_FAILURE_LIMIT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SND_TIMEOUT=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SOCKET_RECV_SIZE=456"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SOCKET_SEND_SIZE=456"), scanner_string_null, NULL }, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + +scanner_variable_t test_boolean_options[]= { + { ARRAY, make_scanner_string("--AUTO_EJECT_HOSTS"), scanner_string_null, __check_AUTO_EJECT_HOSTS }, + { ARRAY, make_scanner_string("--BINARY_PROTOCOL"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--BUFFER_REQUESTS"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--CACHE_LOOKUPS"), scanner_string_null, __check_CACHE_LOOKUPS }, + { ARRAY, make_scanner_string("--CORK"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH_WITH_PREFIX_KEY"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--KETAMA"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--KETAMA_WEIGHTED"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--NOREPLY"), scanner_string_null, __check_NOREPLY }, + { ARRAY, make_scanner_string("--RANDOMIZE_REPLICA_READ"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SORT_HOSTS"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--SUPPORT_CAS"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--TCP_NODELAY"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--TCP_KEEPALIVE"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--TCP_KEEPIDLE"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--USE_UDP"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--VERIFY_KEY"), scanner_string_null, __check_VERIFY_KEY }, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + +scanner_variable_t prefix_key_strings[]= { + { ARRAY, make_scanner_string("--PREFIX_KEY=foo"), make_scanner_string("foo"), __check_prefix_key }, + { ARRAY, make_scanner_string("--PREFIX-KEY=\"foo\""), make_scanner_string("foo"), __check_prefix_key }, + { ARRAY, make_scanner_string("--PREFIX-KEY=\"This is a very long key\""), make_scanner_string("This is a very long key"), __check_prefix_key }, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + +scanner_variable_t distribution_strings[]= { + { ARRAY, make_scanner_string("--DISTRIBUTION=consistent"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--DISTRIBUTION=random"), scanner_string_null, __check_distribution_RANDOM }, + { ARRAY, make_scanner_string("--DISTRIBUTION=modula"), scanner_string_null, NULL }, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + +scanner_variable_t hash_strings[]= { + { ARRAY, make_scanner_string("--HASH=MD5"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=CRC"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=FNV1_64"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=FNV1A_64"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=FNV1_32"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=FNV1A_32"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=MURMUR"), scanner_string_null, NULL }, + { ARRAY, make_scanner_string("--HASH=JENKINS"), scanner_string_null, NULL }, + { NIL, scanner_string_null, scanner_string_null, NULL} +}; + + +static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= true) { - (void)junk; + (void)test_true; memcached_st *memc; memc= memcached_create(NULL); - for (scanner_string_st *ptr= test_number_options; ptr->size; ptr++) + for (scanner_variable_t *ptr= scanner; ptr->type != NIL; ptr++) { memcached_return_t rc; - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr); + rc= memcached_parse_options(memc, ptr->option.c_str, ptr->option.size); + if (test_true) + { + test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc)); + + if (ptr->check_func) + { + (*ptr->check_func)(memc, ptr->result); + } + } + else + { + test_false_with(rc == MEMCACHED_SUCCESS, ptr->option.c_str); + } + memcached_reset(memc); } - memcached_free(memc); return TEST_SUCCESS; } -test_return_t parser_boolean_options_test(memcached_st *junk) +test_return_t server_test(memcached_st *junk) +{ + (void)junk; + return _test_option(test_server_strings); +} + +test_return_t servers_test(memcached_st *junk) { (void)junk; - memcached_st *memc; - memc= memcached_create(NULL); - for (scanner_string_st *ptr= test_boolean_options; ptr->size; ptr++) + test_return_t rc; + if ((rc= _test_option(test_server_strings)) != TEST_SUCCESS) { - memcached_return_t rc; - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr); + return rc; } - memcached_free(memc); +#if 0 + memcached_server_fn callbacks[1]; + callbacks[0]= server_print_callback; + memcached_server_cursor(memc, callbacks, NULL, 1); +#endif + + if ((rc= _test_option(bad_test_strings, false)) != TEST_SUCCESS) + { + return rc; + } return TEST_SUCCESS; } +test_return_t parser_number_options_test(memcached_st *junk) +{ + (void)junk; + return _test_option(test_number_options); +} + +test_return_t parser_boolean_options_test(memcached_st *junk) +{ + (void)junk; + return _test_option(test_boolean_options); +} + test_return_t behavior_parser_test(memcached_st *junk) { (void)junk; @@ -211,55 +318,17 @@ test_return_t behavior_parser_test(memcached_st *junk) test_return_t parser_hash_test(memcached_st *junk) { (void)junk; - memcached_return_t rc; - memcached_st *memc; - memc= memcached_create(NULL); - - scanner_string_st test_strings[]= { - { STRING_WITH_LEN("--HASH=MD5") }, - { STRING_WITH_LEN("--HASH=CRC") }, - { STRING_WITH_LEN("--HASH=FNV1_64") }, - { STRING_WITH_LEN("--HASH=FNV1A_64") }, - { STRING_WITH_LEN("--HASH=FNV1_32") }, - { STRING_WITH_LEN("--HASH=FNV1A_32") }, - { STRING_WITH_LEN("--HASH=HSIEH") }, - { STRING_WITH_LEN("--HASH=MURMUR") }, - { STRING_WITH_LEN("--HASH=JENKINS") }, - { NULL, 0} - }; - - for (scanner_string_st *ptr= test_strings; ptr->size; ptr++) - { - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr); - } - - memcached_free(memc); - - return TEST_SUCCESS; + return _test_option(hash_strings); } test_return_t parser_distribution_test(memcached_st *junk) { (void)junk; - memcached_return_t rc; - memcached_st *memc; - memc= memcached_create(NULL); - - scanner_string_st test_strings[]= { - { STRING_WITH_LEN("--DISTRIBUTION=consistent") }, - { STRING_WITH_LEN("--DISTRIBUTION=random") }, - { STRING_WITH_LEN("--DISTRIBUTION=modula") }, - { NULL, 0} - }; - - for (scanner_string_st *ptr= test_strings; ptr->size; ptr++) - { - rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size); - test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr); - } - - memcached_free(memc); + return _test_option(distribution_strings); +} - return TEST_SUCCESS; +test_return_t parser_key_prefix_test(memcached_st *junk) +{ + (void)junk; + return _test_option(distribution_strings); } diff --git a/tests/parser.h b/tests/parser.h index 78518d20..5c5ad7f2 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -64,6 +64,9 @@ test_return_t parser_hash_test(memcached_st *junk); LIBTEST_INTERNAL_API test_return_t parser_boolean_options_test(memcached_st *junk); +LIBTEST_INTERNAL_API +test_return_t parser_key_prefix_test(memcached_st *junk); + #ifdef __cplusplus } #endif -- 2.30.2