From e0c3f8e0995de37aa10192cba3a1ea076f95830c Mon Sep 17 00:00:00 2001 From: Samarah Date: Fri, 28 Jul 2023 09:44:03 -0400 Subject: [PATCH] test/d4n: this commit squashes the following commits related to tests for d4n. test/redis: Add temporary `boost::redis` unit test program for experimentation test/rgw: Add/update unit test programs for D4N classes + RedisDriver; switch to `boost::redis` usage test/d4n: Begin `cpp_redis` removal from D4N filter test program; needs to be fixed test/d4n: Temporarily remove D4N filter test program until D4N workflows are fully implemented Signed-off-by: Samarah --- src/test/rgw/CMakeLists.txt | 53 +- src/test/rgw/run-d4n-unit-tests.sh | 16 +- src/test/rgw/test_boost_redis.cc | 163 +++ src/test/rgw/test_d4n_directory.cc | 578 ++++++-- src/test/rgw/test_d4n_filter.cc | 2132 ---------------------------- src/test/rgw/test_d4n_policy.cc | 253 ++++ src/test/rgw/test_redis_driver.cc | 497 +++++++ 7 files changed, 1393 insertions(+), 2299 deletions(-) create mode 100644 src/test/rgw/test_boost_redis.cc delete mode 100644 src/test/rgw/test_d4n_filter.cc create mode 100644 src/test/rgw/test_d4n_policy.cc create mode 100644 src/test/rgw/test_redis_driver.cc diff --git a/src/test/rgw/CMakeLists.txt b/src/test/rgw/CMakeLists.txt index dec7ea1c149c4..3367314f4820b 100644 --- a/src/test/rgw/CMakeLists.txt +++ b/src/test/rgw/CMakeLists.txt @@ -37,16 +37,49 @@ target_link_libraries(ceph_test_rgw_d4n_directory PRIVATE ) target_link_libraries(ceph_test_rgw_d4n_directory PRIVATE spawn) install(TARGETS ceph_test_rgw_d4n_directory DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif() -if(WITH_RADOSGW_D4N) -add_executable(ceph_test_rgw_d4n_filter - test_d4n_filter.cc - ) -target_include_directories(ceph_test_rgw_d4n_filter +add_executable(ceph_test_rgw_d4n_policy + test_d4n_policy.cc + ) +target_include_directories(ceph_test_rgw_d4n_policy + PUBLIC "${CMAKE_SOURCE_DIR}/src/dmclock/support/src" + SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw/") +target_link_libraries(ceph_test_rgw_d4n_policy PRIVATE + rgw_common + librados + ceph-common + ${rgw_libs} + ${UNITTEST_LIBS} + ${EXTRALIBS} + ) + target_link_libraries(ceph_test_rgw_d4n_policy PRIVATE spawn) +install(TARGETS ceph_test_rgw_d4n_policy DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(ceph_test_rgw_redis_driver + test_redis_driver.cc + ) +target_include_directories(ceph_test_rgw_redis_driver + PUBLIC "${CMAKE_SOURCE_DIR}/src/dmclock/support/src" + SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw/") +target_link_libraries(ceph_test_rgw_redis_driver PRIVATE + rgw_common + librados + ceph-common + ${rgw_libs} + ${UNITTEST_LIBS} + ${EXTRALIBS} + ) + target_link_libraries(ceph_test_rgw_redis_driver PRIVATE spawn) +install(TARGETS ceph_test_rgw_redis_driver DESTINATION ${CMAKE_INSTALL_BINDIR}) + +# remove later -Sam +add_executable(test_boost_redis + test_boost_redis.cc + ) +target_include_directories(test_boost_redis PUBLIC "${CMAKE_SOURCE_DIR}/src/dmclock/support/src" - SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw/store/dbstore/common") -target_link_libraries(ceph_test_rgw_d4n_filter PRIVATE + SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw/driver/d4n") +target_link_libraries(test_boost_redis PRIVATE rgw_common librados ceph-common @@ -54,8 +87,8 @@ target_link_libraries(ceph_test_rgw_d4n_filter PRIVATE ${UNITTEST_LIBS} ${EXTRALIBS} ) - target_link_libraries(ceph_test_rgw_d4n_filter PRIVATE spawn) -install(TARGETS ceph_test_rgw_d4n_filter DESTINATION ${CMAKE_INSTALL_BINDIR}) + target_link_libraries(test_boost_redis PRIVATE spawn) +install(TARGETS test_boost_redis DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() #unittest_rgw_bencode diff --git a/src/test/rgw/run-d4n-unit-tests.sh b/src/test/rgw/run-d4n-unit-tests.sh index 3490b8e2bcd53..6c4c4ff9110d8 100755 --- a/src/test/rgw/run-d4n-unit-tests.sh +++ b/src/test/rgw/run-d4n-unit-tests.sh @@ -4,17 +4,21 @@ if [ $? -eq 0 ]; then echo "Redis process found; flushing!" redis-cli FLUSHALL -fi +else redis-server --daemonize yes -echo "-----------Redis Server Started-----------" +fi + ../../../build/bin/ceph_test_rgw_d4n_directory printf "\n-----------Directory Test Executed-----------\n" + redis-cli FLUSHALL -echo "-----------Redis Server Flushed-----------" -../../../build/bin/ceph_test_rgw_d4n_filter -printf "\n-----------Filter Test Executed-----------\n" +../../../build/bin/ceph_test_rgw_d4n_policy +printf "\n-----------Policy Test Executed-----------\n" + redis-cli FLUSHALL -echo "-----------Redis Server Flushed-----------" +../../../build/bin/ceph_test_rgw_redis_driver +printf "\n-----------RedisDriver Test Executed-----------\n" + REDIS_PID=$(lsof -i4TCP:6379 -sTCP:LISTEN -t) kill $REDIS_PID echo "-----------Redis Server Stopped-----------" diff --git a/src/test/rgw/test_boost_redis.cc b/src/test/rgw/test_boost_redis.cc new file mode 100644 index 0000000000000..8ec5f01acf51c --- /dev/null +++ b/src/test/rgw/test_boost_redis.cc @@ -0,0 +1,163 @@ +#include +#include + +#include +#include +#include + +namespace net = boost::asio; +using boost::redis::config; +using boost::redis::connection; +using boost::redis::request; +using boost::redis::response; + +class ConnectionFixture: public ::testing::Test { + protected: + virtual void SetUp() { + conn = new connection{io}; + + /* Run context */ + using Executor = net::io_context::executor_type; + using Work = net::executor_work_guard; + work = new std::optional(io.get_executor()); + worker = new std::thread([&] { io.run(); }); + + config cfg; + cfg.addr.host = "127.0.0.1"; + cfg.addr.port = "6379"; + + conn->async_run(cfg, {}, net::detached); + } + + virtual void TearDown() { + io.stop(); + + delete conn; + delete work; + delete worker; + } + + net::io_context io; + connection* conn; + + using Executor = net::io_context::executor_type; + using Work = net::executor_work_guard; + std::optional* work; + std::thread* worker; +}; + +TEST_F(ConnectionFixture, Ping) { + ASSERT_NE(conn, nullptr); + + request req; + req.push("PING", "Hello world"); + + response resp; + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), "Hello world"); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +TEST_F(ConnectionFixture, HMSet) { + request req; + response resp; + + req.push("HMSET", "key", "data", "value"); + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), "OK"); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +TEST_F(ConnectionFixture, HGETALL) { + request req; + response > resp; + + req.push("HMSET", "key", "data", "value"); + req.push("HGETALL", "key"); + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), "OK"); + EXPECT_EQ(std::get<1>(resp).value().size(), 1); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +TEST_F(ConnectionFixture, HMGET) { + request req; + response > resp; + + req.push("HMSET", "key", "data", "value"); + req.push("HMGET", "key", "data"); + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), "OK"); + EXPECT_EQ(std::get<1>(resp).value()[0], "value"); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +TEST_F(ConnectionFixture, HSET) { + request req; + response resp; + + req.push_range("HSET", "key", std::map{{"field", "value"}}); + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), 1); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +TEST_F(ConnectionFixture, FLUSHALL) { + request req; + response resp; + + req.push("HMSET", "key", "data", "value"); + req.push("FLUSHALL"); + + conn->async_exec(req, resp, [&](auto ec, auto) { + ASSERT_EQ((bool)ec, 0); + EXPECT_EQ(std::get<0>(resp).value(), "OK"); + + conn->cancel(); + }); + + *work = std::nullopt; + worker->join(); +} + +int main(int argc, char *argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/test/rgw/test_d4n_directory.cc b/src/test/rgw/test_d4n_directory.cc index c69d2d4ecb1a1..806417416daa7 100644 --- a/src/test/rgw/test_d4n_directory.cc +++ b/src/test/rgw/test_d4n_directory.cc @@ -1,206 +1,482 @@ -#include "../rgw/driver/d4n/d4n_directory.h" // Fix -Sam -#include "rgw_process_env.h" -#include -#include -#include -#include "gtest/gtest.h" +#include +#include +#include -using namespace std; +#include "gtest/gtest.h" +#include "common/ceph_argparse.h" +#include "rgw_auth_registry.h" +#include "driver/d4n/d4n_directory.h" + +namespace net = boost::asio; +using boost::redis::config; +using boost::redis::connection; +using boost::redis::request; +using boost::redis::response; + +class Environment* env; + +class Environment : public ::testing::Environment { + public: + Environment() {} + + virtual ~Environment() {} + + void SetUp() override { + std::vector args; + std::string conf_file_list; + std::string cluster = ""; + CephInitParameters iparams = ceph_argparse_early_args( + args, CEPH_ENTITY_TYPE_CLIENT, + &cluster, &conf_file_list); + + cct = common_preinit(iparams, CODE_ENVIRONMENT_UTILITY, {}); + dpp = new DoutPrefix(cct->get(), dout_subsys, "D4N Object Directory Test: "); + + redisHost = cct->_conf->rgw_d4n_host + ":" + std::to_string(cct->_conf->rgw_d4n_port); + } + + void TearDown() override { + delete dpp; + } -string portStr; -string hostStr; -string redisHost = ""; -string oid = "testName"; -string bucketName = "testBucket"; -int blockSize = 123; + std::string redisHost; + CephContext* cct; + DoutPrefixProvider* dpp; +}; -class DirectoryFixture: public ::testing::Test { +class ObjectDirectoryFixture: public ::testing::Test { protected: virtual void SetUp() { - blockDir = new rgw::d4n::BlockDirectory(hostStr, stoi(portStr)); - cacheBlock = new rgw::d4n::CacheBlock(); + dir = new rgw::d4n::ObjectDirectory{io}; + obj = new rgw::d4n::CacheObj{ + .objName = "testName", + .bucketName = "testBucket", + .creationTime = 0, + .dirty = false, + .hostsList = { env->redisHost } + }; + + conn = new connection{boost::asio::make_strand(io)}; - cacheBlock->hostsList.push_back(redisHost); - cacheBlock->size = blockSize; - cacheBlock->cacheObj.bucketName = bucketName; - cacheBlock->cacheObj.objName = oid; + ASSERT_NE(obj, nullptr); + ASSERT_NE(dir, nullptr); + ASSERT_NE(conn, nullptr); + + dir->init(env->cct, env->dpp); + + /* Run fixture's connection */ + config cfg; + cfg.addr.host = env->cct->_conf->rgw_d4n_host; + cfg.addr.port = std::to_string(env->cct->_conf->rgw_d4n_port); + + conn->async_run(cfg, {}, net::detached); } virtual void TearDown() { - delete blockDir; - blockDir = nullptr; + delete conn; + delete obj; + delete dir; + } + + rgw::d4n::CacheObj* obj; + rgw::d4n::ObjectDirectory* dir; + + net::io_context io; + connection* conn; - delete cacheBlock; - cacheBlock = nullptr; + std::vector vals{"testName", "testBucket", "0", "0", env->redisHost}; + std::vector fields{"objName", "bucketName", "creationTime", "dirty", "objHosts"}; +}; + +class BlockDirectoryFixture: public ::testing::Test { + protected: + virtual void SetUp() { + dir = new rgw::d4n::BlockDirectory{io}; + block = new rgw::d4n::CacheBlock{ + .cacheObj = { + .objName = "testName", + .bucketName = "testBucket", + .creationTime = 0, + .dirty = false, + .hostsList = { env->redisHost } + }, + .blockID = 0, + .version = "", + .size = 0, + .hostsList = { env->redisHost } + }; + + conn = new connection{boost::asio::make_strand(io)}; + + ASSERT_NE(block, nullptr); + ASSERT_NE(dir, nullptr); + ASSERT_NE(conn, nullptr); + + dir->init(env->cct, env->dpp); + + /* Run fixture's connection */ + config cfg; + cfg.addr.host = env->cct->_conf->rgw_d4n_host; + cfg.addr.port = std::to_string(env->cct->_conf->rgw_d4n_port); + + conn->async_run(cfg, {}, net::detached); + } + + virtual void TearDown() { + delete conn; + delete block; + delete dir; } - rgw::d4n::BlockDirectory* blockDir; - rgw::d4n::CacheBlock* cacheBlock; + rgw::d4n::CacheBlock* block; + rgw::d4n::BlockDirectory* dir; + + net::io_context io; + connection* conn; + + std::vector vals{"0", "", "0", "0", env->redisHost, + "testName", "testBucket", "0", "0", env->redisHost}; + std::vector fields{"blockID", "version", "size", "globalWeight", "blockHosts", + "objName", "bucketName", "creationTime", "dirty", "objHosts"}; }; -/* Successful initialization */ -TEST_F(DirectoryFixture, DirectoryInit) { - ASSERT_NE(blockDir, nullptr); - ASSERT_NE(cacheBlock, nullptr); - ASSERT_NE(redisHost.length(), (long unsigned int)0); +TEST_F(ObjectDirectoryFixture, SetYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(obj, optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push_range("HMGET", "testBucket_testName", fields); + req.push("FLUSHALL"); + + response< std::vector, + boost::redis::ignore_t > resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), vals); + conn->cancel(); + }); + + io.run(); } -/* Successful set_value Call and Redis Check */ -TEST_F(DirectoryFixture, SetValueTest) { - cpp_redis::client client; - int key_exist = -1; - string key; - string hosts; - string size; - string bucketName; - string objName; - std::vector fields; - int setReturn = blockDir->set_value(cacheBlock); - - ASSERT_EQ(setReturn, 0); - - fields.push_back("key"); - fields.push_back("hosts"); - fields.push_back("size"); - fields.push_back("bucketName"); - fields.push_back("objName"); - - client.connect(hostStr, stoi(portStr), nullptr, 0, 5, 1000); - ASSERT_EQ((bool)client.is_connected(), (bool)1); - - client.hmget("rgw-object:" + oid + ":block-directory", fields, [&key, &hosts, &size, &bucketName, &objName, &key_exist](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - key_exist = 0; - key = arr[0].as_string(); - hosts = arr[1].as_string(); - size = arr[2].as_string(); - bucketName = arr[3].as_string(); - objName = arr[4].as_string(); +TEST_F(ObjectDirectoryFixture, GetYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(obj, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HSET", "testBucket_testName", "objName", "newoid"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); } + + ASSERT_EQ(0, dir->get(obj, optional_yield{io, yield})); + EXPECT_EQ(obj->objName, "newoid"); + dir->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + } + + conn->cancel(); }); - client.sync_commit(); + io.run(); +} + +TEST_F(ObjectDirectoryFixture, CopyYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(obj, optional_yield{io, yield})); + ASSERT_EQ(0, dir->copy(obj, "copyTestName", "copyBucketName", optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push("EXISTS", "copyBucketName_copyTestName"); + req.push_range("HMGET", "copyBucketName_copyTestName", fields); + req.push("FLUSHALL"); + + response, + boost::redis::ignore_t> resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + + auto copyVals = vals; + copyVals[0] = "copyTestName"; + copyVals[1] = "copyBucketName"; + EXPECT_EQ(std::get<1>(resp).value(), copyVals); - EXPECT_EQ(key_exist, 0); - EXPECT_EQ(key, "rgw-object:" + oid + ":block-directory"); - EXPECT_EQ(hosts, redisHost); - EXPECT_EQ(size, to_string(blockSize)); - EXPECT_EQ(bucketName, bucketName); - EXPECT_EQ(objName, oid); + conn->cancel(); + }); - client.flushall(); + io.run(); } -/* Successful get_value Calls and Redis Check */ -TEST_F(DirectoryFixture, GetValueTest) { - cpp_redis::client client; - int key_exist = -1; - string key; - string hosts; - string size; - string bucketName; - string objName; - std::vector fields; - int setReturn = blockDir->set_value(cacheBlock); - - ASSERT_EQ(setReturn, 0); - - fields.push_back("key"); - fields.push_back("hosts"); - fields.push_back("size"); - fields.push_back("bucketName"); - fields.push_back("objName"); - - client.connect(hostStr, stoi(portStr), nullptr, 0, 5, 1000); - ASSERT_EQ((bool)client.is_connected(), (bool)1); - - client.hmget("rgw-object:" + oid + ":block-directory", fields, [&key, &hosts, &size, &bucketName, &objName, &key_exist](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - key_exist = 0; - key = arr[0].as_string(); - hosts = arr[1].as_string(); - size = arr[2].as_string(); - bucketName = arr[3].as_string(); - objName = arr[4].as_string(); +TEST_F(ObjectDirectoryFixture, DelYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(obj, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "testBucket_testName"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); } + + ASSERT_EQ(0, dir->del(obj, optional_yield{io, yield})); + dir->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "testBucket_testName"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(BlockDirectoryFixture, SetYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push_range("HMGET", "testBucket_testName_0", fields); + req.push("FLUSHALL"); + + response< std::vector, + boost::redis::ignore_t > resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), vals); + conn->cancel(); }); - client.sync_commit(); + io.run(); +} + +TEST_F(BlockDirectoryFixture, GetYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HSET", "testBucket_testName_0", "objName", "newoid"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } - EXPECT_EQ(key_exist, 0); - EXPECT_EQ(key, "rgw-object:" + oid + ":block-directory"); - EXPECT_EQ(hosts, redisHost); - EXPECT_EQ(size, to_string(blockSize)); - EXPECT_EQ(bucketName, bucketName); - EXPECT_EQ(objName, oid); + ASSERT_EQ(0, dir->get(block, optional_yield{io, yield})); + EXPECT_EQ(block->cacheObj.objName, "newoid"); + dir->shutdown(); - /* Check if object name in directory instance matches redis update */ - client.hset("rgw-object:" + oid + ":block-directory", "objName", "newoid", [](cpp_redis::reply& reply) { - if (!reply.is_null()) { - ASSERT_EQ(reply.as_integer(), 0); + { + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); } + + conn->cancel(); }); - client.sync_commit(); + io.run(); +} + +TEST_F(BlockDirectoryFixture, CopyYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + ASSERT_EQ(0, dir->copy(block, "copyTestName", "copyBucketName", optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push("EXISTS", "copyBucketName_copyTestName_0"); + req.push_range("HMGET", "copyBucketName_copyTestName_0", fields); + req.push("FLUSHALL"); + + response, + boost::redis::ignore_t> resp; - int getReturn = blockDir->get_value(cacheBlock); + conn->async_exec(req, resp, yield[ec]); - ASSERT_EQ(getReturn, 0); - EXPECT_EQ(cacheBlock->cacheObj.objName, "newoid"); + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); - client.flushall(); + auto copyVals = vals; + copyVals[5] = "copyTestName"; + copyVals[6] = "copyBucketName"; + EXPECT_EQ(std::get<1>(resp).value(), copyVals); + + conn->cancel(); + }); + + io.run(); } -/* Successful del_value Call and Redis Check */ -TEST_F(DirectoryFixture, DelValueTest) { - cpp_redis::client client; - vector keys; - int setReturn = blockDir->set_value(cacheBlock); +TEST_F(BlockDirectoryFixture, DelYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "testBucket_testName_0"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + } + + ASSERT_EQ(0, dir->del(block, optional_yield{io, yield})); + dir->shutdown(); - ASSERT_EQ(setReturn, 0); + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "testBucket_testName_0"); + req.push("FLUSHALL"); + response resp; - /* Ensure entry exists in directory before deletion */ - keys.push_back("rgw-object:" + oid + ":block-directory"); + conn->async_exec(req, resp, yield[ec]); - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - ASSERT_EQ(reply.as_integer(), 1); + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); } + + conn->cancel(); }); - int delReturn = blockDir->del_value(cacheBlock); + io.run(); +} + +TEST_F(BlockDirectoryFixture, UpdateFieldYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + ASSERT_EQ(0, dir->update_field(block, "objName", "newTestName", optional_yield{io, yield})); + ASSERT_EQ(0, dir->update_field(block, "blockHosts", "127.0.0.1:5000", optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HMGET", "testBucket_testName_0", "objName", "blockHosts"); + req.push("FLUSHALL"); + response< std::vector, + boost::redis::ignore_t> resp; - ASSERT_EQ(delReturn, 0); + conn->async_exec(req, resp, yield[ec]); - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - ASSERT_EQ(reply.as_integer(), 0); /* Zero keys exist */ + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value()[0], "newTestName"); + EXPECT_EQ(std::get<0>(resp).value()[1], "127.0.0.1:6379_127.0.0.1:5000"); + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(BlockDirectoryFixture, RemoveHostYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + block->hostsList.push_back("127.0.0.1:6000"); + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + ASSERT_EQ(0, dir->remove_host(block, "127.0.0.1:6379", optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", "testBucket_testName_0", "blockHosts"); + req.push("HGET", "testBucket_testName_0", "blockHosts"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + EXPECT_EQ(std::get<1>(resp).value(), "127.0.0.1:6000"); } + + ASSERT_EQ(0, dir->remove_host(block, "127.0.0.1:6000", optional_yield{io, yield})); + dir->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "testBucket_testName_0"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + conn->cancel(); }); - client.flushall(); + io.run(); } int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); - /* Other ports can be passed to the program */ - if (argc == 1) { - portStr = "6379"; - hostStr = "127.0.0.1"; - } else if (argc == 3) { - hostStr = argv[1]; - portStr = argv[2]; - } else { - cout << "Incorrect number of arguments." << std::endl; - return -1; - } - - redisHost = hostStr + ":" + portStr; + env = new Environment(); + ::testing::AddGlobalTestEnvironment(env); return RUN_ALL_TESTS(); } diff --git a/src/test/rgw/test_d4n_filter.cc b/src/test/rgw/test_d4n_filter.cc deleted file mode 100644 index b5c382c119e6a..0000000000000 --- a/src/test/rgw/test_d4n_filter.cc +++ /dev/null @@ -1,2132 +0,0 @@ -#include "gtest/gtest.h" -#include "common/ceph_context.h" -#include -#include -#include "rgw_process_env.h" -#include -#include "driver/dbstore/common/dbstore.h" -#include "rgw_sal_store.h" -#include "../../rgw/driver/d4n/rgw_sal_d4n.h" // fix -Sam - -#include "rgw_sal.h" -#include "rgw_auth.h" -#include "rgw_auth_registry.h" -#include "driver/rados/rgw_zone.h" -#include "rgw_sal_config.h" - -#include - -#define dout_subsys ceph_subsys_rgw - -#define METADATA_LENGTH 22 - -using namespace std; - -string portStr; -string hostStr; -string redisHost = ""; - -vector args; -class Environment* env; -const DoutPrefixProvider* dpp; -const req_context rctx{dpp, null_yield, nullptr}; - -class StoreObject : public rgw::sal::StoreObject { - friend class D4NFilterFixture; - FRIEND_TEST(D4NFilterFixture, StoreGetMetadata); -}; - -class Environment : public ::testing::Environment { - boost::asio::io_context ioc; - public: - Environment() {} - - virtual ~Environment() {} - - void SetUp() override { - /* Ensure redis instance is running */ - try { - env_client.connect(hostStr, stoi(portStr), nullptr, 0, 5, 1000); - } catch (std::exception &e) { - std::cerr << "[ ] ERROR: Redis instance not running." << std::endl; - } - - ASSERT_EQ((bool)env_client.is_connected(), (bool)1); - - /* Proceed with environment setup */ - cct = global_init(nullptr, args, CEPH_ENTITY_TYPE_CLIENT, - CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_MON_CONFIG); - - dpp = new DoutPrefix(cct->get(), dout_subsys, "d4n test: "); - DriverManager::Config cfg; - - cfg.store_name = "dbstore"; - cfg.filter_name = "d4n"; - auto config_store_type = g_conf().get_val("rgw_config_store"); - std::unique_ptr cfgstore - = DriverManager::create_config_store(dpp, config_store_type); - ASSERT_TRUE(cfgstore); - rgw::SiteConfig site; - auto r = site.load(dpp, null_yield, cfgstore.get()); - ASSERT_GT(r, 0); - - driver = DriverManager::get_storage(dpp, dpp->get_cct(), - cfg, - ioc, - site, - false, - false, - false, - false, - false, - false, null_yield, - false); - - ASSERT_NE(driver, nullptr); - } - - void TearDown() override { - if (env_client.is_connected()) { - delete driver; - delete dpp; - - env_client.disconnect(); - } - } - - boost::intrusive_ptr cct; - rgw::sal::Driver* driver; - cpp_redis::client env_client; -}; - -class D4NFilterFixture : public ::testing::Test { - protected: - rgw::sal::Driver* driver; - unique_ptr testUser = nullptr; - unique_ptr testBucket = nullptr; - unique_ptr testWriter = nullptr; - - public: - D4NFilterFixture() {} - - void SetUp() { - driver = env->driver; - } - - void TearDown() {} - - int createUser() { - rgw_user u("test_tenant", "test_user", "ns"); - - testUser = driver->get_user(u); - testUser->get_info().user_id = u; - - int ret = testUser->store_user(dpp, null_yield, false); - - return ret; - } - - int createBucket() { - RGWBucketInfo info; - info.bucket.name = "test_bucket"; - - testBucket = driver->get_bucket(info); - - rgw::sal::Bucket::CreateParams params; - params.zonegroup_id = "test_id"; - params.placement_rule.storage_class = "test_sc"; - params.swift_ver_location = "test_location"; - - return testBucket->create(dpp, params, null_yield); - } - - int putObject(string name) { - string object_name = "test_object_" + name; - unique_ptr obj = testBucket->get_object(rgw_obj_key(object_name)); - rgw_user owner; - rgw_placement_rule ptail_placement_rule; - uint64_t olh_epoch = 123; - string unique_tag; - - obj->get_obj_attrs(null_yield, dpp); - - testWriter = driver->get_atomic_writer(dpp, - null_yield, - obj.get(), - owner, - &ptail_placement_rule, - olh_epoch, - unique_tag); - - size_t accounted_size = 4; - string etag("test_etag"); - ceph::real_time mtime; - ceph::real_time set_mtime; - - buffer::list bl; - string tmp = "test_attrs_value_" + name; - bl.append("test_attrs_value_" + name); - map attrs{{"test_attrs_key_" + name, bl}}; - - ceph::real_time delete_at; - char if_match; - char if_nomatch; - string user_data; - rgw_zone_set zones_trace; - bool canceled; - - int ret = testWriter->prepare(null_yield); - - if (!ret) { - ret = testWriter->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - rctx, rgw::sal::FLAG_LOG_OP); - - return ret; - } - - void clientSetUp(cpp_redis::client* client) { - client->connect(hostStr, stoi(portStr), nullptr, 0, 5, 1000); - ASSERT_EQ((bool)client->is_connected(), (bool)1); - - client->flushdb([](cpp_redis::reply& reply) {}); - client->sync_commit(); - } - - void clientReset(cpp_redis::client* client) { - client->flushdb([](cpp_redis::reply& reply) {}); - client->sync_commit(); - } -}; - -/* General operation-related tests */ -TEST_F(D4NFilterFixture, CreateUser) { - EXPECT_EQ(createUser(), 0); - EXPECT_NE(testUser, nullptr); -} - -TEST_F(D4NFilterFixture, CreateBucket) { - ASSERT_EQ(createUser(), 0); - ASSERT_NE(testUser, nullptr); - - EXPECT_EQ(createBucket(), 0); - EXPECT_NE(testBucket, nullptr); -} - -TEST_F(D4NFilterFixture, PutObject) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_PutObject"); - clientSetUp(&client); - - ASSERT_EQ(createUser(), 0); - ASSERT_NE(testUser, nullptr); - - ASSERT_EQ(createBucket(), 0); - ASSERT_NE(testBucket, nullptr); - - EXPECT_EQ(putObject("PutObject"), 0); - EXPECT_NE(testWriter, nullptr); - - client.hgetall("rgw-object:test_object_PutObject:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_PutObject:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_PutObject"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, GetObject) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_GetObject"); - clientSetUp(&client); - - ASSERT_EQ(createUser(), 0); - ASSERT_NE(testUser, nullptr); - - ASSERT_EQ(createBucket(), 0); - ASSERT_NE(testBucket, nullptr); - - ASSERT_EQ(putObject("GetObject"), 0); - ASSERT_NE(testWriter, nullptr); - - unique_ptr testObject_GetObject = testBucket->get_object(rgw_obj_key("test_object_GetObject")); - - EXPECT_NE(testObject_GetObject, nullptr); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_GetObject.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - unique_ptr testROp = testObject_GetObject->get_read_op(); - - EXPECT_NE(testROp, nullptr); - EXPECT_EQ(testROp->prepare(null_yield, dpp), 0); - - client.hgetall("rgw-object:test_object_GetObject:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_GetObject:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_GetObject"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, CopyObjectNone) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_CopyObjectNone"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("CopyObjectNone"); - unique_ptr testObject_CopyObjectNone = testBucket->get_object(rgw_obj_key("test_object_CopyObjectNone")); - - ASSERT_NE(testObject_CopyObjectNone, nullptr); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_CopyObjectNone.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Update object */ - RGWEnv rgw_env; - req_info info(get_pointer(env->cct), &rgw_env); - rgw_zone_id source_zone; - rgw_placement_rule dest_placement; - ceph::real_time src_mtime; - ceph::real_time mtime; - ceph::real_time mod_ptr; - ceph::real_time unmod_ptr; - char if_match; - char if_nomatch; - rgw::sal::AttrsMod attrs_mod = rgw::sal::ATTRSMOD_NONE; - rgw::sal::Attrs attrs; - RGWObjCategory category = RGWObjCategory::Main; - uint64_t olh_epoch = 0; - ceph::real_time delete_at; - string tag; - string etag; - - EXPECT_EQ(testObject_CopyObjectNone->copy_object(testUser.get(), - &info, source_zone, testObject_CopyObjectNone.get(), - testBucket.get(), testBucket.get(), - dest_placement, &src_mtime, &mtime, - &mod_ptr, &unmod_ptr, false, - &if_match, &if_nomatch, attrs_mod, - false, attrs, category, olh_epoch, - delete_at, NULL, &tag, &etag, - NULL, NULL, dpp, null_yield), 0); - - client.hgetall("rgw-object:test_object_CopyObjectNone:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_CopyObjectNone:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_CopyObjectNone"); - } - }); - - client.sync_commit(); -} - -TEST_F(D4NFilterFixture, CopyObjectReplace) { - cpp_redis::client client; - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("CopyObjectReplace"); - unique_ptr testObject_CopyObjectReplace = testBucket->get_object(rgw_obj_key("test_object_CopyObjectReplace")); - - ASSERT_NE(testObject_CopyObjectReplace, nullptr); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_CopyObjectReplace.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Copy to new object */ - unique_ptr testWriterCopy = nullptr; - unique_ptr obj = testBucket->get_object(rgw_obj_key("test_object_copy")); - rgw_user owner; - rgw_placement_rule ptail_placement_rule; - uint64_t olh_epoch_copy = 123; - string unique_tag; - - obj->get_obj_attrs(null_yield, dpp); - - testWriterCopy = driver->get_atomic_writer(dpp, - null_yield, - obj.get(), - owner, - &ptail_placement_rule, - olh_epoch_copy, - unique_tag); - - RGWEnv rgw_env; - size_t accounted_size = 0; - req_info info(get_pointer(env->cct), &rgw_env); - rgw_zone_id source_zone; - rgw_placement_rule dest_placement; - ceph::real_time src_mtime; - ceph::real_time mtime; - ceph::real_time set_mtime; - ceph::real_time mod_ptr; - ceph::real_time unmod_ptr; - rgw::sal::AttrsMod attrs_mod = rgw::sal::ATTRSMOD_REPLACE; - char if_match; - char if_nomatch; - RGWObjCategory category = RGWObjCategory::Main; - uint64_t olh_epoch = 0; - ceph::real_time delete_at; - string tag; - string etag("test_etag_copy"); - - /* Attribute to replace */ - buffer::list bl; - bl.append("test_attrs_copy_value"); - rgw::sal::Attrs attrs{{"test_attrs_key_CopyObjectReplace", bl}}; - - string user_data; - rgw_zone_set zones_trace; - bool canceled; - - ASSERT_EQ(testWriterCopy->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - rctx, rgw::sal::FLAG_LOG_OP), 0); - - unique_ptr testObject_copy = testBucket->get_object(rgw_obj_key("test_object_copy")); - - EXPECT_EQ(testObject_CopyObjectReplace->copy_object(testUser.get(), - &info, source_zone, testObject_copy.get(), - testBucket.get(), testBucket.get(), - dest_placement, &src_mtime, &mtime, - &mod_ptr, &unmod_ptr, false, - &if_match, &if_nomatch, attrs_mod, - false, attrs, category, olh_epoch, - delete_at, NULL, &tag, &etag, - NULL, NULL, dpp, null_yield), 0); - - /* Ensure the original object is still in the cache */ - vector keys; - keys.push_back("rgw-object:test_object_CopyObjectReplace:cache"); - - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 1); - } - }); - - client.sync_commit(); - - /* Retrieve original object's redis data for later comparison */ - std::vector< std::pair > data; - - client.hgetall("rgw-object:test_object_CopyObjectReplace:cache", [&data](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - for (int i = 0; i < (int)arr.size() - 1; i += 2) { - data.push_back({arr[i].as_string(), arr[i + 1].as_string()}); - } - } - }); - - client.sync_commit(); - - /* Check copy */ - client.hgetall("rgw-object:test_object_copy:cache", [&data](cpp_redis::reply& reply) { - bool unexpected = false; - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 4 + METADATA_LENGTH); /* With etag */ - - for (int i = 0; i < (int)arr.size() - 1; i += 2) { - auto it = std::find_if(data.begin(), data.end(), - [&](const auto& pair) { return pair.first == arr[i].as_string(); }); - - if (it != data.end()) { - if (arr[i].as_string() == "test_attrs_key_CopyObjectReplace") - EXPECT_EQ(arr[i + 1].as_string(), "test_attrs_copy_value"); - else if (arr[i].as_string() != "mtime") { /* mtime will be different */ - int index = std::distance(data.begin(), it); - EXPECT_EQ(arr[i + 1].as_string(), data[index].second); - } - } else if (arr[i].as_string() == "etag") { - EXPECT_EQ(arr[i + 1].as_string(), "test_etag_copy"); - } else - unexpected = true; /* Unexpected field */ - } - - EXPECT_EQ(unexpected, false); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, CopyObjectMerge) { - cpp_redis::client client; - vector fields; - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("CopyObjectMerge"); - unique_ptr testObject_CopyObjectMerge = testBucket->get_object(rgw_obj_key("test_object_CopyObjectMerge")); - - ASSERT_NE(testObject_CopyObjectMerge, nullptr); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_CopyObjectMerge.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Copy to new object */ - unique_ptr testWriterCopy = nullptr; - string object_name = "test_object_copy"; - unique_ptr obj = testBucket->get_object(rgw_obj_key(object_name)); - rgw_user owner; - rgw_placement_rule ptail_placement_rule; - uint64_t olh_epoch_copy = 123; - string unique_tag; - - obj->get_obj_attrs(null_yield, dpp); - - testWriterCopy = driver->get_atomic_writer(dpp, - null_yield, - obj.get(), - owner, - &ptail_placement_rule, - olh_epoch_copy, - unique_tag); - - RGWEnv rgw_env; - size_t accounted_size = 4; - req_info info(get_pointer(env->cct), &rgw_env); - rgw_zone_id source_zone; - rgw_placement_rule dest_placement; - ceph::real_time src_mtime; - ceph::real_time mtime; - ceph::real_time set_mtime; - ceph::real_time mod_ptr; - ceph::real_time unmod_ptr; - rgw::sal::AttrsMod attrs_mod = rgw::sal::ATTRSMOD_MERGE; - char if_match; - char if_nomatch; - RGWObjCategory category = RGWObjCategory::Main; - uint64_t olh_epoch = 0; - ceph::real_time delete_at; - string tag; - string etag("test_etag_copy"); - - buffer::list bl; - bl.append("bad_value"); - rgw::sal::Attrs attrs{{"test_attrs_key_CopyObjectMerge", bl}}; /* Existing attr */ - bl.clear(); - bl.append("test_attrs_copy_extra_value"); - attrs.insert({"test_attrs_copy_extra_key", bl}); /* New attr */ - - string user_data; - rgw_zone_set zones_trace; - bool canceled; - - ASSERT_EQ(testWriterCopy->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - rctx, rgw::sal::FLAG_LOG_OP), 0); - - unique_ptr testObject_copy = testBucket->get_object(rgw_obj_key("test_object_copy")); - - EXPECT_EQ(testObject_CopyObjectMerge->copy_object(testUser.get(), - &info, source_zone, testObject_copy.get(), - testBucket.get(), testBucket.get(), - dest_placement, &src_mtime, &mtime, - &mod_ptr, &unmod_ptr, false, - &if_match, &if_nomatch, attrs_mod, - false, attrs, category, olh_epoch, - delete_at, NULL, &tag, &etag, - NULL, NULL, dpp, null_yield), 0); - - /* Ensure the original object is still in the cache */ - vector keys; - keys.push_back("rgw-object:test_object_CopyObjectMerge:cache"); - - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 1); - } - }); - - client.sync_commit(); - - /* Retrieve original object's redis data for later comparison */ - std::vector< std::pair > data; - - client.hgetall("rgw-object:test_object_CopyObjectMerge:cache", [&data](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - for (int i = 0; i < (int)arr.size() - 1; i += 2) { - data.push_back({arr[i].as_string(), arr[i + 1].as_string()}); - } - } - }); - - client.sync_commit(); - - /* Check copy */ - client.hgetall("rgw-object:test_object_copy:cache", [&data](cpp_redis::reply& reply) { - bool unexpected = false; - bool merge = false; - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 6 + METADATA_LENGTH); /* With etag */ - - for (int i = 0; i < (int)arr.size() - 1; i += 2) { - auto it = std::find_if(data.begin(), data.end(), - [&](const auto& pair) { return pair.first == arr[i].as_string(); }); - - if (it != data.end()) { - if (arr[i].as_string() == "test_attrs_key_CopyObjectMerge") - EXPECT_EQ(arr[i + 1].as_string(), "test_attrs_value_CopyObjectMerge"); - else if (arr[i].as_string() != "mtime") { /* mtime will be different */ - int index = std::distance(data.begin(), it); - EXPECT_EQ(arr[i + 1].as_string(), data[index].second); - } - } else if (arr[i].as_string() == "etag") { - EXPECT_EQ(arr[i + 1].as_string(), "test_etag_copy"); - } else if (arr[i].as_string() == "test_attrs_copy_extra_key") { - merge = true; - EXPECT_EQ(arr[i + 1].as_string(), "test_attrs_copy_extra_value"); - } else - unexpected = true; /* Unexpected field */ - } - - EXPECT_EQ(unexpected, false); - EXPECT_EQ(merge, true); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelObject) { - cpp_redis::client client; - vector keys; - keys.push_back("rgw-object:test_object_DelObject:cache"); - clientSetUp(&client); - - ASSERT_EQ(createUser(), 0); - ASSERT_NE(testUser, nullptr); - - ASSERT_EQ(createBucket(), 0); - ASSERT_NE(testBucket, nullptr); - - ASSERT_EQ(putObject("DelObject"), 0); - ASSERT_NE(testWriter, nullptr); - - /* Check the object exists before delete op */ - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 1); - } - }); - - client.sync_commit(); - - unique_ptr testObject_DelObject = testBucket->get_object(rgw_obj_key("test_object_DelObject")); - - EXPECT_NE(testObject_DelObject, nullptr); - - unique_ptr testDOp = testObject_DelObject->get_delete_op(); - - EXPECT_NE(testDOp, nullptr); - EXPECT_EQ(testDOp->delete_obj(dpp, null_yield, true), 0); - - /* Check the object does not exist after delete op */ - client.exists(keys, [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 0); /* Zero keys exist */ - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, CachePolicy) { - cpp_redis::client client; - clientSetUp(&client); - - createUser(); - createBucket(); - - /* Create multipart object */ - string object_name = "test_object_CachePolicy"; - unique_ptr obj = testBucket->get_object(rgw_obj_key(object_name)); - rgw_user owner; - rgw_placement_rule ptail_placement_rule; - uint64_t olh_epoch = 123; - string unique_tag; - - obj->get_obj_attrs(null_yield, dpp); - - testWriter = driver->get_atomic_writer(dpp, - null_yield, - obj.get(), - owner, - &ptail_placement_rule, - olh_epoch, - unique_tag); - - size_t accounted_size = 15; /* Uploaded as multipart */ - string etag("test_etag"); - ceph::real_time mtime; - ceph::real_time set_mtime; - - buffer::list bl; - string tmp = "test_attrs_value_CachePolicy"; - bl.append("test_attrs_value_CachePolicy"); - map attrs{{"test_attrs_key_CachePolicy", bl}}; - - ceph::real_time delete_at; - char if_match; - char if_nomatch; - string user_data; - rgw_zone_set zones_trace; - bool canceled; - - ASSERT_EQ(testWriter->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - null_yield), 0); - - - unique_ptr testObject_CachePolicy = testBucket->get_object(rgw_obj_key("test_object_CachePolicy")); - - ASSERT_NE(testObject_CachePolicy, nullptr); - - /* Copy to new multipart object */ - unique_ptr testWriterCopy = nullptr; - unique_ptr obj_copy = testBucket->get_object(rgw_obj_key("test_object_copy")); - uint64_t olh_epoch_copy = 123; - - obj_copy->get_obj_attrs(null_yield, dpp); - - testWriterCopy = driver->get_atomic_writer(dpp, - null_yield, - obj_copy.get(), - owner, - &ptail_placement_rule, - olh_epoch_copy, - unique_tag); - - RGWEnv rgw_env; - req_info info(get_pointer(env->cct), &rgw_env); - rgw_zone_id source_zone; - rgw_placement_rule dest_placement; - ceph::real_time src_mtime; - ceph::real_time mod_ptr; - ceph::real_time unmod_ptr; - rgw::sal::AttrsMod attrs_mod = rgw::sal::ATTRSMOD_REPLACE; - RGWObjCategory category = RGWObjCategory::Main; - string tag; - - ASSERT_EQ(testWriterCopy->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - null_yield), 0); - - unique_ptr testObject_copy = testBucket->get_object(rgw_obj_key("test_object_copy")); - - EXPECT_EQ(testObject_CachePolicy->copy_object(testUser.get(), - &info, source_zone, testObject_copy.get(), - testBucket.get(), testBucket.get(), - dest_placement, &src_mtime, &mtime, - &mod_ptr, &unmod_ptr, false, - &if_match, &if_nomatch, attrs_mod, - false, attrs, category, olh_epoch, - delete_at, NULL, &tag, &etag, - NULL, NULL, dpp, null_yield), 0); - - /* Ensure data field doesn't exist for original object */ - client.hexists("rgw-object:test_object_CachePolicy:cache", "data", [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 0); - } - }); - - client.sync_commit(); - - /* Ensure data field doesn't exist for copy */ - client.hexists("rgw-object:test_object_CachePolicy:cache", "data", [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 0); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -/* Attribute-related tests */ -TEST_F(D4NFilterFixture, SetObjectAttrs) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_SetObjectAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("SetObjectAttrs"); - unique_ptr testObject_SetObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_SetObjectAttrs")); - - ASSERT_NE(testObject_SetObjectAttrs, nullptr); - - buffer::list bl; - bl.append("test_attrs_value_extra"); - map test_attrs{{"test_attrs_key_extra", bl}}; - fields.push_back("test_attrs_key_extra"); - - EXPECT_EQ(testObject_SetObjectAttrs->set_obj_attrs(dpp, &test_attrs, NULL, null_yield), 0); - - client.hgetall("rgw-object:test_object_SetObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 4 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_SetObjectAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_SetObjectAttrs"); - EXPECT_EQ(arr[1].as_string(), "test_attrs_value_extra"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, GetObjectAttrs) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_GetObjectAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("GetObjectAttrs"); - unique_ptr testObject_GetObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_GetObjectAttrs")); - - ASSERT_NE(testObject_GetObjectAttrs, nullptr); - - buffer::list bl; - bl.append("test_attrs_value_extra"); - map test_attrs{{"test_attrs_key_extra", bl}}; - fields.push_back("test_attrs_key_extra"); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_GetObjectAttrs.get())->get_next(); - - ASSERT_EQ(testObject_GetObjectAttrs->set_obj_attrs(dpp, &test_attrs, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - EXPECT_EQ(testObject_GetObjectAttrs->get_obj_attrs(null_yield, dpp, NULL), 0); - - client.hgetall("rgw-object:test_object_GetObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 4 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_GetObjectAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_GetObjectAttrs"); - EXPECT_EQ(arr[1].as_string(), "test_attrs_value_extra"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelObjectAttrs) { - cpp_redis::client client; - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("DelObjectAttrs"); - unique_ptr testObject_DelObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_DelObjectAttrs")); - - ASSERT_NE(testObject_DelObjectAttrs, nullptr); - - buffer::list bl; - bl.append("test_attrs_value_extra"); - map test_attrs{{"test_attrs_key_extra", bl}}; - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_DelObjectAttrs.get())->get_next(); - - ASSERT_EQ(testObject_DelObjectAttrs->set_obj_attrs(dpp, &test_attrs, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Check that the attributes exist before deletion */ - client.hgetall("rgw-object:test_object_DelObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 4 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - EXPECT_EQ(testObject_DelObjectAttrs->set_obj_attrs(dpp, NULL, &test_attrs, null_yield), 0); - - /* Check that the attribute does not exist after deletion */ - client.hgetall("rgw-object:test_object_DelObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hexists("rgw-object:test_object_DelObjectAttrs:cache", "test_attrs_key_extra", [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 0); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, SetLongObjectAttrs) { - cpp_redis::client client; - map test_attrs_long; - vector fields; - fields.push_back("test_attrs_key_SetLongObjectAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("SetLongObjectAttrs"); - unique_ptr testObject_SetLongObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_SetLongObjectAttrs")); - - ASSERT_NE(testObject_SetLongObjectAttrs, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_long.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - EXPECT_EQ(testObject_SetLongObjectAttrs->set_obj_attrs(dpp, &test_attrs_long, NULL, null_yield), 0); - - client.hgetall("rgw-object:test_object_SetLongObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_SetLongObjectAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_SetLongObjectAttrs"); - - for (int i = 1; i < 11; ++i) { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, GetLongObjectAttrs) { - cpp_redis::client client; - map test_attrs_long; - vector fields; - fields.push_back("test_attrs_key_GetLongObjectAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("GetLongObjectAttrs"); - unique_ptr testObject_GetLongObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_GetLongObjectAttrs")); - - ASSERT_NE(testObject_GetLongObjectAttrs, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_long.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_GetLongObjectAttrs.get())->get_next(); - - ASSERT_EQ(testObject_GetLongObjectAttrs->set_obj_attrs(dpp, &test_attrs_long, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - EXPECT_EQ(testObject_GetLongObjectAttrs->get_obj_attrs(null_yield, dpp, NULL), 0); - - client.hgetall("rgw-object:test_object_GetLongObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_GetLongObjectAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_GetLongObjectAttrs"); - - for (int i = 1; i < 11; ++i) { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, ModifyObjectAttr) { - cpp_redis::client client; - map test_attrs_long; - vector fields; - fields.push_back("test_attrs_key_ModifyObjectAttr"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("ModifyObjectAttr"); - unique_ptr testObject_ModifyObjectAttr = testBucket->get_object(rgw_obj_key("test_object_ModifyObjectAttr")); - - ASSERT_NE(testObject_ModifyObjectAttr, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_long.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_ModifyObjectAttr.get())->get_next(); - - ASSERT_EQ(testObject_ModifyObjectAttr->set_obj_attrs(dpp, &test_attrs_long, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - buffer::list bl_tmp; - string tmp_value = "new_test_attrs_value_extra_5"; - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - EXPECT_EQ(testObject_ModifyObjectAttr->modify_obj_attrs("test_attrs_key_extra_5", bl_tmp, null_yield, dpp), 0); - - client.hgetall("rgw-object:test_object_ModifyObjectAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_ModifyObjectAttr:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_ModifyObjectAttr"); - - for (int i = 1; i < 11; ++i) { - if (i == 6) { - EXPECT_EQ(arr[i].as_string(), "new_test_attrs_value_extra_" + to_string(i - 1)); - } else { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelLongObjectAttrs) { - cpp_redis::client client; - map test_attrs_long; - vector fields; - fields.push_back("test_attrs_key_DelLongObjectAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("DelLongObjectAttrs"); - unique_ptr testObject_DelLongObjectAttrs = testBucket->get_object(rgw_obj_key("test_object_DelLongObjectAttrs")); - - ASSERT_NE(testObject_DelLongObjectAttrs, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_long.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_DelLongObjectAttrs.get())->get_next(); - - ASSERT_EQ(testObject_DelLongObjectAttrs->set_obj_attrs(dpp, &test_attrs_long, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Check that the attributes exist before deletion */ - client.hgetall("rgw-object:test_object_DelLongObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - EXPECT_EQ(testObject_DelLongObjectAttrs->set_obj_attrs(dpp, NULL, &test_attrs_long, null_yield), 0); - - /* Check that the attributes do not exist after deletion */ - client.hgetall("rgw-object:test_object_DelLongObjectAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - - for (int i = 0; i < (int)arr.size(); ++i) { - EXPECT_EQ((int)arr[i].as_string().find("extra"), -1); - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelObjectAttr) { - cpp_redis::client client; - map test_attrs_long; - vector fields; - fields.push_back("test_attrs_key_DelObjectAttr"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("DelObjectAttr"); - unique_ptr testObject_DelObjectAttr = testBucket->get_object(rgw_obj_key("test_object_DelObjectAttr")); - - ASSERT_NE(testObject_DelObjectAttr, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_long.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_DelObjectAttr.get())->get_next(); - - ASSERT_EQ(testObject_DelObjectAttr->set_obj_attrs(dpp, &test_attrs_long, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Check that the attribute exists before deletion */ - client.hgetall("rgw-object:test_object_DelObjectAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - EXPECT_EQ(testObject_DelObjectAttr->delete_obj_attrs(dpp, "test_attrs_key_extra_5", null_yield), 0); - - /* Check that the attribute does not exist after deletion */ - client.hgetall("rgw-object:test_object_DelObjectAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 20 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hexists("rgw-object:test_object_DelObjectAttr:cache", "test_attrs_key_extra_5", [](cpp_redis::reply& reply) { - if (reply.is_integer()) { - EXPECT_EQ(reply.as_integer(), 0); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -/* Edge cases */ -TEST_F(D4NFilterFixture, PrepareCopyObject) { - cpp_redis::client client; - vector fields; - fields.push_back("test_attrs_key_PrepareCopyObject"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("PrepareCopyObject"); - unique_ptr testObject_PrepareCopyObject = testBucket->get_object(rgw_obj_key("test_object_PrepareCopyObject")); - - ASSERT_NE(testObject_PrepareCopyObject, nullptr); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_PrepareCopyObject.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - unique_ptr testROp = testObject_PrepareCopyObject->get_read_op(); - - ASSERT_NE(testROp, nullptr); - ASSERT_EQ(testROp->prepare(null_yield, dpp), 0); - - /* Update object */ - RGWEnv rgw_env; - req_info info(get_pointer(env->cct), &rgw_env); - rgw_zone_id source_zone; - rgw_placement_rule dest_placement; - ceph::real_time src_mtime; - ceph::real_time mtime; - ceph::real_time mod_ptr; - ceph::real_time unmod_ptr; - char if_match; - char if_nomatch; - rgw::sal::AttrsMod attrs_mod = rgw::sal::ATTRSMOD_NONE; - rgw::sal::Attrs attrs; - RGWObjCategory category = RGWObjCategory::Main; - uint64_t olh_epoch = 0; - ceph::real_time delete_at; - string tag; - string etag; - - EXPECT_EQ(testObject_PrepareCopyObject->copy_object(testUser.get(), - &info, source_zone, testObject_PrepareCopyObject.get(), - testBucket.get(), testBucket.get(), - dest_placement, &src_mtime, &mtime, - &mod_ptr, &unmod_ptr, false, - &if_match, &if_nomatch, attrs_mod, - false, attrs, category, olh_epoch, - delete_at, NULL, &tag, &etag, - NULL, NULL, dpp, null_yield), 0); - - client.hgetall("rgw-object:test_object_PrepareCopyObject:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_PrepareCopyObject:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_PrepareCopyObject"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, SetDelAttrs) { - cpp_redis::client client; - map test_attrs_base; - vector fields; - fields.push_back("test_attrs_key_SetDelAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("SetDelAttrs"); - unique_ptr testObject_SetDelAttrs = testBucket->get_object(rgw_obj_key("test_object_SetDelAttrs")); - - ASSERT_NE(testObject_SetDelAttrs, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_SetDelAttrs.get())->get_next(); - - ASSERT_EQ(testObject_SetDelAttrs->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Attempt to set and delete attrs with the same API call */ - buffer::list bl; - bl.append("test_attrs_value_extra"); - map test_attrs_new{{"test_attrs_key_extra", bl}}; - fields.push_back("test_attrs_key_extra"); - - EXPECT_EQ(testObject_SetDelAttrs->set_obj_attrs(dpp, &test_attrs_new, &test_attrs_base, null_yield), 0); - - client.hgetall("rgw-object:test_object_SetDelAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 4 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_SetDelAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_SetDelAttrs"); - EXPECT_EQ(arr[1].as_string(), "test_attrs_value_extra"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, ModifyNonexistentAttr) { - cpp_redis::client client; - map test_attrs_base; - vector fields; - fields.push_back("test_attrs_key_ModifyNonexistentAttr"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("ModifyNonexistentAttr"); - unique_ptr testObject_ModifyNonexistentAttr = testBucket->get_object(rgw_obj_key("test_object_ModifyNonexistentAttr")); - - ASSERT_NE(testObject_ModifyNonexistentAttr, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_ModifyNonexistentAttr.get())->get_next(); - - ASSERT_EQ(testObject_ModifyNonexistentAttr->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - buffer::list bl_tmp; - bl_tmp.append("new_test_attrs_value_extra_ModifyNonexistentAttr"); - - EXPECT_EQ(testObject_ModifyNonexistentAttr->modify_obj_attrs("test_attrs_key_extra_ModifyNonexistentAttr", bl_tmp, null_yield, dpp), 0); - - fields.push_back("test_attrs_key_extra_ModifyNonexistentAttr"); - - client.hgetall("rgw-object:test_object_ModifyNonexistentAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 24 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_ModifyNonexistentAttr:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_ModifyNonexistentAttr"); - - for (int i = 1; i < 11; ++i) { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - - /* New attribute will be created and stored since it was not found in the existing attributes */ - EXPECT_EQ(arr[11].as_string(), "new_test_attrs_value_extra_ModifyNonexistentAttr"); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, ModifyGetAttrs) { - cpp_redis::client client; - map test_attrs_base; - vector fields; - fields.push_back("test_attrs_key_ModifyGetAttrs"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("ModifyGetAttrs"); - unique_ptr testObject_ModifyGetAttrs = testBucket->get_object(rgw_obj_key("test_object_ModifyGetAttrs")); - - ASSERT_NE(testObject_ModifyGetAttrs, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_ModifyGetAttrs.get())->get_next(); - - ASSERT_EQ(testObject_ModifyGetAttrs->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Attempt to get immediately after a modification */ - buffer::list bl_tmp; - bl_tmp.append("new_test_attrs_value_extra_5"); - - ASSERT_EQ(testObject_ModifyGetAttrs->modify_obj_attrs("test_attrs_key_extra_5", bl_tmp, null_yield, dpp), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - EXPECT_EQ(testObject_ModifyGetAttrs->get_obj_attrs(null_yield, dpp, NULL), 0); - - client.hgetall("rgw-object:test_object_ModifyGetAttrs:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_ModifyGetAttrs:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_ModifyGetAttrs"); - - for (int i = 1; i < 11; ++i) { - if (i == 6) { - EXPECT_EQ(arr[i].as_string(), "new_test_attrs_value_extra_5"); - } else { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelNonexistentAttr) { - cpp_redis::client client; - map test_attrs_base; - vector fields; - fields.push_back("test_attrs_key_DelNonexistentAttr"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("DelNonexistentAttr"); - unique_ptr testObject_DelNonexistentAttr = testBucket->get_object(rgw_obj_key("test_object_DelNonexistentAttr")); - - ASSERT_NE(testObject_DelNonexistentAttr, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - fields.push_back(tmp_key); - } - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_DelNonexistentAttr.get())->get_next(); - - ASSERT_EQ(testObject_DelNonexistentAttr->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield), 0); - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Attempt to delete an attribute that does not exist */ - ASSERT_EQ(testObject_DelNonexistentAttr->delete_obj_attrs(dpp, "test_attrs_key_extra_12", null_yield), 0); - - client.hgetall("rgw-object:test_object_DelNonexistentAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 22 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - client.hmget("rgw-object:test_object_DelNonexistentAttr:cache", fields, [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ(arr[0].as_string(), "test_attrs_value_DelNonexistentAttr"); - - for (int i = 1; i < 11; ++i) { - EXPECT_EQ(arr[i].as_string(), "test_attrs_value_extra_" + to_string(i - 1)); - } - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, DelSetWithNonexisentAttr) { - cpp_redis::client client; - map test_attrs_base; - vector fields; - fields.push_back("test_attrs_key_DelSetWithNonexistentAttr"); - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("DelSetWithNonexistentAttr"); - unique_ptr testObject_DelSetWithNonexistentAttr = testBucket->get_object(rgw_obj_key("test_object_DelSetWithNonexistentAttr")); - - ASSERT_NE(testObject_DelSetWithNonexistentAttr, nullptr); - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - } - - ASSERT_EQ(testObject_DelSetWithNonexistentAttr->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield), 0); - - static rgw::sal::Object* nextObject = dynamic_cast(testObject_DelSetWithNonexistentAttr.get())->get_next(); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - EXPECT_EQ(testObject_DelSetWithNonexistentAttr->delete_obj_attrs(dpp, "test_attrs_key_extra_5", null_yield), 0); - - /* Attempt to delete a set of attrs, including one that does not exist */ - EXPECT_EQ(testObject_DelSetWithNonexistentAttr->set_obj_attrs(dpp, NULL, &test_attrs_base, null_yield), 0); - - client.hgetall("rgw-object:test_object_DelSetWithNonexistentAttr:cache", [](cpp_redis::reply& reply) { - auto arr = reply.as_array(); - - if (!arr[0].is_null()) { - EXPECT_EQ((int)arr.size(), 2 + METADATA_LENGTH); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -/* Underlying store attribute check */ -TEST_F(D4NFilterFixture, StoreSetAttr) { - createUser(); - createBucket(); - putObject("StoreSetAttr"); - unique_ptr testObject_StoreSetAttr = testBucket->get_object(rgw_obj_key("test_object_StoreSetAttr")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreSetAttr.get())->get_next(); - - EXPECT_NE(nextObject, nullptr); - - /* Set one attribute */ - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - ASSERT_NE(nextObject->get_attrs().empty(), true); - - /* Check the attribute */ - rgw::sal::Attrs driverAttrs = nextObject->get_attrs(); - pair value(driverAttrs.begin()->first, driverAttrs.begin()->second.to_str()); - - EXPECT_EQ(value, make_pair(string("test_attrs_key_StoreSetAttr"), string("test_attrs_value_StoreSetAttr"))); -} - -TEST_F(D4NFilterFixture, StoreSetAttrs) { - createUser(); - createBucket(); - putObject("StoreSetAttrs"); - unique_ptr testObject_StoreSetAttrs = testBucket->get_object(rgw_obj_key("test_object_StoreSetAttrs")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreSetAttrs.get())->get_next(); - - EXPECT_NE(nextObject, nullptr); - - /* Delete base attribute for easier comparison */ - testObject_StoreSetAttrs->delete_obj_attrs(dpp, "test_attrs_key_StoreSetAttrs", null_yield); - - /* Set more attributes */ - map test_attrs_base; - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - } - - testObject_StoreSetAttrs->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Check the attributes */ - rgw::sal::Attrs driverAttrs = nextObject->get_attrs(); - rgw::sal::Attrs::iterator attrs; - vector< pair > values; - - for (attrs = driverAttrs.begin(); attrs != driverAttrs.end(); ++attrs) { - values.push_back(make_pair(attrs->first, attrs->second.to_str())); - } - - int i = 0; - - for (const auto& pair : values) { - string tmp_key = "test_attrs_key_extra_" + to_string(i); - string tmp_value = "test_attrs_value_extra_" + to_string(i); - - EXPECT_EQ(pair, make_pair(tmp_key, tmp_value)); - ++i; - } -} - -TEST_F(D4NFilterFixture, StoreGetAttrs) { - cpp_redis::client client; - map test_attrs_base; - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("StoreGetAttrs"); - unique_ptr testObject_StoreGetAttrs = testBucket->get_object(rgw_obj_key("test_object_StoreGetAttrs")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreGetAttrs.get())->get_next(); - - EXPECT_NE(nextObject, nullptr); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Delete base attribute for easier comparison */ - testObject_StoreGetAttrs->delete_obj_attrs(dpp, "test_attrs_key_StoreGetAttrs", null_yield); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Set more attributes */ - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - } - - testObject_StoreGetAttrs->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield); - nextObject->get_obj_attrs(null_yield, dpp, NULL); - - /* Change an attribute through redis */ - vector< pair > value; - value.push_back(make_pair("test_attrs_key_extra_5", "new_test_attrs_value_extra_5")); - - client.hmset("rgw-object:test_object_StoreGetAttrs:cache", value, [&](cpp_redis::reply& reply) { - if (!reply.is_null()) { - EXPECT_EQ(reply.as_string(), "OK"); - } - }); - - client.sync_commit(); - - /* Artificially adding the data field so getObject will succeed - for the purposes of this test */ - value.clear(); - value.push_back(make_pair("data", "")); - - client.hmset("rgw-object:test_object_StoreGetAttrs:cache", value, [&](cpp_redis::reply& reply) { - if (!reply.is_null()) { - ASSERT_EQ(reply.as_string(), "OK"); - } - }); - - client.sync_commit(); - - ASSERT_EQ(testObject_StoreGetAttrs->get_obj_attrs(null_yield, dpp, NULL), 0); /* Cache attributes */ - - /* Check the attributes on the store layer */ - rgw::sal::Attrs driverAttrs = nextObject->get_attrs(); - rgw::sal::Attrs::iterator driverattrs; - vector< pair > driverValues; - - for (driverattrs = driverAttrs.begin(); driverattrs != driverAttrs.end(); ++driverattrs) { - driverValues.push_back(make_pair(driverattrs->first, driverattrs->second.to_str())); - } - - EXPECT_EQ((int)driverValues.size(), 10); - - int i = 0; - - for (const auto& pair : driverValues) { - string tmp_key = "test_attrs_key_extra_" + to_string(i); - string tmp_value = "test_attrs_value_extra_" + to_string(i); - - if (i == 5) { - tmp_value = "new_" + tmp_value; - } - - EXPECT_EQ(pair, make_pair(tmp_key, tmp_value)); - ++i; - } - - /* Restore and check original attributes */ - nextObject->get_obj_attrs(null_yield, dpp, NULL); - driverAttrs = nextObject->get_attrs(); - driverValues.clear(); - - for (driverattrs = driverAttrs.begin(); driverattrs != driverAttrs.end(); ++driverattrs) { - driverValues.push_back(make_pair(driverattrs->first, driverattrs->second.to_str())); - } - - EXPECT_EQ((int)driverValues.size(), 10); - - i = 0; - - for (const auto& pair : driverValues) { - string tmp_key = "test_attrs_key_extra_" + to_string(i); - string tmp_value = "test_attrs_value_extra_" + to_string(i); - - EXPECT_EQ(pair, make_pair(tmp_key, tmp_value)); - ++i; - } - - clientReset(&client); -} - -TEST_F(D4NFilterFixture, StoreGetMetadata) { - cpp_redis::client client; - clientSetUp(&client); - - createUser(); - createBucket(); - putObject("StoreGetMetadata"); - unique_ptr testObject_StoreGetMetadata = testBucket->get_object(rgw_obj_key("test_object_StoreGetMetadata")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreGetMetadata.get())->get_next(); - - EXPECT_NE(nextObject, nullptr); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Change metadata values through redis */ - vector< pair > value; - value.push_back(make_pair("mtime", "2021-11-08T21:13:38.334696731Z")); - value.push_back(make_pair("object_size", "100")); - value.push_back(make_pair("accounted_size", "200")); - value.push_back(make_pair("epoch", "3")); /* version_id is not tested because the object does not have an instance */ - value.push_back(make_pair("source_zone_short_id", "300")); - value.push_back(make_pair("bucket_count", "10")); - value.push_back(make_pair("bucket_size", "20")); - - client.hmset("rgw-object:test_object_StoreGetMetadata:cache", value, [](cpp_redis::reply& reply) { - if (!reply.is_null()) { - EXPECT_EQ(reply.as_string(), "OK"); - } - }); - - client.sync_commit(); - - /* Artificially adding the data field so getObject will succeed - for the purposes of this test */ - value.clear(); - value.push_back(make_pair("data", "")); - - client.hmset("rgw-object:test_object_StoreGetMetadata:cache", value, [](cpp_redis::reply& reply) { - if (!reply.is_null()) { - ASSERT_EQ(reply.as_string(), "OK"); - } - }); - - client.sync_commit(); - - unique_ptr testROp = testObject_StoreGetMetadata->get_read_op(); - - ASSERT_NE(testROp, nullptr); - ASSERT_EQ(testROp->prepare(null_yield, dpp), 0); - - /* Check updated metadata values */ - static StoreObject* storeObject = static_cast(dynamic_cast(testObject_StoreGetMetadata.get())->get_next()); - - EXPECT_EQ(to_iso_8601(storeObject->state.mtime), "2021-11-08T21:13:38.334696731Z"); - EXPECT_EQ(testObject_StoreGetMetadata->get_obj_size(), (uint64_t)100); - EXPECT_EQ(storeObject->state.accounted_size, (uint64_t)200); - EXPECT_EQ(storeObject->state.epoch, (uint64_t)3); - EXPECT_EQ(storeObject->state.zone_short_id, (uint32_t)300); -} - -TEST_F(D4NFilterFixture, StoreModifyAttr) { - createUser(); - createBucket(); - putObject("StoreModifyAttr"); - unique_ptr testObject_StoreModifyAttr = testBucket->get_object(rgw_obj_key("test_object_StoreModifyAttr")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreModifyAttr.get())->get_next(); - - ASSERT_NE(nextObject, nullptr); - - /* Modify existing attribute */ - buffer::list bl_tmp; - string tmp_value = "new_test_attrs_value_StoreModifyAttr"; - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - testObject_StoreModifyAttr->modify_obj_attrs("test_attrs_key_StoreModifyAttr", bl_tmp, null_yield, dpp); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Check the attribute */ - rgw::sal::Attrs driverAttrs = nextObject->get_attrs(); - pair value(driverAttrs.begin()->first, driverAttrs.begin()->second.to_str()); - - EXPECT_EQ(value, make_pair(string("test_attrs_key_StoreModifyAttr"), string("new_test_attrs_value_StoreModifyAttr"))); -} - -TEST_F(D4NFilterFixture, StoreDelAttrs) { - createUser(); - createBucket(); - putObject("StoreDelAttrs"); - unique_ptr testObject_StoreDelAttrs = testBucket->get_object(rgw_obj_key("test_object_StoreDelAttrs")); - - /* Get the underlying store */ - static rgw::sal::Object* nextObject = dynamic_cast(testObject_StoreDelAttrs.get())->get_next(); - - ASSERT_NE(nextObject, nullptr); - - /* Set more attributes */ - map test_attrs_base; - - for (int i = 0; i < 10; ++i) { - buffer::list bl_tmp; - string tmp_value = "test_attrs_value_extra_" + to_string(i); - bl_tmp.append(tmp_value.data(), strlen(tmp_value.data())); - - string tmp_key = "test_attrs_key_extra_" + to_string(i); - test_attrs_base.insert({tmp_key, bl_tmp}); - } - - testObject_StoreDelAttrs->set_obj_attrs(dpp, &test_attrs_base, NULL, null_yield); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Check that the attributes exist before deletion */ - rgw::sal::Attrs driverAttrs = nextObject->get_attrs(); - - EXPECT_EQ(driverAttrs.size(), (long unsigned int)11); - - rgw::sal::Attrs::iterator driverattrs; - vector< pair > driverValues; - - for (driverattrs = ++driverAttrs.begin(); driverattrs != driverAttrs.end(); ++driverattrs) { - driverValues.push_back(make_pair(driverattrs->first, driverattrs->second.to_str())); - } - - int i = 0; - - for (const auto& pair : driverValues) { - string tmp_key = "test_attrs_key_extra_" + to_string(i); - string tmp_value = "test_attrs_value_extra_" + to_string(i); - - EXPECT_EQ(pair, make_pair(tmp_key, tmp_value)); - ++i; - } - - testObject_StoreDelAttrs->set_obj_attrs(dpp, NULL, &test_attrs_base, null_yield); - - ASSERT_EQ(nextObject->get_obj_attrs(null_yield, dpp, NULL), 0); - - /* Check that the attributes do not exist after deletion */ - driverAttrs = nextObject->get_attrs(); - - EXPECT_EQ(driverAttrs.size(), (long unsigned int)1); - - pair value(driverAttrs.begin()->first, driverAttrs.begin()->second.to_str()); - - EXPECT_EQ(value, make_pair(string("test_attrs_key_StoreDelAttrs"), string("test_attrs_value_StoreDelAttrs"))); -} - -/* SAL object data storage check */ -TEST_F(D4NFilterFixture, DataCheck) { - cpp_redis::client client; - clientSetUp(&client); - - createUser(); - createBucket(); - - /* Prepare, process, and complete object write */ - unique_ptr obj = testBucket->get_object(rgw_obj_key("test_object_DataCheck")); - rgw_user owner; - rgw_placement_rule ptail_placement_rule; - uint64_t olh_epoch = 123; - string unique_tag; - - obj->get_obj_attrs(null_yield, dpp); - - testWriter = driver->get_atomic_writer(dpp, - null_yield, - obj.get(), - owner, - &ptail_placement_rule, - olh_epoch, - unique_tag); - - size_t accounted_size = 4; - string etag("test_etag"); - ceph::real_time mtime; - ceph::real_time set_mtime; - - buffer::list bl; - string tmp = "test_attrs_value_DataCheck"; - bl.append("test_attrs_value_DataCheck"); - map attrs{{"test_attrs_key_DataCheck", bl}}; - buffer::list data; - data.append("test data"); - - ceph::real_time delete_at; - char if_match; - char if_nomatch; - string user_data; - rgw_zone_set zones_trace; - bool canceled; - - ASSERT_EQ(testWriter->prepare(null_yield), 0); - - ASSERT_EQ(testWriter->process(std::move(data), 0), 0); - - ASSERT_EQ(testWriter->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - rctx, rgw::sal::FLAG_LOG_OP), 0); - - client.hget("rgw-object:test_object_DataCheck:cache", "data", [&data](cpp_redis::reply& reply) { - if (reply.is_string()) { - EXPECT_EQ(reply.as_string(), data.to_str()); - } - }); - - client.sync_commit(); - - /* Change data and ensure redis stores the new value */ - buffer::list dataNew; - dataNew.append("new test data"); - - ASSERT_EQ(testWriter->prepare(null_yield), 0); - - ASSERT_EQ(testWriter->process(std::move(dataNew), 0), 0); - - ASSERT_EQ(testWriter->complete(accounted_size, etag, - &mtime, set_mtime, - attrs, - delete_at, - &if_match, &if_nomatch, - &user_data, - &zones_trace, &canceled, - rctx, rgw::sal::FLAG_LOG_OP), 0); - - client.hget("rgw-object:test_object_DataCheck:cache", "data", [&dataNew](cpp_redis::reply& reply) { - if (reply.is_string()) { - EXPECT_EQ(reply.as_string(), dataNew.to_str()); - } - }); - - client.sync_commit(); - - clientReset(&client); -} - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - /* Other host and port can be passed to the program */ - if (argc == 1) { - portStr = "6379"; - hostStr = "127.0.0.1"; - } else if (argc == 3) { - hostStr = argv[1]; - portStr = argv[2]; - } else { - std::cout << "Incorrect number of arguments." << std::endl; - return -1; - } - - redisHost = hostStr + ":" + portStr; - - env = new Environment(); - ::testing::AddGlobalTestEnvironment(env); - - return RUN_ALL_TESTS(); -} diff --git a/src/test/rgw/test_d4n_policy.cc b/src/test/rgw/test_d4n_policy.cc new file mode 100644 index 0000000000000..e73cf3fe003fa --- /dev/null +++ b/src/test/rgw/test_d4n_policy.cc @@ -0,0 +1,253 @@ +#include +#include +#include + +#include "gtest/gtest.h" +#include "common/ceph_argparse.h" +#include "rgw_auth_registry.h" +#include "driver/d4n/d4n_policy.h" + +namespace net = boost::asio; +using boost::redis::config; +using boost::redis::connection; +using boost::redis::request; +using boost::redis::response; + +class Environment* env; + +class Environment : public ::testing::Environment { + public: + Environment() {} + + virtual ~Environment() {} + + void SetUp() override { + std::vector args; + std::string conf_file_list; + std::string cluster = ""; + CephInitParameters iparams = ceph_argparse_early_args( + args, CEPH_ENTITY_TYPE_CLIENT, + &cluster, &conf_file_list); + + cct = common_preinit(iparams, CODE_ENVIRONMENT_UTILITY, {}); + dpp = new DoutPrefix(cct->get(), dout_subsys, "D4N Object Directory Test: "); + + redisHost = cct->_conf->rgw_d4n_host + ":" + std::to_string(cct->_conf->rgw_d4n_port); + } + + std::string redisHost; + CephContext* cct; + DoutPrefixProvider* dpp; +}; + +class LFUDAPolicyFixture: public ::testing::Test { + protected: + virtual void SetUp() { + block = new rgw::d4n::CacheBlock{ + .cacheObj = { + .objName = "testName", + .bucketName = "testBucket", + .creationTime = 0, + .dirty = false, + .hostsList = { env->redisHost } + }, + .blockID = 0, + .version = "", + .size = bl.length(), + .hostsList = { env->redisHost } + }; + + rgw::cache::Partition partition_info{ .location = "RedisCache" }; + cacheDriver = new rgw::cache::RedisDriver{io, partition_info}; + policyDriver = new rgw::d4n::PolicyDriver(io, "lfuda"); + dir = new rgw::d4n::BlockDirectory{io}; + conn = new connection{boost::asio::make_strand(io)}; + + ASSERT_NE(dir, nullptr); + ASSERT_NE(cacheDriver, nullptr); + ASSERT_NE(policyDriver, nullptr); + ASSERT_NE(conn, nullptr); + + dir->init(env->cct, env->dpp); + cacheDriver->initialize(env->cct, env->dpp); + policyDriver->init(); + policyDriver->get_cache_policy()->init(env->cct, env->dpp); + + bl.append("test data"); + bufferlist attrVal; + attrVal.append("attrVal"); + attrs.insert({"attr", attrVal}); + + /* Run fixture's connection */ + config cfg; + cfg.addr.host = env->cct->_conf->rgw_d4n_host; + cfg.addr.port = std::to_string(env->cct->_conf->rgw_d4n_port); + + conn->async_run(cfg, {}, net::detached); + } + + virtual void TearDown() { + delete conn; + delete block; + delete dir; + delete cacheDriver; + delete policyDriver; + } + + rgw::d4n::CacheBlock* block; + rgw::d4n::BlockDirectory* dir; + rgw::d4n::PolicyDriver* policyDriver; + rgw::cache::RedisDriver* cacheDriver; + + net::io_context io; + connection* conn; + + bufferlist bl; + rgw::sal::Attrs attrs; + std::string key = "testName"; +}; + +TEST_F(LFUDAPolicyFixture, LocalGetBlockYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, key, bl, bl.length(), attrs, optional_yield{io, yield})); + policyDriver->get_cache_policy()->insert(env->dpp, key, 0, bl.length(), "", cacheDriver, optional_yield{io, yield}); + + /* Change cache age for testing purposes */ + { + boost::system::error_code ec; + request req; + req.push("HSET", "lfuda", "age", "5"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + ASSERT_GE(policyDriver->get_cache_policy()->get_block(env->dpp, block, cacheDriver, optional_yield{io, yield}), 0); + + dir->shutdown(); + cacheDriver->shutdown(); + policyDriver->get_cache_policy()->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "localWeight"); + req.push("FLUSHALL"); + + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "5"); + conn->cancel(); + }); + + io.run(); +} + +TEST_F(LFUDAPolicyFixture, RemoteGetBlockYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + /* Set victim block for eviction */ + rgw::d4n::CacheBlock victim = rgw::d4n::CacheBlock{ + .cacheObj = { + .objName = "victimName", + .bucketName = "testBucket", + .creationTime = 0, + .dirty = false, + .hostsList = { env->redisHost } + }, + .blockID = 0, + .version = "", + .size = bl.length(), + .globalWeight = 5, + .hostsList = { env->redisHost } + }; + + bufferlist attrVal; + attrVal.append(std::to_string(bl.length())); + attrs.insert({"accounted_size", attrVal}); + attrVal.clear(); + attrVal.append("testBucket"); + attrs.insert({"bucket_name", attrVal}); + + ASSERT_EQ(0, dir->set(&victim, optional_yield{io, yield})); + ASSERT_EQ(0, cacheDriver->put(env->dpp, victim.cacheObj.objName, bl, bl.length(), attrs, optional_yield{io, yield})); + policyDriver->get_cache_policy()->insert(env->dpp, victim.cacheObj.objName, 0, bl.length(), "", cacheDriver, optional_yield{io, yield}); + + /* Remote block */ + block->size = cacheDriver->get_free_space(env->dpp) + 1; /* To trigger eviction */ + block->hostsList.clear(); + block->cacheObj.hostsList.clear(); + block->hostsList.push_back("127.0.0.1:6000"); + block->cacheObj.hostsList.push_back("127.0.0.1:6000"); + + ASSERT_EQ(0, dir->set(block, optional_yield{io, yield})); + + ASSERT_GE(policyDriver->get_cache_policy()->get_block(env->dpp, block, cacheDriver, optional_yield{io, yield}), 0); + + dir->shutdown(); + cacheDriver->shutdown(); + policyDriver->get_cache_policy()->shutdown(); + + boost::system::error_code ec; + request req; + req.push("EXISTS", "RedisCache/victimName"); + req.push("HGET", "testBucket_victimName_0", "globalWeight"); + req.push("HGET", "testBucket_testName_0", "globalWeight"); + req.push("FLUSHALL"); + + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + EXPECT_EQ(std::get<1>(resp).value(), "5"); + EXPECT_EQ(std::get<2>(resp).value(), "0"); + conn->cancel(); + }); + + io.run(); +} + +TEST_F(LFUDAPolicyFixture, BackendGetBlockYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_GE(policyDriver->get_cache_policy()->get_block(env->dpp, block, cacheDriver, optional_yield{io, yield}), 0); + + dir->shutdown(); + cacheDriver->shutdown(); + policyDriver->get_cache_policy()->shutdown(); + + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + + response resp; + //response< std::vector, + // boost::redis::ignore_t > resp; + + conn->async_exec(req, resp, yield[ec]); + + //ASSERT_EQ((bool)ec, false); + //EXPECT_EQ(std::get<0>(resp).value(), vals); + conn->cancel(); + }); + + io.run(); +} + +int main(int argc, char *argv[]) { + ::testing::InitGoogleTest(&argc, argv); + + env = new Environment(); + ::testing::AddGlobalTestEnvironment(env); + + return RUN_ALL_TESTS(); +} diff --git a/src/test/rgw/test_redis_driver.cc b/src/test/rgw/test_redis_driver.cc new file mode 100644 index 0000000000000..a1f8783d54bdc --- /dev/null +++ b/src/test/rgw/test_redis_driver.cc @@ -0,0 +1,497 @@ +#include +#include +#include + +#include "gtest/gtest.h" +#include "common/ceph_argparse.h" +#include "rgw_auth_registry.h" +#include "rgw_redis_driver.h" + +namespace net = boost::asio; +using boost::redis::config; +using boost::redis::connection; +using boost::redis::request; +using boost::redis::response; + +class Environment* env; + +class Environment : public ::testing::Environment { + public: + Environment() {} + + virtual ~Environment() {} + + void SetUp() override { + std::vector args; + std::string conf_file_list; + std::string cluster = ""; + CephInitParameters iparams = ceph_argparse_early_args( + args, CEPH_ENTITY_TYPE_CLIENT, + &cluster, &conf_file_list); + + cct = common_preinit(iparams, CODE_ENVIRONMENT_UTILITY, {}); + dpp = new DoutPrefix(cct->get(), dout_subsys, "D4N Object Directory Test: "); + + redisHost = cct->_conf->rgw_d4n_host + ":" + std::to_string(cct->_conf->rgw_d4n_port); + } + + std::string redisHost; + CephContext* cct; + DoutPrefixProvider* dpp; +}; + +class RedisDriverFixture: public ::testing::Test { + protected: + virtual void SetUp() { + rgw::cache::Partition partition_info{ .location = "RedisCache" }; + cacheDriver = new rgw::cache::RedisDriver{io, partition_info}; + + conn = new connection{boost::asio::make_strand(io)}; + + ASSERT_NE(cacheDriver, nullptr); + ASSERT_NE(conn, nullptr); + + cacheDriver->initialize(env->cct, env->dpp); + + bl.append("test data"); + bufferlist attrVal; + attrVal.append("attrVal"); + attrs.insert({"attr", attrVal}); + + /* Run fixture's connection */ + config cfg; + cfg.addr.host = env->cct->_conf->rgw_d4n_host; + cfg.addr.port = std::to_string(env->cct->_conf->rgw_d4n_port); + + conn->async_run(cfg, {}, net::detached); + } + + virtual void TearDown() { + delete conn; + delete cacheDriver; + } + + rgw::cache::RedisDriver* cacheDriver; + + net::io_context io; + connection* conn; + + bufferlist bl; + rgw::sal::Attrs attrs; +}; + +TEST_F(RedisDriverFixture, PutYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + cacheDriver->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "attr"); + req.push("FLUSHALL"); + + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "attrVal"); + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, GetYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HSET", "RedisCache/testName", "data", "new data", "attr", "newVal"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + bufferlist ret; + rgw::sal::Attrs retAttrs; + + ASSERT_EQ(0, cacheDriver->get(env->dpp, "testName", 0, bl.length(), ret, retAttrs, optional_yield{io, yield})); + EXPECT_EQ(ret.to_str(), "new data"); + EXPECT_EQ(retAttrs.begin()->second.to_str(), "newVal"); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, DelYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "RedisCache/testName"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + } + + ASSERT_EQ(0, cacheDriver->del(env->dpp, "testName", optional_yield{io, yield})); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("EXISTS", "RedisCache/testName"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + conn->cancel(); + }); + + io.run(); +} + +// How can I test get_async? -Sam + +TEST_F(RedisDriverFixture, AppendDataYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "data"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "test data"); + } + + bufferlist val; + val.append(" has been written"); + + ASSERT_EQ(0, cacheDriver->append_data(env->dpp, "testName", val, optional_yield{io, yield})); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "data"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "test data has been written"); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, DeleteDataYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", "RedisCache/testName", "data"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + } + + ASSERT_EQ(0, cacheDriver->delete_data(env->dpp, "testName", optional_yield{io, yield})); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", "RedisCache/testName", "data"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, SetAttrsYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + rgw::sal::Attrs newAttrs; + bufferlist newVal; + newVal.append("newVal"); + newAttrs.insert({"newAttr", newVal}); + + newVal.clear(); + newVal.append("nextVal"); + newAttrs.insert({"nextAttr", newVal}); + + ASSERT_EQ(0, cacheDriver->set_attrs(env->dpp, "testName", newAttrs, optional_yield{io, yield})); + cacheDriver->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HMGET", "RedisCache/testName", "newAttr", "nextAttr"); + req.push("FLUSHALL"); + + response< std::vector, + boost::redis::ignore_t> resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value()[0], "newVal"); + EXPECT_EQ(std::get<0>(resp).value()[1], "nextVal"); + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, GetAttrsYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + rgw::sal::Attrs nextAttrs = attrs; + bufferlist nextVal; + nextVal.append("nextVal"); + nextAttrs.insert({"nextAttr", nextVal}); + + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), nextAttrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HSET", "RedisCache/testName", "attr", "newVal1", "nextAttr", "newVal2"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + rgw::sal::Attrs retAttrs; + + ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testName", retAttrs, optional_yield{io, yield})); + + auto it = retAttrs.begin(); + EXPECT_EQ(it->second.to_str(), "newVal1"); + ++it; + EXPECT_EQ(it->second.to_str(), "newVal2"); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, UpdateAttrsYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + rgw::sal::Attrs newAttrs; + bufferlist newVal; + newVal.append("newVal"); + newAttrs.insert({"attr", newVal}); + + ASSERT_EQ(0, cacheDriver->update_attrs(env->dpp, "testName", newAttrs, optional_yield{io, yield})); + cacheDriver->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "attr"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "newVal"); + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, DeleteAttrsYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", "RedisCache/testName", "attr"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 1); + } + + rgw::sal::Attrs delAttrs; + bufferlist delVal; + delAttrs.insert({"attr", delVal}); + + ASSERT_GE(cacheDriver->delete_attrs(env->dpp, "testName", delAttrs, optional_yield{io, yield}), 0); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", "RedisCache/testName", "attr"); + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, SetAttrYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + ASSERT_GE(cacheDriver->set_attr(env->dpp, "testName", "newAttr", "newVal", optional_yield{io, yield}), 0); + cacheDriver->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HGET", "RedisCache/testName", "newAttr"); + req.push("FLUSHALL"); + + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), "newVal"); + conn->cancel(); + }); + + io.run(); +} + +TEST_F(RedisDriverFixture, GetAttrYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, cacheDriver->put(env->dpp, "testName", bl, bl.length(), attrs, optional_yield{io, yield})); + + { + boost::system::error_code ec; + request req; + req.push("HSET", "RedisCache/testName", "attr", "newVal"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value(), 0); + } + + ASSERT_EQ("newVal", cacheDriver->get_attr(env->dpp, "testName", "attr", optional_yield{io, yield})); + cacheDriver->shutdown(); + + { + boost::system::error_code ec; + request req; + req.push("FLUSHALL"); + response resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + } + + conn->cancel(); + }); + + io.run(); +} + + +int main(int argc, char *argv[]) { + ::testing::InitGoogleTest(&argc, argv); + + env = new Environment(); + ::testing::AddGlobalTestEnvironment(env); + + return RUN_ALL_TESTS(); +} -- 2.39.5