libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #include <vector> 00029 #include <deque> 00030 #include <string> 00031 00032 #include <boost/test/unit_test.hpp> 00033 00034 #include "../../include/moost/pdl/dynamic_library.h" 00035 #include "../../include/moost/utils/foreach.hpp" 00036 #include "../../include/moost/testing/error_matcher.hpp" 00037 00038 #include "test_interface.h" 00039 00040 BOOST_AUTO_TEST_SUITE(moost_pdl) 00041 00042 namespace 00043 { 00044 00045 typedef moost::testing::error_matcher matches; 00046 00047 std::deque<std::string> events; 00048 00049 std::string next_event() 00050 { 00051 std::string event; 00052 00053 if (!events.empty()) 00054 { 00055 event = events.front(); 00056 events.pop_front(); 00057 } 00058 00059 return event; 00060 } 00061 00062 class other_test_interface : public moost::pdl::dynamic_class 00063 { 00064 public: 00065 virtual int bla() = 0; 00066 }; 00067 00068 typedef std::pair<std::string, int> class_t; 00069 00070 void test_loader(const std::string& dir, const std::string& libname, const std::vector<class_t>& classvec) 00071 { 00072 std::string library = dir + '/' + libname; 00073 00074 BOOST_REQUIRE(classvec.size() > 0); 00075 BOOST_REQUIRE_EQUAL(events.size(), 0); 00076 00077 { 00078 moost::pdl::dynamic_library lib(library); 00079 BOOST_CHECK(lib.is_open()); 00080 } 00081 00082 BOOST_CHECK_EQUAL(events.size(), 2); 00083 BOOST_CHECK_EQUAL(next_event(), "load " + libname); 00084 BOOST_CHECK_EQUAL(next_event(), "unload " + libname); 00085 00086 { 00087 moost::pdl::dynamic_library lib(library); 00088 00089 BOOST_CHECK_EQUAL(events.size(), 1); 00090 BOOST_CHECK_EQUAL(next_event(), "load " + libname); 00091 00092 foreach (const class_t& cls, classvec) 00093 { 00094 { 00095 boost::shared_ptr<my_test_interface> inst(lib.create<my_test_interface>(cls.first)); 00096 BOOST_REQUIRE(inst != 0); 00097 BOOST_CHECK_EQUAL(events.size(), 1); 00098 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 1"); 00099 00100 BOOST_CHECK_EQUAL(inst->do_it(), cls.second); 00101 00102 boost::shared_ptr<other_test_interface> inst2; 00103 BOOST_CHECK_THROW(inst2 = lib.create<other_test_interface>(cls.first), moost::pdl::exception); 00104 BOOST_CHECK(inst2 == 0); 00105 BOOST_CHECK_EQUAL(events.size(), 2); 00106 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 2"); 00107 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 2"); 00108 } 00109 00110 BOOST_CHECK_EQUAL(events.size(), 1); 00111 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 1"); 00112 } 00113 } 00114 00115 BOOST_CHECK_EQUAL(events.size(), 1); 00116 BOOST_CHECK_EQUAL(next_event(), "unload " + libname); 00117 00118 moost::pdl::dynamic_library lib; 00119 BOOST_CHECK(!lib.is_open()); 00120 00121 BOOST_CHECK_EQUAL(events.size(), 0); 00122 00123 lib.open(library); 00124 00125 BOOST_CHECK_EQUAL(events.size(), 1); 00126 BOOST_CHECK_EQUAL(next_event(), "load " + libname); 00127 00128 lib.open(library); 00129 00130 BOOST_CHECK_EQUAL(events.size(), 0); 00131 BOOST_CHECK(lib.is_open()); 00132 00133 foreach (const class_t& cls, classvec) 00134 { 00135 { 00136 boost::shared_ptr<my_test_interface> inst(lib.create<my_test_interface>(cls.first)); 00137 BOOST_REQUIRE(inst != 0); 00138 BOOST_CHECK_EQUAL(events.size(), 1); 00139 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 1"); 00140 00141 BOOST_CHECK_EQUAL(inst->do_it(), cls.second); 00142 00143 boost::shared_ptr<other_test_interface> inst2; 00144 BOOST_CHECK_THROW(inst2 = lib.create<other_test_interface>(cls.first), moost::pdl::exception); 00145 BOOST_CHECK(inst2 == 0); 00146 BOOST_CHECK_EQUAL(events.size(), 2); 00147 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 2"); 00148 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 2"); 00149 } 00150 00151 BOOST_CHECK_EQUAL(events.size(), 1); 00152 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 1"); 00153 } 00154 00155 lib.close(); 00156 00157 BOOST_CHECK_EQUAL(events.size(), 1); 00158 BOOST_CHECK_EQUAL(next_event(), "unload " + libname); 00159 BOOST_CHECK(!lib.is_open()); 00160 00161 foreach (const class_t& cls, classvec) 00162 { 00163 { 00164 moost::pdl::dynamic_library(library).create<my_test_interface>(cls.first); 00165 BOOST_CHECK_EQUAL(events.size(), 4); 00166 BOOST_CHECK_EQUAL(next_event(), "load " + libname); 00167 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 1"); 00168 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 1"); 00169 BOOST_CHECK_EQUAL(next_event(), "unload " + libname); 00170 00171 boost::shared_ptr<my_test_interface> inst = moost::pdl::dynamic_library(library).create<my_test_interface>(cls.first); 00172 BOOST_REQUIRE(inst != 0); 00173 BOOST_CHECK_EQUAL(events.size(), 2); 00174 BOOST_CHECK_EQUAL(next_event(), "load " + libname); 00175 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 1"); 00176 00177 BOOST_CHECK_EQUAL(inst->do_it(), cls.second); 00178 00179 boost::shared_ptr<other_test_interface> inst2; 00180 BOOST_CHECK_THROW(inst2 = moost::pdl::dynamic_library(library).create<other_test_interface>(cls.first), moost::pdl::exception); 00181 BOOST_CHECK(inst2 == 0); 00182 BOOST_CHECK_EQUAL(events.size(), 2); 00183 BOOST_CHECK_EQUAL(next_event(), "ctor " + libname + ":" + cls.first + " 2"); 00184 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 2"); 00185 } 00186 00187 BOOST_CHECK_EQUAL(events.size(), 2); 00188 BOOST_CHECK_EQUAL(next_event(), "dtor " + libname + ":" + cls.first + " 1"); 00189 BOOST_CHECK_EQUAL(next_event(), "unload " + libname); 00190 } 00191 } 00192 00193 } 00194 00195 extern "C" void pdl_test_event(const std::string& event) 00196 { 00197 events.push_back(event); 00198 } 00199 00200 BOOST_AUTO_TEST_CASE(load_library) 00201 { 00202 // Check loading, unloading, creating & destroying instances 00203 00204 std::vector<class_t> classvec(2); 00205 00206 classvec[0].first = "my_test_class1"; 00207 classvec[1].first = "my_test_class2"; 00208 00209 classvec[0].second = 1; 00210 classvec[1].second = 2; 00211 00212 test_loader("../lib", "test_module1", classvec); 00213 00214 classvec[0].second = 3; 00215 classvec[1].second = 4; 00216 00217 test_loader("../lib", "test_module2", classvec); 00218 } 00219 00220 BOOST_AUTO_TEST_CASE(load_library_multi) 00221 { 00222 // Check that multiple library instances only load the shared object once 00223 00224 { 00225 const std::string library("../lib/test_module1"); 00226 00227 moost::pdl::dynamic_library lib1(library); 00228 BOOST_CHECK_EQUAL(events.size(), 1); 00229 BOOST_CHECK_EQUAL(next_event(), "load test_module1"); 00230 00231 { 00232 moost::pdl::dynamic_library lib2(library); 00233 BOOST_CHECK_EQUAL(events.size(), 0); 00234 } 00235 00236 BOOST_CHECK_EQUAL(events.size(), 0); 00237 } 00238 00239 BOOST_CHECK_EQUAL(events.size(), 1); 00240 BOOST_CHECK_EQUAL(next_event(), "unload test_module1"); 00241 } 00242 00243 BOOST_AUTO_TEST_CASE(multi_instances) 00244 { 00245 // Check that every instance we create is distinct 00246 00247 { 00248 boost::shared_ptr<my_test_interface> inst2; 00249 00250 { 00251 moost::pdl::dynamic_library lib("../lib/test_module1"); 00252 BOOST_CHECK_EQUAL(events.size(), 1); 00253 BOOST_CHECK_EQUAL(next_event(), "load test_module1"); 00254 00255 { 00256 boost::shared_ptr<my_test_interface> inst1; 00257 00258 inst1 = lib.create<my_test_interface>("my_test_class1"); 00259 BOOST_CHECK_EQUAL(events.size(), 1); 00260 BOOST_CHECK_EQUAL(next_event(), "ctor test_module1:my_test_class1 1"); 00261 00262 inst2 = lib.create<my_test_interface>("my_test_class1"); 00263 BOOST_CHECK_EQUAL(events.size(), 1); 00264 BOOST_CHECK_EQUAL(next_event(), "ctor test_module1:my_test_class1 2"); 00265 00266 BOOST_CHECK_EQUAL(inst1->do_it(), 1); 00267 BOOST_CHECK_EQUAL(inst1->do_it(), 11); 00268 BOOST_CHECK_EQUAL(inst2->do_it(), 1); 00269 BOOST_CHECK_EQUAL(inst2->do_it(), 11); 00270 BOOST_CHECK_EQUAL(inst1->do_it(), 21); 00271 BOOST_CHECK_EQUAL(inst2->do_it(), 21); 00272 } 00273 00274 BOOST_CHECK_EQUAL(events.size(), 1); 00275 BOOST_CHECK_EQUAL(next_event(), "dtor test_module1:my_test_class1 1"); 00276 00277 BOOST_CHECK_EQUAL(inst2->do_it(), 31); 00278 } 00279 00280 BOOST_CHECK_EQUAL(events.size(), 0); 00281 } 00282 00283 BOOST_CHECK_EQUAL(events.size(), 2); 00284 BOOST_CHECK_EQUAL(next_event(), "dtor test_module1:my_test_class1 2"); 00285 BOOST_CHECK_EQUAL(next_event(), "unload test_module1"); 00286 } 00287 00288 BOOST_AUTO_TEST_CASE(pdl_error) 00289 { 00290 moost::pdl::dynamic_library dl; 00291 00292 BOOST_CHECK_EXCEPTION(dl.create<my_test_interface>("foo"), moost::pdl::exception, 00293 matches("no library loaded")); 00294 00295 // XXX: This check won't necessarily work on Windows, as the error message is probably different 00296 BOOST_CHECK_EXCEPTION(dl.open("Does_Not_Exist"), moost::pdl::library_not_found_error, matches(".*Does_Not_Exist.*")); 00297 00298 BOOST_CHECK(!dl.is_open()); 00299 00300 dl.open("../lib/test_module1"); 00301 00302 BOOST_CHECK(dl.is_open()); 00303 00304 BOOST_CHECK_EXCEPTION(dl.create<my_test_interface>("foo"), moost::pdl::class_not_found_error, 00305 matches("class foo not found in ../lib/.*test_module1.*")); 00306 00307 BOOST_CHECK_EXCEPTION(dl.create<my_test_interface>("my_fail_class"), moost::pdl::exception, 00308 matches("failed to create instance of class my_fail_class")); 00309 00310 BOOST_CHECK_EXCEPTION(dl.create<other_test_interface>("my_test_class1"), moost::pdl::exception, 00311 matches("invalid type for class my_test_class1")); 00312 00313 dl.close(); 00314 00315 BOOST_CHECK(!dl.is_open()); 00316 00317 BOOST_CHECK_EQUAL(events.size(), 4); 00318 BOOST_CHECK_EQUAL(next_event(), "load test_module1"); 00319 BOOST_CHECK_EQUAL(next_event(), "ctor test_module1:my_test_class1 1"); 00320 BOOST_CHECK_EQUAL(next_event(), "dtor test_module1:my_test_class1 1"); 00321 BOOST_CHECK_EQUAL(next_event(), "unload test_module1"); 00322 } 00323 00324 BOOST_AUTO_TEST_SUITE_END()