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>
11 #include "common/debug.h"
12 #include "include/ceph_assert.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
;
38 // clear any existing error
42 void (*cls_init
)() = reinterpret_cast<void (*)()>(
43 dlsym(handle
, "__cls_init"));
45 char* error
= nullptr;
46 if ((error
= dlerror()) != nullptr) {
47 std::cerr
<< "Error locating initializer: " << error
<< std::endl
;
48 } else if (cls_init
) {
49 m_class_handles
.push_back(handle
);
54 std::cerr
<< "Class: " << name
<< " (" << path
<< ") missing initializer"
59 void TestClassHandler::open_all_classes() {
60 ceph_assert(m_class_handles
.empty());
62 const char* env
= getenv("CEPH_LIB");
63 std::string
CEPH_LIB(env
? env
: "lib");
64 DIR *dir
= ::opendir(CEPH_LIB
.c_str());
69 std::set
<std::string
> names
;
70 struct dirent
*pde
= nullptr;
71 while ((pde
= ::readdir(dir
))) {
72 std::string
name(pde
->d_name
);
73 if (!boost::algorithm::starts_with(name
, "libcls_") ||
74 !boost::algorithm::ends_with(name
, ".so")) {
80 for (auto& name
: names
) {
81 std::string class_name
= name
.substr(7, name
.size() - 10);
82 open_class(class_name
, CEPH_LIB
+ "/" + name
);
87 int TestClassHandler::create(const std::string
&name
, cls_handle_t
*handle
) {
88 if (m_classes
.find(name
) != m_classes
.end()) {
89 std::cerr
<< "Class " << name
<< " already exists" << std::endl
;
93 SharedClass
cls(new Class());
94 m_classes
[name
] = cls
;
95 *handle
= reinterpret_cast<cls_handle_t
>(cls
.get());
99 int TestClassHandler::create_method(cls_handle_t hclass
,
101 cls_method_cxx_call_t class_call
,
102 cls_method_handle_t
*handle
) {
103 Class
*cls
= reinterpret_cast<Class
*>(hclass
);
104 if (cls
->methods
.find(name
) != cls
->methods
.end()) {
105 std::cerr
<< "Class method " << hclass
<< ":" << name
<< " already exists"
110 SharedMethod
method(new Method());
111 method
->class_call
= class_call
;
112 cls
->methods
[name
] = method
;
116 cls_method_cxx_call_t
TestClassHandler::get_method(const std::string
&cls
,
117 const std::string
&method
) {
118 Classes::iterator c_it
= m_classes
.find(cls
);
119 if (c_it
== m_classes
.end()) {
120 std::cerr
<< "Failed to located class " << cls
<< std::endl
;
124 SharedClass scls
= c_it
->second
;
125 Methods::iterator m_it
= scls
->methods
.find(method
);
126 if (m_it
== scls
->methods
.end()) {
127 std::cerr
<< "Failed to located class method" << cls
<< "." << method
131 return m_it
->second
->class_call
;
134 TestClassHandler::SharedMethodContext
TestClassHandler::get_method_context(
135 TestIoCtxImpl
*io_ctx_impl
, const std::string
&oid
,
136 const SnapContext
&snapc
) {
137 SharedMethodContext
ctx(new MethodContext());
139 // clone to ioctx to provide a firewall for gmock expectations
140 ctx
->io_ctx_impl
= io_ctx_impl
->clone();
146 int TestClassHandler::create_filter(cls_handle_t hclass
,
147 const std::string
& name
,
148 cls_cxx_filter_factory_t fn
)
150 Class
*cls
= reinterpret_cast<Class
*>(hclass
);
151 if (cls
->filters
.find(name
) != cls
->filters
.end()) {
154 cls
->filters
[name
] = fn
;
158 TestClassHandler::MethodContext::~MethodContext() {
162 } // namespace librados