From: Brian Aker Date: Mon, 5 Mar 2012 00:44:37 +0000 (-0800) Subject: Add in better testing for gdb. X-Git-Tag: 1.0.5~12 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=93dec285cdb4aab2bff0bae0d50e033b69560181;p=awesomized%2Flibmemcached Add in better testing for gdb. --- diff --git a/.bzrignore b/.bzrignore index d3ff77af..a3cc73e5 100644 --- a/.bzrignore +++ b/.bzrignore @@ -144,3 +144,4 @@ tmp_chroot unittests/unittests tests/libmemcached-1.0/testsocket example/t/memcached_light +libtest/abort diff --git a/example/interface_v0.cc b/example/interface_v0.cc index cc2f17d2..e4f5c901 100644 --- a/example/interface_v0.cc +++ b/example/interface_v0.cc @@ -20,6 +20,12 @@ #include #include "example/memcached_light.h" #include "example/storage.h" +#include "util/log.hpp" + + +using namespace datadifferential; + +static util::log_info_st *log_file= NULL; static protocol_binary_response_status noop_command_handler(const void *cookie, protocol_binary_request_header *header, @@ -121,18 +127,22 @@ static protocol_binary_response_status delete_command_handler(const void *cookie response.message.header.response.opcode= header->request.opcode; response.message.header.response.opaque= header->request.opaque; - if (!delete_item(key, keylen)) + if (delete_item(key, keylen) == false) { + log_file->write(util::VERBOSE_NOTICE, "%s not found: %.*s", __func__, keylen, key); response.message.header.response.status= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT); return response_handler(cookie, header, (protocol_binary_response_header*)&response); } else if (header->request.opcode == PROTOCOL_BINARY_CMD_DELETE) { + log_file->write(util::VERBOSE_NOTICE, "%s not found: %.*s", __func__, keylen, key); /* DELETEQ doesn't want success response */ response.message.header.response.status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS); return response_handler(cookie, header, (protocol_binary_response_header*)&response); } + log_file->write(util::VERBOSE_NOTICE, "%s deleted: %.*s", __func__, keylen, key); + return PROTOCOL_BINARY_RESPONSE_SUCCESS; } @@ -516,8 +526,10 @@ static protocol_binary_response_status stat_command_handler(const void *cookie, memcached_binary_protocol_callback_st interface_v0_impl; -void initialize_interface_v0_handler(void) +void initialize_interface_v0_handler(util::log_info_st& arg) { + log_file= &arg; + interface_v0_impl.interface_version= MEMCACHED_PROTOCOL_HANDLER_V0; interface_v0_impl.interface.v0.comcode[PROTOCOL_BINARY_CMD_GET]= get_command_handler; interface_v0_impl.interface.v0.comcode[PROTOCOL_BINARY_CMD_SET]= set_command_handler; diff --git a/example/interface_v1.cc b/example/interface_v1.cc index a4364918..08d09388 100644 --- a/example/interface_v1.cc +++ b/example/interface_v1.cc @@ -9,19 +9,23 @@ * command is being sent. */ #include "config.h" -#include + +#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include #include #include #include "example/memcached_light.h" #include "example/storage.h" +#include "util/log.hpp" + +static datadifferential::util::log_info_st *log_file= NULL; static protocol_binary_response_status add_handler(const void *cookie, const void *key, @@ -390,8 +394,9 @@ static protocol_binary_response_status version_handler(const void *cookie, memcached_binary_protocol_callback_st interface_v1_impl; -void initialize_interface_v1_handler(void) +void initialize_interface_v1_handler(datadifferential::util::log_info_st& arg) { + log_file= &arg; memset(&interface_v1_impl, 0, sizeof(memcached_binary_protocol_callback_st)); interface_v1_impl.interface_version= MEMCACHED_PROTOCOL_HANDLER_V1; diff --git a/example/memcached_light.cc b/example/memcached_light.cc index 61c5314d..e7f952ea 100644 --- a/example/memcached_light.cc +++ b/example/memcached_light.cc @@ -433,13 +433,6 @@ int main(int argc, char **argv) { memcached_binary_protocol_callback_st *interface= &interface_v0_impl; - /* - * We need to initialize the handlers manually due to a bug in the - * warnings generated by struct initialization in gcc (all the way up to 4.4) - */ - initialize_interface_v0_handler(); - initialize_interface_v1_handler(); - { enum long_option_t { OPT_HELP, @@ -554,6 +547,14 @@ int main(int argc, char **argv) util::log_info_st log_file(argv[0], global_options.log_file, false); log_file.write(util::VERBOSE_NOTICE, "starting log"); + /* + * We need to initialize the handlers manually due to a bug in the + * warnings generated by struct initialization in gcc (all the way up to 4.4) + */ + initialize_interface_v0_handler(log_file); + initialize_interface_v1_handler(log_file); + + if (server_socket(log_file, global_options.service) == false) { return EXIT_FAILURE; diff --git a/example/memcached_light.h b/example/memcached_light.h index 12c4ea79..6abb8744 100644 --- a/example/memcached_light.h +++ b/example/memcached_light.h @@ -1,5 +1,44 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Memcached Light interface definitions + * + * Copyright (C) 2012 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. + * + */ + /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */ #pragma once -extern void initialize_interface_v0_handler(void); -extern void initialize_interface_v1_handler(void); +#include "util/log.hpp" + +void initialize_interface_v0_handler(datadifferential::util::log_info_st&); +void initialize_interface_v1_handler(datadifferential::util::log_info_st&); diff --git a/example/t/include.am b/example/t/include.am index 3cb5b809..b9b7556d 100644 --- a/example/t/include.am +++ b/example/t/include.am @@ -12,12 +12,25 @@ MEMCACHED_LIGHT_TESTS_LDADDS= \ libmemcached/libmemcached.la \ libmemcached/libmemcachedutil.la \ libtest/libtest.la -example_t_memcached_light_SOURCES= example/t/memcached_light.cc + +example_t_memcached_light_SOURCES= +example_t_memcached_light_LDADD= + +example_t_memcached_light_SOURCES+= example/t/memcached_light.cc +example_t_memcached_light_SOURCES+= tests/libmemcached-1.0/memcached_get.cc +example_t_memcached_light_SOURCES+= tests/libmemcached-1.0/setup_and_teardowns.cc example_t_memcached_light_CXXFLAGS = $(AM_CXXFLAGS) example_t_memcached_light_DEPENDENCIES= $(MEMCACHED_LIGHT_TESTS_LDADDS) example/memcached_light -example_t_memcached_light_LDADD= $(MEMCACHED_LIGHT_TESTS_LDADDS) +example_t_memcached_light_LDADD+= $(MEMCACHED_LIGHT_TESTS_LDADDS) +example_t_memcached_light_LDADD+= $(LIBUUID_LDFLAGS) check_PROGRAMS+= example/t/memcached_light noinst_PROGRAMS+= example/t/memcached_light -test-memcached_light: example/t/memcached_light +test-memcached_light: example/t/memcached_light example/memcached_light @example/t/memcached_light + +gdb-memcached_light: example/t/memcached_light example/memcached_light + @$(DEBUG_COMMAND) example/t/memcached_light + +valgrind-memcached_light: example/t/memcached_light example/memcached_light + $(VALGRIND_COMMAND) example/t/memcached_light diff --git a/example/t/memcached_light.cc b/example/t/memcached_light.cc index 44f2770c..bcfce0a5 100644 --- a/example/t/memcached_light.cc +++ b/example/t/memcached_light.cc @@ -44,6 +44,8 @@ #include #include +#include "tests/libmemcached-1.0/memcached_get.h" + using namespace libtest; #ifndef __INTEL_COMPILER @@ -133,6 +135,39 @@ static test_return_t max_connections_file_TEST(void *) return TEST_SUCCESS; } +typedef test_return_t (*libmemcached_test_callback_fn)(memcached_st *); + +static test_return_t _runner_default(libmemcached_test_callback_fn func, void *object) +{ + if (func) + { + test_true(object); + test_return_t ret; + try { + ret= func((memcached_st*)object); + } + catch (std::exception& e) + { + libtest::Error << e.what(); + return TEST_FAILURE; + } + + return ret; + } + + return TEST_SUCCESS; +} + +class MemcachedLightRunner : public libtest::Runner { +public: + test_return_t run(test_callback_fn* func, void *object) + { + return _runner_default(libmemcached_test_callback_fn(func), object); + } +}; + +static MemcachedLightRunner defualt_libmemcached_runner; + test_st cmdline_option_TESTS[] ={ {"--help", true, help_TEST }, {"--verbose", true, verbose_TEST }, @@ -146,8 +181,21 @@ test_st cmdline_option_TESTS[] ={ {0, 0, 0} }; +/* Clean the server before beginning testing */ +test_st basic_TESTS[] ={ +#if 0 + {"memcached_get()", true, (test_callback_fn*)get_test }, + {"memcached_get() test 2", false, (test_callback_fn*)get_test2 }, + {"memcached_get() test 3", false, (test_callback_fn*)get_test3 }, + {"memcached_get() test 4", false, (test_callback_fn*)get_test4 }, + {"memcached_get() test 5", false, (test_callback_fn*)get_test5 }, +#endif + {0, 0, 0} +}; + collection_st collection[] ={ {"command line options", 0, 0, cmdline_option_TESTS }, + {"basic", 0, 0, basic_TESTS }, {0, 0, 0, 0} }; @@ -164,13 +212,32 @@ static void *world_create(server_startup_st& servers, test_return_t& error) error= TEST_FAILURE; } - return &servers; + + char buffer[1024]; + int length= snprintf(buffer, sizeof(buffer), "--server=localhost:%d", int(libtest::default_port())); + fatal_assert(length > 0); + + memcached_st *memc= memcached(buffer, length); + + fatal_assert(memc); + + return (void*)memc; +} + +static bool world_destroy(void *object) +{ + memcached_st *memc= (memcached_st*)object; + memcached_free(memc); + + return TEST_SUCCESS; } void get_world(Framework *world) { - world->collections= collection; world->_create= world_create; + world->_destroy= world_destroy; + world->collections= collection; + world->set_runner(&defualt_libmemcached_runner); } diff --git a/libtest/abort.cc b/libtest/abort.cc new file mode 100644 index 00000000..05dfa26f --- /dev/null +++ b/libtest/abort.cc @@ -0,0 +1,11 @@ +#include + +int main(void) +{ + if (1) + { + abort(); + } + + return 0; +} diff --git a/libtest/cmdline.cc b/libtest/cmdline.cc index 6807c338..22f0399d 100644 --- a/libtest/cmdline.cc +++ b/libtest/cmdline.cc @@ -26,6 +26,7 @@ using namespace libtest; #include #include #include +#include #include #include #include @@ -56,7 +57,7 @@ extern "C" { namespace { - std::string print_argv(char * * & built_argv, const size_t& argc, const pid_t& pid) + std::string print_argv(char * * & built_argv, const size_t& argc) { std::stringstream arg_buffer; @@ -68,6 +69,18 @@ namespace { return arg_buffer.str(); } + std::string print_argv(char** argv) + { + std::stringstream arg_buffer; + + for (char** ptr= argv; *ptr; ptr++) + { + arg_buffer << *ptr << " "; + } + + return arg_buffer.str(); + } + static Application::error_t int_to_error_t(int arg) { switch (arg) @@ -89,6 +102,8 @@ namespace libtest { Application::Application(const std::string& arg, const bool _use_libtool_arg) : _use_libtool(_use_libtool_arg), + _use_valgrind(false), + _use_gdb(false), _argc(0), _exectuble(arg), built_argv(NULL), @@ -102,6 +117,19 @@ Application::Application(const std::string& arg, const bool _use_libtool_arg) : } } + // Find just the name of the application with no path + { + size_t found= arg.find_last_of("/\\"); + if (found) + { + _exectuble_name= arg.substr(found +1); + } + else + { + _exectuble_name= arg; + } + } + if (_use_libtool and getenv("PWD")) { _exectuble_with_path+= getenv("PWD"); @@ -133,13 +161,66 @@ Application::error_t Application::run(const char *args[]) create_argv(args); int spawn_ret; - if (_use_libtool) + if (_use_gdb) { - spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL); + std::string gdb_run_file= create_tmpfile(_exectuble_name); + std::fstream file_stream; + file_stream.open(gdb_run_file.c_str(), std::fstream::out | std::fstream::trunc); + + _gdb_filename= create_tmpfile(_exectuble_name); + file_stream + << "set logging redirect on" << std::endl + << "set logging file " << _gdb_filename << std::endl + << "set logging overwrite on" << std::endl + << "set logging on" << std::endl + << "set environment LIBTEST_IN_GDB=1" << std::endl + << "run " << arguments() << std::endl + << "thread apply all bt" << std::endl + << "quit" << std::endl; + + fatal_assert(file_stream.good()); + file_stream.close(); + + if (_use_libtool) + { + // libtool --mode=execute gdb -f -x binary + char *argv[]= { + const_cast(libtool()), + const_cast("--mode=execute"), + const_cast("gdb"), + const_cast("-batch"), + const_cast("-f"), + const_cast("-x"), + const_cast(gdb_run_file.c_str()), + const_cast(_exectuble_with_path.c_str()), + 0}; + + spawn_ret= posix_spawnp(&_pid, libtool(), &file_actions, NULL, argv, NULL); + } + else + { + // gdb binary + char *argv[]= { + const_cast("gdb"), + const_cast("-batch"), + const_cast("-f"), + const_cast("-x"), + const_cast(gdb_run_file.c_str()), + const_cast(_exectuble_with_path.c_str()), + 0}; + spawn_ret= posix_spawnp(&_pid, "gdb", &file_actions, NULL, argv, NULL); + } } else { - spawn_ret= posix_spawnp(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL); + if (_use_libtool) + { + spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL); + } + else + { + spawn_ret= posix_spawnp(&_pid, built_argv[0], &file_actions, NULL, built_argv, NULL); + } } posix_spawn_file_actions_destroy(&file_actions); @@ -237,10 +318,12 @@ Application::error_t Application::wait() } } +#if 0 if (exit_code == Application::INVALID) { - Error << print_argv(built_argv, _argc, _pid); + Error << print_argv(built_argv, _argc); } +#endif return exit_code; } @@ -341,6 +424,18 @@ void Application::create_argv(const char *args[]) _argc+= 2; // +2 for libtool --mode=execute } + /* + valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE + */ + if (_use_valgrind) + { + _argc+= 7; + } + else if (_use_gdb) // gdb + { + _argc+= 1; + } + for (Options::const_iterator iter= _options.begin(); iter != _options.end(); iter++) { _argc++; @@ -368,6 +463,25 @@ void Application::create_argv(const char *args[]) built_argv[x++]= strdup(libtool()); built_argv[x++]= strdup("--mode=execute"); } + + if (_use_valgrind) + { + /* + valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE + */ + built_argv[x++]= strdup("valgrind"); + built_argv[x++]= strdup("--error-exitcode=1"); + built_argv[x++]= strdup("--leak-check=yes"); + built_argv[x++]= strdup("--show-reachable=yes"); + built_argv[x++]= strdup("--track-fds=yes"); + built_argv[x++]= strdup("--malloc-fill=A5"); + built_argv[x++]= strdup("--free-fill=DE"); + } + else if (_use_gdb) + { + built_argv[x++]= strdup("gdb"); + } + built_argv[x++]= strdup(_exectuble_with_path.c_str()); for (Options::const_iterator iter= _options.begin(); iter != _options.end(); iter++) @@ -391,7 +505,21 @@ void Application::create_argv(const char *args[]) std::string Application::print() { - return print_argv(built_argv, _argc, _pid); + return print_argv(built_argv, _argc); +} + +std::string Application::arguments() +{ + std::stringstream arg_buffer; + + for (size_t x= 1 + _use_libtool ? 2 : 0; + x < _argc and built_argv[x]; + x++) + { + arg_buffer << built_argv[x] << " "; + } + + return arg_buffer.str(); } void Application::delete_argv() diff --git a/libtest/cmdline.h b/libtest/cmdline.h index 39ba35a2..f6da62be 100644 --- a/libtest/cmdline.h +++ b/libtest/cmdline.h @@ -95,15 +95,36 @@ public: std::string print(); + void use_valgrind(bool arg= true) + { + _use_valgrind= arg; + } + + void use_gdb(bool arg= true) + { + _use_gdb= arg; + } + + std::string arguments(); + + std::string gdb_filename() + { + return _gdb_filename; + } + private: void create_argv(const char *args[]); void delete_argv(); private: const bool _use_libtool; + bool _use_valgrind; + bool _use_gdb; size_t _argc; + std::string _exectuble_name; std::string _exectuble; std::string _exectuble_with_path; + std::string _gdb_filename; Options _options; Pipe stdin_fd; Pipe stdout_fd; diff --git a/libtest/include.am b/libtest/include.am index 76392eca..92dc7d27 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -79,8 +79,8 @@ noinst_HEADERS+= \ libtest/killpid.h \ libtest/libtool.hpp \ libtest/memcached.h \ - libtest/runner.h \ libtest/port.h \ + libtest/runner.h \ libtest/server.h \ libtest/server_container.h \ libtest/signal.h \ @@ -91,6 +91,7 @@ noinst_HEADERS+= \ libtest/string.hpp \ libtest/test.h \ libtest/test.hpp \ + libtest/tmpfile.hpp \ libtest/vchar.hpp \ libtest/visibility.h \ libtest/wait.h @@ -117,6 +118,7 @@ libtest_libtest_la_SOURCES= \ libtest/socket.cc \ libtest/strerror.cc \ libtest/test.cc \ + libtest/tmpfile.cc \ libtest/vchar.cc libtest_libtest_la_CXXFLAGS= @@ -199,7 +201,7 @@ tmp_chroot/var/run: tmp_chroot/var @$(mkdir_p) tmp_chroot/var/run -libtest_unittest_DEPENDENCIES+= libtest/libtest.la libtest_tmp_dir +libtest_unittest_DEPENDENCIES+= libtest/libtest.la libtest_tmp_dir libtest/abort libtest/wait libtest_unittest_LDADD+= libtest/libtest.la libtest_unittest_SOURCES= libtest/unittest.cc check_PROGRAMS+= libtest/unittest @@ -226,3 +228,6 @@ noinst_PROGRAMS+= libtest/skiptest libtest_wait_SOURCES= libtest/wait.cc noinst_PROGRAMS+= libtest/wait + +libtest_abort_SOURCES= libtest/abort.cc +noinst_PROGRAMS+= libtest/abort diff --git a/libtest/memcached.cc b/libtest/memcached.cc index 6f81dd6c..c5358bf5 100644 --- a/libtest/memcached.cc +++ b/libtest/memcached.cc @@ -123,7 +123,7 @@ public: // Memcached is slow to start, so we need to do this if (not pid_file().empty()) { - if (not wait_for_pidfile()) + if (wait_for_pidfile() == false) { Error << "Pidfile was not found:" << pid_file(); return -1; @@ -320,6 +320,22 @@ public: return true; } + void log_file_option(Application& app, const std::string& arg) + { + if (arg.empty() == false) + { + std::string buffer("--log-file="); + buffer+= arg; + app.add_option("--verbose"); + app.add_option(buffer); + } + } + + bool has_log_file_option() const + { + return true; + } + bool build(size_t argc, const char *argv[]); }; diff --git a/libtest/run.gdb b/libtest/run.gdb index 320407a2..86b5fe07 100644 --- a/libtest/run.gdb +++ b/libtest/run.gdb @@ -1,2 +1,6 @@ +set logging on +set logging overwrite on set environment LIBTEST_IN_GDB=1 run +thread apply all bt +quit diff --git a/libtest/server.cc b/libtest/server.cc index 8ca6b53e..e554039a 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -138,6 +138,19 @@ bool Server::start() } Application app(executable(), is_libtool()); + + if (is_debug()) + { + app.use_gdb(); + } + else if (getenv("TESTS_ENVIRONMENT")) + { + if (strstr(getenv("TESTS_ENVIRONMENT"), "gdb")) + { + app.use_gdb(); + } + } + if (args(app) == false) { Error << "Could not build command()"; @@ -293,8 +306,7 @@ bool Server::set_log_file() int fd; if ((fd= mkstemp(file_buffer)) == -1) { - perror(file_buffer); - return false; + libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", file_buffer, strerror(errno)); } close(fd); @@ -307,13 +319,9 @@ bool Server::args(Application& app) { // Set a log file if it was requested (and we can) - if (getenv("LIBTEST_LOG") and has_log_file_option()) + if (has_log_file_option()) { - if (not set_log_file()) - { - return false; - } - + set_log_file(); log_file_option(app, _log_file); } diff --git a/libtest/server.h b/libtest/server.h index b193fb8f..df2bbee8 100644 --- a/libtest/server.h +++ b/libtest/server.h @@ -78,7 +78,7 @@ public: } } - bool has_log_file_option() const + virtual bool has_log_file_option() const { return false; } diff --git a/libtest/test.hpp b/libtest/test.hpp index c0d91938..eb1b56c0 100644 --- a/libtest/test.hpp +++ b/libtest/test.hpp @@ -60,3 +60,4 @@ #include #include #include +#include diff --git a/libtest/tmpfile.cc b/libtest/tmpfile.cc new file mode 100644 index 00000000..1bbacda3 --- /dev/null +++ b/libtest/tmpfile.cc @@ -0,0 +1,46 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * libtest + * + * Copyright (C) 2012 Data Differential, http://datadifferential.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include + +namespace libtest { + +std::string create_tmpfile(const std::string& name) +{ + char file_buffer[FILENAME_MAX]; + file_buffer[0]= 0; + + int length= snprintf(file_buffer, sizeof(file_buffer), "var/tmp/%s.XXXXXX", name.c_str()); + fatal_assert(length > 0); + + int fd; + if ((fd= mkstemp(file_buffer)) == -1) + { + libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", file_buffer, strerror(errno)); + } + close(fd); + unlink(file_buffer); + + return file_buffer; +} + +} // namespace libtest diff --git a/libtest/tmpfile.hpp b/libtest/tmpfile.hpp new file mode 100644 index 00000000..5ab50c47 --- /dev/null +++ b/libtest/tmpfile.hpp @@ -0,0 +1,31 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * libtest + * + * Copyright (C) 2012 Data Differential, http://datadifferential.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include + +namespace libtest { + +std::string create_tmpfile(const std::string&); + +} // namespace libtest + diff --git a/libtest/unittest.cc b/libtest/unittest.cc index 33309a7c..bffa4ecb 100644 --- a/libtest/unittest.cc +++ b/libtest/unittest.cc @@ -322,6 +322,29 @@ static test_return_t application_true_BINARY(void *) return TEST_SUCCESS; } +static test_return_t application_gdb_true_BINARY2(void *) +{ + Application true_app("true"); + true_app.use_gdb(); + + test_compare(Application::SUCCESS, true_app.run()); + test_compare(Application::SUCCESS, true_app.wait()); + + return TEST_SUCCESS; +} + +static test_return_t application_gdb_true_BINARY(void *) +{ + Application true_app("true"); + true_app.use_gdb(); + + const char *args[]= { "--fubar", 0 }; + test_compare(Application::SUCCESS, true_app.run(args)); + test_compare(Application::SUCCESS, true_app.wait()); + + return TEST_SUCCESS; +} + static test_return_t application_true_fubar_BINARY(void *) { Application true_app("true"); @@ -334,6 +357,18 @@ static test_return_t application_true_fubar_BINARY(void *) return TEST_SUCCESS; } +static test_return_t application_doesnotexist_BINARY(void *) +{ + Application true_app("doesnotexist"); + + const char *args[]= { "--fubar", 0 }; + test_compare(Application::SUCCESS, true_app.run(args)); + test_compare(Application::INVALID, true_app.wait()); + test_compare(0, true_app.stdout_result().size()); + + return TEST_SUCCESS; +} + static test_return_t application_true_fubar_eq_doh_BINARY(void *) { Application true_app("true"); @@ -502,14 +537,49 @@ static test_return_t wait_services_BINARY2(void *) return TEST_SUCCESS; } -static test_return_t application_wait_services_BINARY2(void *) +static test_return_t wait_services_appliction_TEST(void *) { test_skip(0, access("/etc/services", R_OK )); - libtest::Application("libtest/wait", true); + libtest::Application wait_app("libtest/wait", true); + wait_app.use_gdb(); + const char *args[]= { "/etc/services", 0 }; + test_compare(Application::SUCCESS, wait_app.run(args)); + test_compare(Application::SUCCESS, wait_app.wait()); - test_compare(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true)); + return TEST_SUCCESS; +} + +static test_return_t gdb_wait_services_appliction_TEST(void *) +{ + test_skip(0, access("/etc/services", R_OK )); + + libtest::Application wait_app("libtest/wait", true); + wait_app.use_gdb(); + + const char *args[]= { "/etc/services", 0 }; + test_compare(Application::SUCCESS, wait_app.run(args)); + test_compare(Application::SUCCESS, wait_app.wait()); + + return TEST_SUCCESS; +} + +static test_return_t gdb_abort_services_appliction_TEST(void *) +{ + libtest::Application abort_app("libtest/abort", true); + abort_app.use_gdb(); + + test_compare(Application::SUCCESS, abort_app.run()); + test_compare(Application::SUCCESS, abort_app.wait()); + + std::string gdb_filename= abort_app.gdb_filename(); + const char *args[]= { "SIGABRT", gdb_filename.c_str(), 0 }; + test_compare(EXIT_SUCCESS, exec_cmdline("grep", args)); + + // Sanity test + args[0]= "THIS_WILL_NOT_BE_FOUND"; + test_compare(EXIT_FAILURE, exec_cmdline("grep", args)); return TEST_SUCCESS; } @@ -541,6 +611,21 @@ static test_return_t number_of_cpus_TEST(void *) return TEST_SUCCESS; } +static test_return_t create_tmpfile_TEST(void *) +{ + std::string tmp= create_tmpfile(__func__); + + Application touch_app("touch"); + const char *args[]= { tmp.c_str(), 0 }; + test_compare(Application::SUCCESS, touch_app.run(args)); + test_compare(Application::SUCCESS, touch_app.wait()); + + test_compare_hint(0, access(tmp.c_str(), R_OK), strerror(errno)); + test_compare_hint(0, unlink(tmp.c_str()), strerror(errno)); + + return TEST_SUCCESS; +} + static test_return_t fatal_message_TEST(void *) { test_compare(fatal_calls++, fatal::disabled_counter()); @@ -640,6 +725,9 @@ test_st cmdline_tests[] ={ {"wait --quiet --version", 0, wait_version_BINARY }, {"wait --quiet /etc/services", 0, wait_services_BINARY }, {"wait /etc/services", 0, wait_services_BINARY2 }, + {"wait /etc/services", 0, wait_services_appliction_TEST }, + {"gdb wait /etc/services", 0, gdb_wait_services_appliction_TEST }, + {"gdb abort", 0, gdb_abort_services_appliction_TEST }, {0, 0, 0} }; @@ -660,10 +748,18 @@ test_st number_of_cpus_TESTS[] ={ {0, 0, 0} }; +test_st create_tmpfile_TESTS[] ={ + {"libtest::create_tmpfile()", 0, create_tmpfile_TEST }, + {0, 0, 0} +}; + test_st application_tests[] ={ {"vchar_t", 0, vchar_t_TEST }, {"true", 0, application_true_BINARY }, + {"gbd true --fubar", 0, application_gdb_true_BINARY }, + {"gbd true", 0, application_gdb_true_BINARY2 }, {"true --fubar", 0, application_true_fubar_BINARY }, + {"doesnotexist --fubar", 0, application_doesnotexist_BINARY }, {"true --fubar=doh", 0, application_true_fubar_eq_doh_BINARY }, {"true --fubar=doh add_option()", 0, application_true_fubar_eq_doh_option_BINARY }, {"echo fubar", 0, application_echo_fubar_BINARY }, @@ -710,6 +806,7 @@ collection_st collection[] ={ {"get_free_port()", 0, 0, get_free_port_TESTS }, {"fatal", disable_fatal_exception, enable_fatal_exception, fatal_message_TESTS }, {"number_of_cpus()", 0, 0, number_of_cpus_TESTS }, + {"create_tmpfile()", 0, 0, create_tmpfile_TESTS }, {0, 0, 0, 0} }; diff --git a/tests/libmemcached-1.0/all_tests.h b/tests/libmemcached-1.0/all_tests.h index 47db429d..c54a5071 100644 --- a/tests/libmemcached-1.0/all_tests.h +++ b/tests/libmemcached-1.0/all_tests.h @@ -37,6 +37,8 @@ #pragma once +#include + /* Clean the server before beginning testing */ test_st tests[] ={ diff --git a/tests/libmemcached-1.0/include.am b/tests/libmemcached-1.0/include.am index 48a03695..a320a9a5 100644 --- a/tests/libmemcached-1.0/include.am +++ b/tests/libmemcached-1.0/include.am @@ -25,6 +25,7 @@ noinst_HEADERS+= \ tests/libmemcached-1.0/generate.h \ tests/libmemcached-1.0/haldenbrand.h \ tests/libmemcached-1.0/mem_functions.h \ + tests/libmemcached-1.0/memcached_get.h \ tests/libmemcached-1.0/setup_and_teardowns.h \ tests/libmemcached-1.0/stat.h \ tests/namespace.h \ @@ -67,6 +68,7 @@ tests_libmemcached_1_0_testapp_SOURCES= \ tests/libmemcached-1.0/haldenbrand.cc \ tests/libmemcached-1.0/ketama.cc \ tests/libmemcached-1.0/mem_functions.cc \ + tests/libmemcached-1.0/memcached_get.cc \ tests/libmemcached-1.0/namespace.cc \ tests/libmemcached-1.0/parser.cc \ tests/libmemcached-1.0/pool.cc \ @@ -113,6 +115,7 @@ tests_libmemcached_1_0_testsocket_SOURCES= \ tests/libmemcached-1.0/haldenbrand.cc \ tests/libmemcached-1.0/ketama.cc \ tests/libmemcached-1.0/mem_functions.cc \ + tests/libmemcached-1.0/memcached_get.cc \ tests/libmemcached-1.0/namespace.cc \ tests/libmemcached-1.0/parser.cc \ tests/libmemcached-1.0/pool.cc \ diff --git a/tests/libmemcached-1.0/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index a878b2df..8a1951e6 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -192,16 +192,6 @@ private: std::vector _lengths; }; -static memcached_return_t return_value_based_on_buffering(memcached_st *memc) -{ - if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS)) - { - return MEMCACHED_BUFFERED; - } - - return MEMCACHED_SUCCESS; -} - static memcached_st * create_single_instance_memcached(const memcached_st *original_memc, const char *options) { /* @@ -1185,62 +1175,6 @@ test_return_t read_through(memcached_st *memc) return TEST_SUCCESS; } -test_return_t get_test(memcached_st *memc) -{ - uint64_t query_id= memcached_query_id(memc); - memcached_return_t rc= memcached_delete(memc, - test_literal_param(__func__), - time_t(0)); - test_true_hint(rc == MEMCACHED_BUFFERED or rc == MEMCACHED_NOTFOUND, memcached_last_error_message(memc)); - test_compare(query_id +1, memcached_query_id(memc)); - - size_t string_length; - uint32_t flags; - char *string= memcached_get(memc, - test_literal_param(__func__), - &string_length, &flags, &rc); - - test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_last_error_message(memc)); - test_false(string_length); - test_false(string); - - return TEST_SUCCESS; -} - -test_return_t get_test2(memcached_st *memc) -{ - const char *value= "when we sanitize"; - - uint64_t query_id= memcached_query_id(memc); - test_compare(return_value_based_on_buffering(memc), - memcached_set(memc, - test_literal_param(__func__), - value, strlen(value), - time_t(0), uint32_t(0))); - test_compare(query_id +1, memcached_query_id(memc)); - - query_id= memcached_query_id(memc); - test_true(query_id); - - uint32_t flags; - size_t string_length; - memcached_return_t rc; - char *string= memcached_get(memc, - test_literal_param(__func__), - &string_length, &flags, &rc); - test_compare(query_id +1, memcached_query_id(memc)); - - test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); - test_compare_got(MEMCACHED_SUCCESS, memcached_last_error(memc), memcached_last_error_message(memc)); - test_true(string); - test_compare(strlen(value), string_length); - test_memcmp(string, value, string_length); - - free(string); - - return TEST_SUCCESS; -} - test_return_t set_test2(memcached_st *memc) { for (uint32_t x= 0; x < 10; x++) @@ -1285,126 +1219,6 @@ test_return_t set_test3(memcached_st *memc) return TEST_SUCCESS; } -test_return_t get_test3(memcached_st *memc) -{ - size_t value_length= 8191; - - libtest::vchar_t value; - value.reserve(value_length); - for (uint32_t x= 0; x < value_length; x++) - { - value.push_back(char(x % 127)); - } - - test_compare_hint(return_value_based_on_buffering(memc), - memcached_set(memc, - test_literal_param(__func__), - &value[0], value.size(), - time_t(0), uint32_t(0)), - memcached_last_error_message(memc)); - - size_t string_length; - uint32_t flags; - memcached_return_t rc; - char *string= memcached_get(memc, - test_literal_param(__func__), - &string_length, &flags, &rc); - - test_compare(MEMCACHED_SUCCESS, rc); - test_true(string); - test_compare(value.size(), string_length); - test_memcmp(string, &value[0], string_length); - - free(string); - - return TEST_SUCCESS; -} - -test_return_t get_test4(memcached_st *memc) -{ - size_t value_length= 8191; - - libtest::vchar_t value; - value.reserve(value_length); - for (uint32_t x= 0; x < value_length; x++) - { - value.push_back(char(x % 127)); - } - - test_compare_hint(return_value_based_on_buffering(memc), - memcached_set(memc, - test_literal_param(__func__), - &value[0], value.size(), - time_t(0), uint32_t(0)), - memcached_last_error_message(memc)); - - for (uint32_t x= 0; x < 10; x++) - { - uint32_t flags; - size_t string_length; - memcached_return_t rc; - char *string= memcached_get(memc, - test_literal_param(__func__), - &string_length, &flags, &rc); - - test_compare(MEMCACHED_SUCCESS, rc); - test_true(string); - test_compare(value.size(), string_length); - test_memcmp(string, &value[0], string_length); - free(string); - } - - return TEST_SUCCESS; -} - -/* - * This test verifies that memcached_read_one_response doesn't try to - * dereference a NIL-pointer if you issue a multi-get and don't read out all - * responses before you execute a storage command. - */ -test_return_t get_test5(memcached_st *memc) -{ - /* - ** Request the same key twice, to ensure that we hash to the same server - ** (so that we have multiple response values queued up) ;-) - */ - const char *keys[]= { "key", "key" }; - size_t lengths[]= { 3, 3 }; - uint32_t flags; - size_t rlen; - - test_compare_hint(return_value_based_on_buffering(memc), - memcached_set(memc, keys[0], lengths[0], - keys[0], lengths[0], - time_t(0), uint32_t(0)), - memcached_last_error_message(memc)); - test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys))); - - memcached_result_st results_obj; - memcached_result_st *results= memcached_result_create(memc, &results_obj); - test_true(results); - - memcached_return_t rc; - results= memcached_fetch_result(memc, &results_obj, &rc); - test_true(results); - - memcached_result_free(&results_obj); - - /* Don't read out the second result, but issue a set instead.. */ - test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0)); - - char *val= memcached_get_by_key(memc, keys[0], lengths[0], "yek", 3, - &rlen, &flags, &rc); - test_false(val); - test_compare(MEMCACHED_NOTFOUND, rc); - val= memcached_get(memc, keys[0], lengths[0], &rlen, &flags, &rc); - test_true(val); - test_compare(MEMCACHED_SUCCESS, rc); - free(val); - - return TEST_SUCCESS; -} - test_return_t mget_end(memcached_st *memc) { const char *keys[]= { "foo", "foo2" }; diff --git a/tests/libmemcached-1.0/mem_functions.h b/tests/libmemcached-1.0/mem_functions.h index 7126f7fc..d632dd4b 100644 --- a/tests/libmemcached-1.0/mem_functions.h +++ b/tests/libmemcached-1.0/mem_functions.h @@ -78,11 +78,6 @@ test_return_t fnv1a_32_run (memcached_st *); test_return_t fnv1a_64_run (memcached_st *); test_return_t get_stats(memcached_st *memc); test_return_t get_stats_keys(memcached_st *memc); -test_return_t get_test(memcached_st *memc); -test_return_t get_test2(memcached_st *memc); -test_return_t get_test3(memcached_st *memc); -test_return_t get_test4(memcached_st *memc); -test_return_t get_test5(memcached_st *memc); test_return_t getpid_connection_failure_test(memcached_st *memc); test_return_t getpid_test(memcached_st *memc); test_return_t hash_sanity_test (memcached_st *memc); diff --git a/tests/libmemcached-1.0/memcached_get.cc b/tests/libmemcached-1.0/memcached_get.cc new file mode 100644 index 00000000..2636ecdb --- /dev/null +++ b/tests/libmemcached-1.0/memcached_get.cc @@ -0,0 +1,222 @@ +/* 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 +#include + +/* + Test cases +*/ + +#include +#include "tests/libmemcached-1.0/memcached_get.h" +#include "tests/libmemcached-1.0/setup_and_teardowns.h" + +test_return_t get_test(memcached_st *memc) +{ + uint64_t query_id= memcached_query_id(memc); + memcached_return_t rc= memcached_delete(memc, + test_literal_param(__func__), + time_t(0)); + test_true_hint(rc == MEMCACHED_BUFFERED or rc == MEMCACHED_NOTFOUND, memcached_last_error_message(memc)); + test_compare(query_id +1, memcached_query_id(memc)); + + size_t string_length; + uint32_t flags; + char *string= memcached_get(memc, + test_literal_param(__func__), + &string_length, &flags, &rc); + + test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_last_error_message(memc)); + test_false(string_length); + test_false(string); + + return TEST_SUCCESS; +} + +test_return_t get_test2(memcached_st *memc) +{ + const char *value= "when we sanitize"; + + uint64_t query_id= memcached_query_id(memc); + test_compare(return_value_based_on_buffering(memc), + memcached_set(memc, + test_literal_param(__func__), + value, strlen(value), + time_t(0), uint32_t(0))); + test_compare(query_id +1, memcached_query_id(memc)); + + query_id= memcached_query_id(memc); + test_true(query_id); + + uint32_t flags; + size_t string_length; + memcached_return_t rc; + char *string= memcached_get(memc, + test_literal_param(__func__), + &string_length, &flags, &rc); + test_compare(query_id +1, memcached_query_id(memc)); + + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_last_error(memc), memcached_last_error_message(memc)); + test_true(string); + test_compare(strlen(value), string_length); + test_memcmp(string, value, string_length); + + free(string); + + return TEST_SUCCESS; +} + +test_return_t get_test3(memcached_st *memc) +{ + size_t value_length= 8191; + + libtest::vchar_t value; + value.reserve(value_length); + for (uint32_t x= 0; x < value_length; x++) + { + value.push_back(char(x % 127)); + } + + test_compare_hint(return_value_based_on_buffering(memc), + memcached_set(memc, + test_literal_param(__func__), + &value[0], value.size(), + time_t(0), uint32_t(0)), + memcached_last_error_message(memc)); + + size_t string_length; + uint32_t flags; + memcached_return_t rc; + char *string= memcached_get(memc, + test_literal_param(__func__), + &string_length, &flags, &rc); + + test_compare(MEMCACHED_SUCCESS, rc); + test_true(string); + test_compare(value.size(), string_length); + test_memcmp(string, &value[0], string_length); + + free(string); + + return TEST_SUCCESS; +} + +test_return_t get_test4(memcached_st *memc) +{ + size_t value_length= 8191; + + libtest::vchar_t value; + value.reserve(value_length); + for (uint32_t x= 0; x < value_length; x++) + { + value.push_back(char(x % 127)); + } + + test_compare_hint(return_value_based_on_buffering(memc), + memcached_set(memc, + test_literal_param(__func__), + &value[0], value.size(), + time_t(0), uint32_t(0)), + memcached_last_error_message(memc)); + + for (uint32_t x= 0; x < 10; x++) + { + uint32_t flags; + size_t string_length; + memcached_return_t rc; + char *string= memcached_get(memc, + test_literal_param(__func__), + &string_length, &flags, &rc); + + test_compare(MEMCACHED_SUCCESS, rc); + test_true(string); + test_compare(value.size(), string_length); + test_memcmp(string, &value[0], string_length); + free(string); + } + + return TEST_SUCCESS; +} + +/* + * This test verifies that memcached_read_one_response doesn't try to + * dereference a NIL-pointer if you issue a multi-get and don't read out all + * responses before you execute a storage command. + */ +test_return_t get_test5(memcached_st *memc) +{ + /* + ** Request the same key twice, to ensure that we hash to the same server + ** (so that we have multiple response values queued up) ;-) + */ + const char *keys[]= { "key", "key" }; + size_t lengths[]= { 3, 3 }; + uint32_t flags; + size_t rlen; + + test_compare_hint(return_value_based_on_buffering(memc), + memcached_set(memc, keys[0], lengths[0], + keys[0], lengths[0], + time_t(0), uint32_t(0)), + memcached_last_error_message(memc)); + test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys))); + + memcached_result_st results_obj; + memcached_result_st *results= memcached_result_create(memc, &results_obj); + test_true(results); + + memcached_return_t rc; + results= memcached_fetch_result(memc, &results_obj, &rc); + test_true(results); + + memcached_result_free(&results_obj); + + /* Don't read out the second result, but issue a set instead.. */ + test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0)); + + char *val= memcached_get_by_key(memc, keys[0], lengths[0], "yek", 3, + &rlen, &flags, &rc); + test_false(val); + test_compare(MEMCACHED_NOTFOUND, rc); + val= memcached_get(memc, keys[0], lengths[0], &rlen, &flags, &rc); + test_true(val); + test_compare(MEMCACHED_SUCCESS, rc); + free(val); + + return TEST_SUCCESS; +} diff --git a/tests/libmemcached-1.0/memcached_get.h b/tests/libmemcached-1.0/memcached_get.h new file mode 100644 index 00000000..46e8def3 --- /dev/null +++ b/tests/libmemcached-1.0/memcached_get.h @@ -0,0 +1,44 @@ +/* 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 get_test(memcached_st*); +test_return_t get_test2(memcached_st*); +test_return_t get_test3(memcached_st*); +test_return_t get_test4(memcached_st*); +test_return_t get_test5(memcached_st*); + diff --git a/tests/libmemcached-1.0/setup_and_teardowns.cc b/tests/libmemcached-1.0/setup_and_teardowns.cc index 84f57abe..9bf0e92a 100644 --- a/tests/libmemcached-1.0/setup_and_teardowns.cc +++ b/tests/libmemcached-1.0/setup_and_teardowns.cc @@ -44,6 +44,17 @@ #include + +memcached_return_t return_value_based_on_buffering(memcached_st *memc) +{ + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS)) + { + return MEMCACHED_BUFFERED; + } + + return MEMCACHED_SUCCESS; +} + /** @note This should be testing to see if the server really supports the binary protocol. */ diff --git a/tests/libmemcached-1.0/setup_and_teardowns.h b/tests/libmemcached-1.0/setup_and_teardowns.h index e141685f..fa6fbdf2 100644 --- a/tests/libmemcached-1.0/setup_and_teardowns.h +++ b/tests/libmemcached-1.0/setup_and_teardowns.h @@ -37,6 +37,8 @@ #pragma once +memcached_return_t return_value_based_on_buffering(memcached_st*); + test_return_t pre_behavior_ketama(memcached_st*); test_return_t pre_behavior_ketama_weighted(memcached_st*); test_return_t pre_binary(memcached_st*); diff --git a/util/log.hpp b/util/log.hpp index 885133a2..1442faa3 100644 --- a/util/log.hpp +++ b/util/log.hpp @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include #include @@ -124,23 +125,32 @@ struct log_info_st return fd; } - void write(verbose_t verbose, const char *mesg) + void write(verbose_t verbose, const char *format, ...) { - if (opt_file) + if (opt_file or opt_syslog) { - char buffer[UTIL_MAX_ERROR_SIZE]; - int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %s\n", verbose_name(verbose), mesg); - if (::write(file(), buffer, buffer_length) == -1) + va_list args; + va_start(args, format); + char mesg[BUFSIZ]; + int mesg_length= vsnprintf(mesg, sizeof(mesg), format, args); + va_end(args); + + if (opt_file) { - std::cerr << "Could not write to log file." << std::endl; - syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno)); - } + char buffer[UTIL_MAX_ERROR_SIZE]; + int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %.*s\n", verbose_name(verbose), mesg_length, mesg); + if (::write(file(), buffer, buffer_length) == -1) + { + std::cerr << "Could not write to log file." << std::endl; + syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno)); + } - } + } - if (opt_syslog) - { - syslog(int(verbose), "%7s %s", verbose_name(verbose), mesg); + if (opt_syslog) + { + syslog(int(verbose), "%7s %.*s", verbose_name(verbose), mesg_length, mesg); + } } }