From: Michael Wallner Date: Fri, 16 Oct 2020 18:43:59 +0000 (+0200) Subject: testing X-Git-Tag: 1.1.0-beta1~205 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=ca5b36c524c7b4ecdb436c2e20a8a0b089be127a;p=m6w6%2Flibmemcached testing --- diff --git a/CMake/_Include.cmake b/CMake/_Include.cmake index 41077574..420a9723 100644 --- a/CMake/_Include.cmake +++ b/CMake/_Include.cmake @@ -54,6 +54,10 @@ endif() ## uuid if(BUILD_TESTING) + if(NOT MEMCACHED_BINARY) + find_package(Memcached) + set(MEMCACHED_BINARY ${MEMCACHED_EXECUTABLE}) + endif() check_dependency(LIBUUID uuid uuid/uuid.h) endif() diff --git a/CMakeConfig.txt b/CMakeConfig.txt index 7e36cf5a..710f4cd0 100644 --- a/CMakeConfig.txt +++ b/CMakeConfig.txt @@ -44,11 +44,11 @@ option(ENABLE_MEMASLAP "enable memaslap client" option(ENABLE_SASL "enable SASL support" $ENV{ENABLE_SASL}) -set(ENABLE_SANITIZERS $ENV{ENABLE_SANITIZERS} +set(ENABLE_SANITIZERS "$ENV{ENABLE_SANITIZERS}" CACHE STRING "sanitizers to enable (e.g. address undefined ...)") if(BUILD_TESTING) - set(MEMCACHED_BINARY $ENV{MEMCACHED_BINARY} + set(MEMCACHED_BINARY "$ENV{MEMCACHED_BINARY}" CACHE STRING "memcached binary") set(CMAKE_CTEST_ARGUMENTS "--output-on-failure") if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2339a55b..118dbc44 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,11 +5,8 @@ endif() include(CMake/Catch.cmake) if(NOT MEMCACHED_BINARY) - find_program(MEMCACHED_BINARY memcached DOC "memcached binary") - if(NOT MEMCACHED_BINARY) - message(SEND_ERROR "Could not find memcached(1) binary") - set(ENV{INVALID_CONFIGURATION} 1) - endif() + message(SEND_ERROR "Could not find memcached(1) binary") + set(ENV{INVALID_CONFIGURATION} 1) endif() diff --git a/test/tests/memcached/errors.cpp b/test/tests/memcached/errors.cpp new file mode 100644 index 00000000..16ac61a7 --- /dev/null +++ b/test/tests/memcached/errors.cpp @@ -0,0 +1,16 @@ +#include "test/lib/common.hpp" + +TEST_CASE("memcached_errors") { + SECTION("NO_SERVERS") { + MemcachedPtr memc; + memcached_return_t rc; + auto key = "key"; + size_t len = 3; + + REQUIRE(MEMCACHED_NO_SERVERS == memcached_flush(*memc, 0)); + REQUIRE(MEMCACHED_NO_SERVERS == memcached_set(*memc, S(__func__), S(__func__), 0, 0)); + REQUIRE_FALSE(memcached_get(*memc, S(__func__), nullptr, nullptr, &rc)); + REQUIRE(MEMCACHED_NO_SERVERS == rc); + REQUIRE(MEMCACHED_NO_SERVERS == memcached_mget(*memc, &key, &len, 1)); + } +} diff --git a/test/tests/memcached/noblock.cpp b/test/tests/memcached/noblock.cpp new file mode 100644 index 00000000..aa88b842 --- /dev/null +++ b/test/tests/memcached/noblock.cpp @@ -0,0 +1,43 @@ +#include "test/lib/common.hpp" +#include "test/lib/MemcachedCluster.hpp" + +TEST_CASE("memcached_noblock") { + auto test = MemcachedCluster::network(); + auto memc = &test.memc; + auto timeout = GENERATE(0, -1); + + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1)); + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1)); + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, timeout)); + + auto num = timeout ? 10'000 : 1'000'000; + auto hit = 0u; + auto rnd = random_ascii_string(512); + for (auto i = 0; i < num; ++i) { + auto key = to_string(i); + auto rc = memcached_set(memc, key.c_str(), key.length(), rnd.c_str(), rnd.length(), 1, 0); + switch (rc) { + case MEMCACHED_SUCCESS: + case MEMCACHED_BUFFERED: + case MEMCACHED_SERVER_TEMPORARILY_DISABLED: + break; + case MEMCACHED_TIMEOUT: + case MEMCACHED_WRITE_FAILURE: + if(!timeout) { + --i; + } + ++hit; + REQUIRE(true); + break; + default: + REQUIRE(false); + } + } + INFO("failures triggered: " << hit); + if (timeout) { + CHECK_FALSE(hit); + } else { + CHECK(hit > 0); + CHECK(hit <= test.cluster.getServers().size()); + } +} diff --git a/test/tests/memcached/value_flags.cpp b/test/tests/memcached/value_flags.cpp new file mode 100644 index 00000000..e148b1d3 --- /dev/null +++ b/test/tests/memcached/value_flags.cpp @@ -0,0 +1,38 @@ +#include "test/lib/common.hpp" +#include "test/lib/MemcachedCluster.hpp" + +TEST_CASE("memcached_value_flags") { + auto test = MemcachedCluster::mixed(); + auto memc = &test.memc; + const auto size = 1048064lu; + auto blob = make_unique(size); + + SECTION("set & get flags") { + uint32_t flag = GENERATE(123, 456, 789); + + REQUIRE_SUCCESS(memcached_set(memc, S(__func__), blob.get(), size, 0, flag)); + + size_t len; + uint32_t flg; + memcached_return_t rc; + Malloced val(memcached_get(memc, S(__func__), &len, &flg, &rc)); + REQUIRE_SUCCESS(rc); + REQUIRE(*val); + REQUIRE(len == size); + REQUIRE(flg == flag); + + len = strlen(__func__); + auto fun = __func__; + char key[MEMCACHED_MAX_KEY]; + memcpy(key, fun, strlen(fun) + 1); + const char *keys[1] = {key}; + REQUIRE_SUCCESS(memcached_mget(memc, keys, &len, 1)); + while (auto rv = memcached_fetch(memc, key, nullptr, &len, &flg, &rc)) { + REQUIRE_SUCCESS(rc); + REQUIRE(len == size); + REQUIRE_FALSE(memcmp(rv, blob.get(), len)); + REQUIRE(flag == flg); + } + REQUIRE_RC(MEMCACHED_END, rc); + } +} diff --git a/tests/libmemcached-1.0/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index ddb4c1a6..189f60f2 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -466,468 +466,6 @@ test_return_t memcached_fetch_result_NOT_FOUND(memcached_st *memc) return TEST_SUCCESS; } -/* We don't test the behavior itself, we test the switches */ -test_return_t behavior_test(memcached_st *memc) -{ - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); - test_compare(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); - test_compare(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_MD5); - test_compare(uint64_t(MEMCACHED_HASH_MD5), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_HASH)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); - test_zero(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 0); - test_zero(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_DEFAULT); - test_compare(uint64_t(MEMCACHED_HASH_DEFAULT), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_HASH)); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_CRC); - test_compare(uint64_t(MEMCACHED_HASH_CRC), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_HASH)); - - test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE)); - - test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE)); - - uint64_t value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, value +1); - test_compare((value +1), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS)); - - return TEST_SUCCESS; -} - -test_return_t MEMCACHED_BEHAVIOR_CORK_test(memcached_st *memc) -{ - test_compare(MEMCACHED_DEPRECATED, - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CORK, true)); - - // Platform dependent -#if 0 - bool value= (bool)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CORK); - test_false(value); -#endif - - return TEST_SUCCESS; -} - - -test_return_t MEMCACHED_BEHAVIOR_TCP_KEEPALIVE_test(memcached_st *memc) -{ - memcached_return_t rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE, true); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOT_SUPPORTED); - - bool value= (bool)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); - - if (memcached_success(rc)) - { - test_true(value); - } - else - { - test_false(value); - } - - return TEST_SUCCESS; -} - - -test_return_t MEMCACHED_BEHAVIOR_TCP_KEEPIDLE_test(memcached_st *memc) -{ - memcached_return_t rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_KEEPIDLE, true); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOT_SUPPORTED); - - bool value= (bool)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_KEEPIDLE); - - if (memcached_success(rc)) - { - test_true(value); - } - else - { - test_false(value); - } - - return TEST_SUCCESS; -} - -/* Make sure we behave properly if server list has no values */ -test_return_t user_supplied_bug4(memcached_st *memc) -{ - const char *keys[]= {"fudge", "son", "food"}; - size_t key_length[]= {5, 3, 4}; - - /* Here we free everything before running a bunch of mget tests */ - memcached_servers_reset(memc); - - - /* We need to empty the server before continueing test */ - test_compare(MEMCACHED_NO_SERVERS, - memcached_flush(memc, 0)); - - test_compare(MEMCACHED_NO_SERVERS, - memcached_mget(memc, keys, key_length, 3)); - - { - unsigned int keys_returned; - memcached_return_t rc; - test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, rc)); - test_compare(MEMCACHED_NOTFOUND, rc); - test_zero(keys_returned); - } - - for (uint32_t x= 0; x < 3; x++) - { - test_compare(MEMCACHED_NO_SERVERS, - memcached_set(memc, keys[x], key_length[x], - keys[x], key_length[x], - (time_t)50, (uint32_t)9)); - } - - test_compare(MEMCACHED_NO_SERVERS, - memcached_mget(memc, keys, key_length, 3)); - - { - char *return_value; - char return_key[MEMCACHED_MAX_KEY]; - memcached_return_t rc; - size_t return_key_length; - size_t return_value_length; - uint32_t flags; - uint32_t x= 0; - while ((return_value= memcached_fetch(memc, return_key, &return_key_length, - &return_value_length, &flags, &rc))) - { - test_true(return_value); - test_compare(MEMCACHED_SUCCESS, rc); - test_true(return_key_length == return_value_length); - test_memcmp(return_value, return_key, return_value_length); - free(return_value); - x++; - } - } - - return TEST_SUCCESS; -} - -#define VALUE_SIZE_BUG5 1048064 -test_return_t user_supplied_bug5(memcached_st *memc) -{ - const char *keys[]= {"036790384900", "036790384902", "036790384904", "036790384906"}; - size_t key_length[]= {strlen("036790384900"), strlen("036790384902"), strlen("036790384904"), strlen("036790384906")}; - char *value; - size_t value_length; - uint32_t flags; - char *insert_data= new (std::nothrow) char[VALUE_SIZE_BUG5]; - - for (uint32_t x= 0; x < VALUE_SIZE_BUG5; x++) - { - insert_data[x]= (signed char)rand(); - } - - test_compare(MEMCACHED_SUCCESS, - memcached_flush(memc, 0)); - - memcached_return_t rc; - test_null(memcached_get(memc, keys[0], key_length[0], &value_length, &flags, &rc)); - test_compare(MEMCACHED_SUCCESS, - memcached_mget(memc, keys, key_length, 4)); - - unsigned int count; - test_compare(TEST_SUCCESS, fetch_all_results(memc, count, rc)); - test_compare(MEMCACHED_NOTFOUND, rc); - test_zero(count); - - for (uint32_t x= 0; x < 4; x++) - { - test_compare(MEMCACHED_SUCCESS, - memcached_set(memc, keys[x], key_length[x], - insert_data, VALUE_SIZE_BUG5, - (time_t)0, (uint32_t)0)); - } - - for (uint32_t x= 0; x < 10; x++) - { - value= memcached_get(memc, keys[0], key_length[0], - &value_length, &flags, &rc); - test_compare(rc, MEMCACHED_SUCCESS); - test_true(value); - ::free(value); - - test_compare(MEMCACHED_SUCCESS, - memcached_mget(memc, keys, key_length, 4)); - - test_compare(TEST_SUCCESS, fetch_all_results(memc, count)); - test_compare(4U, count); - } - delete [] insert_data; - - return TEST_SUCCESS; -} - -test_return_t user_supplied_bug6(memcached_st *memc) -{ - const char *keys[]= {"036790384900", "036790384902", "036790384904", "036790384906"}; - size_t key_length[]= {strlen("036790384900"), strlen("036790384902"), strlen("036790384904"), strlen("036790384906")}; - char return_key[MEMCACHED_MAX_KEY]; - size_t return_key_length; - char *value; - size_t value_length; - uint32_t flags; - char *insert_data= new (std::nothrow) char[VALUE_SIZE_BUG5]; - - for (uint32_t x= 0; x < VALUE_SIZE_BUG5; x++) - { - insert_data[x]= (signed char)rand(); - } - - test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0)); - - test_compare(TEST_SUCCESS, confirm_keys_dont_exist(memc, keys, test_array_length(keys))); - - // We will now confirm that memcached_mget() returns success, but we will - // then check to make sure that no actual keys are returned. - test_compare(MEMCACHED_SUCCESS, - memcached_mget(memc, keys, key_length, 4)); - - memcached_return_t rc; - uint32_t count= 0; - while ((value= memcached_fetch(memc, return_key, &return_key_length, - &value_length, &flags, &rc))) - { - count++; - } - test_zero(count); - test_compare(MEMCACHED_NOTFOUND, rc); - - for (uint32_t x= 0; x < test_array_length(keys); x++) - { - test_compare(MEMCACHED_SUCCESS, - memcached_set(memc, keys[x], key_length[x], - insert_data, VALUE_SIZE_BUG5, - (time_t)0, (uint32_t)0)); - } - test_compare(TEST_SUCCESS, confirm_keys_exist(memc, keys, test_array_length(keys))); - - for (uint32_t x= 0; x < 2; x++) - { - value= memcached_get(memc, keys[0], key_length[0], - &value_length, &flags, &rc); - test_true(value); - free(value); - - test_compare(MEMCACHED_SUCCESS, - memcached_mget(memc, keys, key_length, 4)); - /* We test for purge of partial complete fetches */ - for (count= 3; count; count--) - { - value= memcached_fetch(memc, return_key, &return_key_length, - &value_length, &flags, &rc); - test_compare(MEMCACHED_SUCCESS, rc); - test_memcmp(value, insert_data, value_length); - test_true(value_length); - free(value); - } - } - delete [] insert_data; - - return TEST_SUCCESS; -} - -test_return_t user_supplied_bug8(memcached_st *) -{ - memcached_return_t rc; - memcached_st *mine; - memcached_st *memc_clone; - - memcached_server_st *servers; - const char *server_list= "memcache1.memcache.bk.sapo.pt:11211, memcache1.memcache.bk.sapo.pt:11212, memcache1.memcache.bk.sapo.pt:11213, memcache1.memcache.bk.sapo.pt:11214, memcache2.memcache.bk.sapo.pt:11211, memcache2.memcache.bk.sapo.pt:11212, memcache2.memcache.bk.sapo.pt:11213, memcache2.memcache.bk.sapo.pt:11214"; - - servers= memcached_servers_parse(server_list); - test_true(servers); - - mine= memcached_create(NULL); - rc= memcached_server_push(mine, servers); - test_compare(MEMCACHED_SUCCESS, rc); - memcached_server_list_free(servers); - - test_true(mine); - memc_clone= memcached_clone(NULL, mine); - - memcached_quit(mine); - memcached_quit(memc_clone); - - - memcached_free(mine); - memcached_free(memc_clone); - - return TEST_SUCCESS; -} - -/* Test flag store/retrieve */ -test_return_t user_supplied_bug7(memcached_st *memc) -{ - char *insert_data= new (std::nothrow) char[VALUE_SIZE_BUG5]; - test_true(insert_data); - - for (size_t x= 0; x < VALUE_SIZE_BUG5; x++) - { - insert_data[x]= (signed char)rand(); - } - - memcached_flush(memc, 0); - - const char *keys= "036790384900"; - size_t key_length= strlen(keys); - test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys, key_length, - insert_data, VALUE_SIZE_BUG5, - time_t(0), 245U)); - - memcached_return_t rc; - size_t value_length; - uint32_t flags= 0; - char *value= memcached_get(memc, keys, key_length, - &value_length, &flags, &rc); - test_compare(245U, flags); - test_true(value); - free(value); - - test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, &keys, &key_length, 1)); - - char return_key[MEMCACHED_MAX_KEY]; - size_t return_key_length; - flags= 0; - value= memcached_fetch(memc, return_key, &return_key_length, - &value_length, &flags, &rc); - test_compare(uint32_t(245), flags); - test_true(value); - free(value); - delete [] insert_data; - - - return TEST_SUCCESS; -} - -test_return_t user_supplied_bug9(memcached_st *memc) -{ - const char *keys[]= {"UDATA:edevil@sapo.pt", "fudge&*@#", "for^#@&$not"}; - size_t key_length[3]; - uint32_t flags; - unsigned count= 0; - - char return_key[MEMCACHED_MAX_KEY]; - size_t return_key_length; - char *return_value; - size_t return_value_length; - - - key_length[0]= strlen("UDATA:edevil@sapo.pt"); - key_length[1]= strlen("fudge&*@#"); - key_length[2]= strlen("for^#@&$not"); - - - for (unsigned int x= 0; x < 3; x++) - { - memcached_return_t rc= memcached_set(memc, keys[x], key_length[x], - keys[x], key_length[x], - (time_t)50, (uint32_t)9); - test_compare(MEMCACHED_SUCCESS, rc); - } - - memcached_return_t rc= memcached_mget(memc, keys, key_length, 3); - test_compare(MEMCACHED_SUCCESS, rc); - - /* We need to empty the server before continueing test */ - while ((return_value= memcached_fetch(memc, return_key, &return_key_length, - &return_value_length, &flags, &rc)) != NULL) - { - test_true(return_value); - free(return_value); - count++; - } - test_compare(3U, count); - - return TEST_SUCCESS; -} - -/* We are testing with aggressive timeout to get failures */ -test_return_t user_supplied_bug10(memcached_st *memc) -{ - test_skip(memc->servers[0].type, MEMCACHED_CONNECTION_TCP); - - size_t value_length= 512; - unsigned int set= 1; - memcached_st *mclone= memcached_clone(NULL, memc); - - memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, set); - memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, set); - memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, uint64_t(0)); - - libtest::vchar_t value; - value.reserve(value_length); - for (uint32_t x= 0; x < value_length; x++) - { - value.push_back(char(x % 127)); - } - - for (unsigned int x= 1; x <= 100000; ++x) - { - memcached_return_t rc= memcached_set(mclone, - test_literal_param("foo"), - &value[0], value.size(), - 0, 0); - - test_true((rc == MEMCACHED_SUCCESS or rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_BUFFERED or rc == MEMCACHED_TIMEOUT or rc == MEMCACHED_CONNECTION_FAILURE - or rc == MEMCACHED_SERVER_TEMPORARILY_DISABLED)); - - if (rc == MEMCACHED_WRITE_FAILURE or rc == MEMCACHED_TIMEOUT) - { - x--; - } - } - - memcached_free(mclone); - - return TEST_SUCCESS; -} - -/* - We are looking failures in the async protocol -*/ -test_return_t user_supplied_bug11(memcached_st *memc) -{ - (void)memc; -#ifndef __APPLE__ - test::Memc mclone(memc); - - memcached_behavior_set(&mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, true); - memcached_behavior_set(&mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, true); - memcached_behavior_set(&mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, size_t(-1)); - - test_compare(-1, int32_t(memcached_behavior_get(&mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT))); - - libtest::vchar_t value; - value.reserve(512); - for (unsigned int x= 0; x < 512; x++) - { - value.push_back(char(x % 127)); - } - - for (unsigned int x= 1; x <= 100000; ++x) - { - memcached_return_t rc= memcached_set(&mclone, test_literal_param("foo"), &value[0], value.size(), 0, 0); - (void)rc; - } - -#endif - - return TEST_SUCCESS; -} - /* Bug found where incr was not returning MEMCACHED_NOTFOUND when object did not exist. */