1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librados_test_stub/TestClassHandler.h"
5 #include "test/librados_test_stub/TestIoCtxImpl.h"
6 #include <boost/algorithm/string/predicate.hpp>
10 #include "common/debug.h"
11 #include "include/ceph_assert.h"
12 #include "include/dlfcn_compat.h"
14 #define dout_context g_ceph_context
15 #define dout_subsys ceph_subsys_rados
19 TestClassHandler::TestClassHandler() {
22 TestClassHandler::~TestClassHandler() {
23 for (ClassHandles::iterator it
= m_class_handles
.begin();
24 it
!= m_class_handles
.end(); ++it
) {
29 void TestClassHandler::open_class(const std::string
& name
,
30 const std::string
& path
) {
31 void *handle
= dlopen(path
.c_str(), RTLD_NOW
);
33 std::cerr
<< "Failed to load class: " << name
<< " (" << path
<< "): "
34 << dlerror() << std::endl
;
39 void (*cls_init
)() = reinterpret_cast<void (*)()>(
40 dlsym(handle
, "__cls_init"));
43 std::cerr
<< "Error locating initializer: " << dlerror() << std::endl
;
44 } else if (cls_init
) {
45 m_class_handles
.push_back(handle
);
50 std::cerr
<< "Class: " << name
<< " (" << path
<< ") missing initializer"
55 void TestClassHandler::open_all_classes() {
56 ceph_assert(m_class_handles
.empty());
58 const char* env
= getenv("CEPH_LIB");
59 std::string
CEPH_LIB(env
? env
: "lib");
60 DIR *dir
= ::opendir(CEPH_LIB
.c_str());
65 std::set
<std::string
> names
;
66 struct dirent
*pde
= nullptr;
67 while ((pde
= ::readdir(dir
))) {
68 std::string
name(pde
->d_name
);
69 if (!boost::algorithm::starts_with(name
, "libcls_") ||
70 !boost::algorithm::ends_with(name
, SHARED_LIB_SUFFIX
)) {
76 for (auto& name
: names
) {
77 std::string class_name
= name
.substr(7, name
.size() - 10);
78 open_class(class_name
, CEPH_LIB
+ "/" + name
);
83 int TestClassHandler::create(const std::string
&name
, cls_handle_t
*handle
) {
84 if (m_classes
.find(name
) != m_classes
.end()) {
85 std::cerr
<< "Class " << name
<< " already exists" << std::endl
;
89 SharedClass
cls(new Class());
90 m_classes
[name
] = cls
;
91 *handle
= reinterpret_cast<cls_handle_t
>(cls
.get());
95 int TestClassHandler::create_method(cls_handle_t hclass
,
97 cls_method_cxx_call_t class_call
,
98 cls_method_handle_t
*handle
) {
99 Class
*cls
= reinterpret_cast<Class
*>(hclass
);
100 if (cls
->methods
.find(name
) != cls
->methods
.end()) {
101 std::cerr
<< "Class method " << hclass
<< ":" << name
<< " already exists"
106 SharedMethod
method(new Method());
107 method
->class_call
= class_call
;
108 cls
->methods
[name
] = method
;
112 cls_method_cxx_call_t
TestClassHandler::get_method(const std::string
&cls
,
113 const std::string
&method
) {
114 Classes::iterator c_it
= m_classes
.find(cls
);
115 if (c_it
== m_classes
.end()) {
116 std::cerr
<< "Failed to located class " << cls
<< std::endl
;
120 SharedClass scls
= c_it
->second
;
121 Methods::iterator m_it
= scls
->methods
.find(method
);
122 if (m_it
== scls
->methods
.end()) {
123 std::cerr
<< "Failed to located class method" << cls
<< "." << method
127 return m_it
->second
->class_call
;
130 TestClassHandler::SharedMethodContext
TestClassHandler::get_method_context(
131 TestIoCtxImpl
*io_ctx_impl
, const std::string
&oid
, uint64_t snap_id
,
132 const SnapContext
&snapc
) {
133 SharedMethodContext
ctx(new MethodContext());
135 // clone to ioctx to provide a firewall for gmock expectations
136 ctx
->io_ctx_impl
= io_ctx_impl
->clone();
138 ctx
->snap_id
= snap_id
;
143 int TestClassHandler::create_filter(cls_handle_t hclass
,
144 const std::string
& name
,
145 cls_cxx_filter_factory_t fn
)
147 Class
*cls
= reinterpret_cast<Class
*>(hclass
);
148 if (cls
->filters
.find(name
) != cls
->filters
.end()) {
151 cls
->filters
[name
] = fn
;
155 TestClassHandler::MethodContext::~MethodContext() {
159 } // namespace librados