Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados_test_stub / TestClassHandler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librados_test_stub/TestClassHandler.h"
5 #include "test/librados_test_stub/TestIoCtxImpl.h"
6 #include <boost/algorithm/string/predicate.hpp>
7 #include <dlfcn.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "common/debug.h"
12 #include "include/assert.h"
13
14 #define dout_context g_ceph_context
15 #define dout_subsys ceph_subsys_rados
16
17 namespace librados {
18
19 TestClassHandler::TestClassHandler() {
20 }
21
22 TestClassHandler::~TestClassHandler() {
23   for (ClassHandles::iterator it = m_class_handles.begin();
24       it != m_class_handles.end(); ++it) {
25     dlclose(*it);
26   }
27 }
28
29 void TestClassHandler::open_class(const std::string& name,
30                                   const std::string& path) {
31   void *handle = dlopen(path.c_str(), RTLD_NOW);
32   if (handle == NULL) {
33     derr << "Failed to load class: " << dlerror() << dendl;
34     return;
35   }
36   m_class_handles.push_back(handle);
37
38   // initialize
39   void (*cls_init)() = reinterpret_cast<void (*)()>(
40       dlsym(handle, "__cls_init"));
41   if (cls_init) {
42     cls_init();
43   }
44 }
45
46 void TestClassHandler::open_all_classes() {
47   assert(m_class_handles.empty());
48
49   const char* env = getenv("CEPH_LIB");
50   std::string CEPH_LIB(env ? env : ".libs");
51   DIR *dir = ::opendir(CEPH_LIB.c_str());
52   if (dir == NULL) {
53     assert(false);;
54   }
55
56   struct dirent *pde = nullptr;
57   while ((pde = ::readdir(dir))) {
58     std::string name(pde->d_name);
59     if (!boost::algorithm::starts_with(name, "libcls_") ||
60         !boost::algorithm::ends_with(name, ".so")) {
61       continue;
62     }
63     std::string class_name = name.substr(7, name.size() - 10);
64     open_class(class_name, CEPH_LIB + "/" + name);
65   }
66   closedir(dir);
67 }
68
69 int TestClassHandler::create(const std::string &name, cls_handle_t *handle) {
70   if (m_classes.find(name) != m_classes.end()) {
71     return -EEXIST;
72   }
73
74   SharedClass cls(new Class());
75   m_classes[name] = cls;
76   *handle = reinterpret_cast<cls_handle_t>(cls.get());
77   return 0;
78 }
79
80 int TestClassHandler::create_method(cls_handle_t hclass,
81                                     const char *name,
82                                     cls_method_cxx_call_t class_call,
83                                     cls_method_handle_t *handle) {
84   Class *cls = reinterpret_cast<Class*>(hclass);
85   if (cls->methods.find(name) != cls->methods.end()) {
86     return -EEXIST;
87   }
88
89   SharedMethod method(new Method());
90   method->class_call = class_call;
91   cls->methods[name] = method;
92   return 0;
93 }
94
95 cls_method_cxx_call_t TestClassHandler::get_method(const std::string &cls,
96                                                    const std::string &method) {
97   Classes::iterator c_it = m_classes.find(cls);
98   if (c_it == m_classes.end()) {
99     return NULL;
100   }
101
102   SharedClass scls = c_it->second;
103   Methods::iterator m_it = scls->methods.find(method);
104   if (m_it == scls->methods.end()) {
105     return NULL;
106   }
107   return m_it->second->class_call;
108 }
109
110 TestClassHandler::SharedMethodContext TestClassHandler::get_method_context(
111     TestIoCtxImpl *io_ctx_impl, const std::string &oid,
112     const SnapContext &snapc) {
113   SharedMethodContext ctx(new MethodContext());
114
115   // clone to ioctx to provide a firewall for gmock expectations
116   ctx->io_ctx_impl = io_ctx_impl->clone();
117   ctx->oid = oid;
118   ctx->snapc = snapc;
119   return ctx;
120 }
121
122 int TestClassHandler::create_filter(cls_handle_t hclass,
123                                     const std::string& name,
124                                     cls_cxx_filter_factory_t fn)
125 {
126   Class *cls = reinterpret_cast<Class*>(hclass);
127   if (cls->filters.find(name) != cls->filters.end()) {
128     return -EEXIST;
129   }
130   cls->filters[name] = fn;
131   return 0;
132 }
133
134 TestClassHandler::MethodContext::~MethodContext() {
135   io_ctx_impl->put();
136 }
137
138 } // namespace librados