From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/test/librados_test_stub/TestClassHandler.cc | 159 ++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/test/librados_test_stub/TestClassHandler.cc (limited to 'src/test/librados_test_stub/TestClassHandler.cc') diff --git a/src/test/librados_test_stub/TestClassHandler.cc b/src/test/librados_test_stub/TestClassHandler.cc new file mode 100644 index 000000000..df830918f --- /dev/null +++ b/src/test/librados_test_stub/TestClassHandler.cc @@ -0,0 +1,159 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/librados_test_stub/TestClassHandler.h" +#include "test/librados_test_stub/TestIoCtxImpl.h" +#include +#include +#include +#include +#include "common/debug.h" +#include "include/ceph_assert.h" +#include "include/dlfcn_compat.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rados + +namespace librados { + +TestClassHandler::TestClassHandler() { +} + +TestClassHandler::~TestClassHandler() { + for (ClassHandles::iterator it = m_class_handles.begin(); + it != m_class_handles.end(); ++it) { + dlclose(*it); + } +} + +void TestClassHandler::open_class(const std::string& name, + const std::string& path) { + void *handle = dlopen(path.c_str(), RTLD_NOW); + if (handle == NULL) { + std::cerr << "Failed to load class: " << name << " (" << path << "): " + << dlerror() << std::endl; + return; + } + + // initialize + void (*cls_init)() = reinterpret_cast( + dlsym(handle, "__cls_init")); + + if (!cls_init) { + std::cerr << "Error locating initializer: " << dlerror() << std::endl; + } else if (cls_init) { + m_class_handles.push_back(handle); + cls_init(); + return; + } + + std::cerr << "Class: " << name << " (" << path << ") missing initializer" + << std::endl; + dlclose(handle); +} + +void TestClassHandler::open_all_classes() { + ceph_assert(m_class_handles.empty()); + + const char* env = getenv("CEPH_LIB"); + std::string CEPH_LIB(env ? env : "lib"); + DIR *dir = ::opendir(CEPH_LIB.c_str()); + if (dir == NULL) { + ceph_abort();; + } + + std::set names; + struct dirent *pde = nullptr; + while ((pde = ::readdir(dir))) { + std::string name(pde->d_name); + if (!boost::algorithm::starts_with(name, "libcls_") || + !boost::algorithm::ends_with(name, SHARED_LIB_SUFFIX)) { + continue; + } + names.insert(name); + } + + for (auto& name : names) { + std::string class_name = name.substr(7, name.size() - 10); + open_class(class_name, CEPH_LIB + "/" + name); + } + closedir(dir); +} + +int TestClassHandler::create(const std::string &name, cls_handle_t *handle) { + if (m_classes.find(name) != m_classes.end()) { + std::cerr << "Class " << name << " already exists" << std::endl; + return -EEXIST; + } + + SharedClass cls(new Class()); + m_classes[name] = cls; + *handle = reinterpret_cast(cls.get()); + return 0; +} + +int TestClassHandler::create_method(cls_handle_t hclass, + const char *name, + cls_method_cxx_call_t class_call, + cls_method_handle_t *handle) { + Class *cls = reinterpret_cast(hclass); + if (cls->methods.find(name) != cls->methods.end()) { + std::cerr << "Class method " << hclass << ":" << name << " already exists" + << std::endl; + return -EEXIST; + } + + SharedMethod method(new Method()); + method->class_call = class_call; + cls->methods[name] = method; + return 0; +} + +cls_method_cxx_call_t TestClassHandler::get_method(const std::string &cls, + const std::string &method) { + Classes::iterator c_it = m_classes.find(cls); + if (c_it == m_classes.end()) { + std::cerr << "Failed to located class " << cls << std::endl; + return NULL; + } + + SharedClass scls = c_it->second; + Methods::iterator m_it = scls->methods.find(method); + if (m_it == scls->methods.end()) { + std::cerr << "Failed to located class method" << cls << "." << method + << std::endl; + return NULL; + } + return m_it->second->class_call; +} + +TestClassHandler::SharedMethodContext TestClassHandler::get_method_context( + TestIoCtxImpl *io_ctx_impl, const std::string &oid, uint64_t snap_id, + const SnapContext &snapc) { + SharedMethodContext ctx(new MethodContext()); + + // clone to ioctx to provide a firewall for gmock expectations + ctx->io_ctx_impl = io_ctx_impl->clone(); + ctx->oid = oid; + ctx->snap_id = snap_id; + ctx->snapc = snapc; + return ctx; +} + +int TestClassHandler::create_filter(cls_handle_t hclass, + const std::string& name, + cls_cxx_filter_factory_t fn) +{ + Class *cls = reinterpret_cast(hclass); + if (cls->filters.find(name) != cls->filters.end()) { + return -EEXIST; + } + cls->filters[name] = fn; + return 0; +} + +TestClassHandler::MethodContext::~MethodContext() { + io_ctx_impl->put(); +} + +} // namespace librados -- cgit v1.2.3