shared_library_load_test.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. // Copyright 2011-2012 Renato Tegon Forti
  2. // Copyright 2015-2019 Antony Polukhin
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // For more information, see http://www.boost.org
  8. #include "../example/b2_workarounds.hpp"
  9. #include <boost/dll.hpp>
  10. #include <boost/core/lightweight_test.hpp>
  11. // Unit Tests
  12. namespace boost { namespace dll { namespace fs {
  13. #ifdef BOOST_DLL_USE_STD_FS
  14. using std::filesystem::remove;
  15. using std::filesystem::copy;
  16. #else
  17. using boost::filesystem::remove;
  18. using boost::filesystem::copy;
  19. #endif
  20. }}}
  21. inline boost::dll::fs::path drop_version(const boost::dll::fs::path& lhs) {
  22. boost::dll::fs::path ext = lhs.filename().extension();
  23. if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) {
  24. ext = lhs;
  25. ext.replace_extension().replace_extension().replace_extension();
  26. return ext;
  27. }
  28. return lhs;
  29. }
  30. inline bool lib_path_equal(const boost::dll::fs::path& lhs, const boost::dll::fs::path& rhs) {
  31. const bool res = (drop_version(lhs).filename() == drop_version(rhs).filename());
  32. if (!res) {
  33. std::cerr << "lhs != rhs: " << lhs << " != " << rhs << '\n';
  34. }
  35. return res;
  36. }
  37. struct fs_copy_guard {
  38. const boost::dll::fs::path actual_path_;
  39. const bool same_;
  40. inline explicit fs_copy_guard(const boost::dll::fs::path& shared_library_path)
  41. : actual_path_( drop_version(shared_library_path) )
  42. , same_(actual_path_ == shared_library_path)
  43. {
  44. if (!same_) {
  45. boost::dll::fs::error_code ignore;
  46. boost::dll::fs::remove(actual_path_, ignore);
  47. boost::dll::fs::copy(shared_library_path, actual_path_, ignore);
  48. }
  49. }
  50. inline ~fs_copy_guard() {
  51. if (!same_) {
  52. boost::dll::fs::error_code ignore;
  53. boost::dll::fs::remove(actual_path_, ignore);
  54. }
  55. }
  56. };
  57. // Disgusting workarounds for b2 on Windows platform
  58. inline boost::dll::fs::path do_find_correct_libs_path(int argc, char* argv[], const char* lib_name) {
  59. boost::dll::fs::path ret;
  60. for (int i = 1; i < argc; ++i) {
  61. ret = argv[i];
  62. if (ret.string().find(lib_name) != std::string::npos && b2_workarounds::is_shared_library(ret)) {
  63. return ret;
  64. }
  65. }
  66. return lib_name;
  67. }
  68. int main(int argc, char* argv[])
  69. {
  70. using namespace boost::dll;
  71. BOOST_TEST(argc >= 3);
  72. boost::dll::fs::path shared_library_path = do_find_correct_libs_path(argc, argv, "test_library");
  73. std::cout << "Library: " << shared_library_path;
  74. {
  75. shared_library sl(shared_library_path);
  76. BOOST_TEST(sl.is_loaded());
  77. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  78. shared_library sl2;
  79. BOOST_TEST(!sl2.is_loaded());
  80. BOOST_TEST(!sl2);
  81. swap(sl, sl2);
  82. BOOST_TEST(!sl.is_loaded());
  83. BOOST_TEST(!sl);
  84. BOOST_TEST(sl2.is_loaded());
  85. BOOST_TEST(sl2);
  86. sl.assign(sl2);
  87. BOOST_TEST(sl.is_loaded());
  88. BOOST_TEST(sl);
  89. BOOST_TEST(sl2.is_loaded());
  90. BOOST_TEST(sl2);
  91. BOOST_TEST(sl2.location() == sl.location());
  92. sl.assign(sl2);
  93. BOOST_TEST(sl.is_loaded());
  94. BOOST_TEST(sl);
  95. BOOST_TEST(sl2.is_loaded());
  96. BOOST_TEST(sl2);
  97. BOOST_TEST(sl2.location() == sl.location());
  98. sl2.assign(sl);
  99. BOOST_TEST(sl.is_loaded());
  100. BOOST_TEST(sl);
  101. BOOST_TEST(sl2.is_loaded());
  102. BOOST_TEST(sl2);
  103. BOOST_TEST(sl2.location() == sl.location());
  104. // Assigning an empty shared library
  105. sl2.assign(shared_library());
  106. BOOST_TEST(sl.is_loaded());
  107. BOOST_TEST(sl);
  108. BOOST_TEST(!sl2.is_loaded());
  109. BOOST_TEST(!sl2);
  110. boost::dll::fs::error_code ec;
  111. BOOST_TEST(sl2.location(ec) != sl.location());
  112. BOOST_TEST(ec);
  113. }
  114. {
  115. boost::dll::fs::error_code ec;
  116. shared_library sl(shared_library_path, ec);
  117. BOOST_TEST(sl.is_loaded());
  118. BOOST_TEST(sl);
  119. BOOST_TEST(!ec);
  120. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  121. BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path));
  122. BOOST_TEST(!ec);
  123. // Checking self assignment #1
  124. sl.assign(sl);
  125. BOOST_TEST(sl.is_loaded());
  126. BOOST_TEST(sl);
  127. BOOST_TEST(!ec);
  128. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  129. BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path));
  130. // Checking self assignment #2
  131. sl.assign(sl, ec);
  132. BOOST_TEST(sl.is_loaded());
  133. BOOST_TEST(sl);
  134. BOOST_TEST(!ec);
  135. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  136. BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path));
  137. }
  138. {
  139. shared_library sl;
  140. BOOST_TEST(!sl.is_loaded());
  141. sl.assign(sl);
  142. BOOST_TEST(!sl);
  143. shared_library sl2(sl);
  144. BOOST_TEST(!sl);
  145. BOOST_TEST(!sl2);
  146. sl2.assign(sl);
  147. BOOST_TEST(!sl);
  148. BOOST_TEST(!sl2);
  149. }
  150. {
  151. shared_library sl;
  152. sl.load(shared_library_path);
  153. BOOST_TEST(sl.is_loaded());
  154. BOOST_TEST(sl);
  155. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  156. }
  157. {
  158. shared_library sl;
  159. boost::dll::fs::error_code ec;
  160. sl.load(shared_library_path, ec);
  161. BOOST_TEST(sl.is_loaded());
  162. BOOST_TEST(sl);
  163. BOOST_TEST(!ec);
  164. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  165. }
  166. {
  167. shared_library sl(shared_library_path, load_mode::load_with_altered_search_path );
  168. BOOST_TEST(sl.is_loaded());
  169. BOOST_TEST(sl);
  170. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  171. }
  172. {
  173. boost::dll::fs::error_code ec;
  174. shared_library sl(shared_library_path, load_mode::load_with_altered_search_path, ec);
  175. BOOST_TEST(sl.is_loaded());
  176. BOOST_TEST(sl);
  177. BOOST_TEST(!ec);
  178. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  179. BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path));
  180. BOOST_TEST(!ec);
  181. }
  182. {
  183. boost::dll::fs::error_code ec;
  184. shared_library sl(shared_library_path, load_mode::search_system_folders, ec);
  185. BOOST_TEST(sl.is_loaded());
  186. BOOST_TEST(sl);
  187. BOOST_TEST(!ec);
  188. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  189. BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path));
  190. BOOST_TEST(!ec);
  191. }
  192. {
  193. try {
  194. #if BOOST_OS_WINDOWS
  195. boost::dll::shared_library("winmm.dll");
  196. #elif BOOST_OS_LINUX
  197. boost::dll::shared_library("libdl.so");
  198. #endif
  199. BOOST_TEST(false);
  200. } catch (...) {}
  201. }
  202. {
  203. try {
  204. #if BOOST_OS_WINDOWS
  205. boost::dll::shared_library("winmm", load_mode::search_system_folders | load_mode::append_decorations);
  206. #elif BOOST_OS_LINUX
  207. boost::dll::shared_library("dl", boost::dll::load_mode::search_system_folders | load_mode::append_decorations);
  208. #endif
  209. } catch (...) {
  210. BOOST_TEST(false);
  211. }
  212. }
  213. {
  214. shared_library sl;
  215. sl.load(shared_library_path, load_mode::load_with_altered_search_path);
  216. BOOST_TEST(sl.is_loaded());
  217. BOOST_TEST(sl);
  218. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  219. }
  220. {
  221. shared_library sl;
  222. boost::dll::fs::error_code ec;
  223. sl.load(shared_library_path, load_mode::load_with_altered_search_path, ec);
  224. BOOST_TEST(sl.is_loaded());
  225. BOOST_TEST(sl);
  226. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  227. }
  228. {
  229. shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global);
  230. BOOST_TEST(sl.is_loaded());
  231. BOOST_TEST(sl);
  232. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  233. }
  234. {
  235. shared_library sl(shared_library_path, load_mode::rtld_local);
  236. BOOST_TEST(sl.is_loaded());
  237. BOOST_TEST(sl);
  238. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  239. }
  240. {
  241. shared_library sl(shared_library_path, load_mode::rtld_now);
  242. BOOST_TEST(sl.is_loaded());
  243. BOOST_TEST(sl);
  244. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  245. }
  246. {
  247. fs_copy_guard guard(shared_library_path);
  248. boost::dll::fs::path platform_independent_path = guard.actual_path_;
  249. platform_independent_path.replace_extension();
  250. if (platform_independent_path.filename().wstring().find(L"lib") == 0) {
  251. platform_independent_path
  252. = platform_independent_path.parent_path() / platform_independent_path.filename().wstring().substr(3);
  253. }
  254. std::cerr << "platform_independent_path: " << platform_independent_path << '\n';
  255. shared_library sl(platform_independent_path, load_mode::append_decorations);
  256. BOOST_TEST(sl.is_loaded());
  257. BOOST_TEST(sl);
  258. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  259. sl.unload();
  260. BOOST_TEST(!sl.is_loaded());
  261. BOOST_TEST(!sl);
  262. }
  263. {
  264. shared_library sl(shared_library_path, load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path);
  265. BOOST_TEST(sl.is_loaded());
  266. BOOST_TEST(sl);
  267. }
  268. {
  269. boost::dll::fs::error_code ec;
  270. shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec);
  271. BOOST_TEST(sl.is_loaded());
  272. BOOST_TEST(sl);
  273. BOOST_TEST(!ec);
  274. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  275. }
  276. {
  277. shared_library sl;
  278. sl.load(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global);
  279. BOOST_TEST(sl.is_loaded());
  280. BOOST_TEST(sl);
  281. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  282. }
  283. { // Non-default flags with assignment
  284. shared_library sl(shared_library_path,
  285. load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path
  286. // `load_mode::rtld_deepbind` is incompatible with sanitizers:
  287. // You are trying to dlopen a libtest_library.so shared library with RTLD_DEEPBIND flag which is incompatibe with sanitizer runtime
  288. // (see https://github.com/google/sanitizers/issues/611 for details).
  289. #ifndef BOOST_TRAVISCI_BUILD
  290. | load_mode::rtld_deepbind
  291. #endif
  292. );
  293. BOOST_TEST(sl.is_loaded());
  294. BOOST_TEST(sl);
  295. boost::dll::fs::error_code ec;
  296. shared_library sl2(sl, ec);
  297. BOOST_TEST(!ec);
  298. BOOST_TEST(sl.is_loaded());
  299. BOOST_TEST(sl);
  300. BOOST_TEST(sl2.is_loaded());
  301. BOOST_TEST(sl2);
  302. BOOST_TEST(sl2.location() == sl.location());
  303. shared_library sl3(sl);
  304. BOOST_TEST(sl.is_loaded());
  305. BOOST_TEST(sl);
  306. BOOST_TEST(sl3.is_loaded());
  307. BOOST_TEST(sl3);
  308. shared_library sl4;
  309. sl4.assign(sl, ec);
  310. BOOST_TEST(!ec);
  311. BOOST_TEST(sl.is_loaded());
  312. BOOST_TEST(sl);
  313. BOOST_TEST(sl4.is_loaded());
  314. BOOST_TEST(sl4);
  315. }
  316. { // Non-default flags with assignment and error_code
  317. boost::dll::fs::error_code ec;
  318. shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec);
  319. BOOST_TEST(sl.is_loaded());
  320. BOOST_TEST(sl);
  321. BOOST_TEST(!ec);
  322. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  323. shared_library sl2(sl, ec);
  324. BOOST_TEST(!ec);
  325. BOOST_TEST(sl.is_loaded());
  326. BOOST_TEST(sl);
  327. BOOST_TEST(sl2.is_loaded());
  328. BOOST_TEST(sl2);
  329. BOOST_TEST(sl2.location() == sl.location());
  330. shared_library sl3(sl);
  331. BOOST_TEST(sl.is_loaded());
  332. BOOST_TEST(sl);
  333. BOOST_TEST(sl3.is_loaded());
  334. BOOST_TEST(sl3);
  335. BOOST_TEST(sl3.location() == sl.location());
  336. }
  337. { // self_load
  338. shared_library sl(program_location());
  339. BOOST_TEST(sl.is_loaded());
  340. BOOST_TEST(sl);
  341. std::cout << "\nProgram location: " << program_location();
  342. std::cout << "\nLibrary location: " << sl.location();
  343. BOOST_TEST( boost::dll::fs::equivalent(sl.location(), program_location()) );
  344. boost::dll::fs::error_code ec;
  345. shared_library sl2(program_location());
  346. BOOST_TEST(sl2.is_loaded());
  347. BOOST_TEST( boost::dll::fs::equivalent(sl2.location(), program_location()) );
  348. BOOST_TEST(sl2);
  349. BOOST_TEST(!ec);
  350. BOOST_TEST(sl == sl2);
  351. BOOST_TEST(!(sl < sl2 || sl2 <sl));
  352. BOOST_TEST(!(sl != sl2));
  353. sl.load(shared_library_path);
  354. BOOST_TEST(sl != sl2);
  355. BOOST_TEST(sl < sl2 || sl2 <sl);
  356. BOOST_TEST(!(sl == sl2));
  357. sl.unload();
  358. BOOST_TEST(!sl);
  359. BOOST_TEST(sl != sl2);
  360. BOOST_TEST(sl < sl2 || sl2 <sl);
  361. BOOST_TEST(!(sl == sl2));
  362. sl2.unload();
  363. BOOST_TEST(!sl2);
  364. BOOST_TEST(sl == sl2);
  365. BOOST_TEST(!(sl < sl2 || sl2 <sl));
  366. BOOST_TEST(!(sl != sl2));
  367. // assigning self
  368. sl.load(program_location());
  369. sl2 = sl;
  370. BOOST_TEST(sl == sl2);
  371. BOOST_TEST(sl.location() == sl2.location());
  372. }
  373. {
  374. shared_library sl;
  375. boost::dll::fs::error_code ec;
  376. sl.load(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec);
  377. BOOST_TEST(sl.is_loaded());
  378. BOOST_TEST(sl);
  379. BOOST_TEST(!ec);
  380. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  381. sl.load(program_location());
  382. BOOST_TEST(sl.is_loaded());
  383. BOOST_TEST(sl);
  384. sl.load(program_location());
  385. BOOST_TEST(sl.is_loaded());
  386. BOOST_TEST(sl);
  387. BOOST_TEST(!ec);
  388. }
  389. { // self_load
  390. shared_library sl;
  391. boost::dll::fs::error_code ec;
  392. sl.load(program_location());
  393. BOOST_TEST(sl.is_loaded());
  394. BOOST_TEST(sl);
  395. BOOST_TEST(!ec);
  396. }
  397. { // unload
  398. shared_library sl(shared_library_path);
  399. BOOST_TEST(sl.is_loaded());
  400. BOOST_TEST(sl);
  401. BOOST_TEST(lib_path_equal(sl.location(), shared_library_path));
  402. sl.unload();
  403. BOOST_TEST(!sl.is_loaded());
  404. BOOST_TEST(!sl);
  405. }
  406. { // error_code load calls test
  407. boost::dll::fs::error_code ec;
  408. shared_library sl(shared_library_path / "dir_that_does_not_exist", ec);
  409. BOOST_TEST(ec);
  410. BOOST_TEST(!sl.is_loaded());
  411. BOOST_TEST(!sl);
  412. boost::dll::fs::path bad_path(shared_library_path);
  413. bad_path += ".1.1.1.1.1.1";
  414. sl.load(bad_path, ec);
  415. BOOST_TEST(ec);
  416. BOOST_TEST(!sl.is_loaded());
  417. BOOST_TEST(!sl);
  418. sl.load(shared_library_path, ec);
  419. BOOST_TEST(!ec);
  420. BOOST_TEST(sl.is_loaded());
  421. BOOST_TEST(sl);
  422. shared_library sl2(bad_path, ec);
  423. BOOST_TEST(ec);
  424. BOOST_TEST(!sl2.is_loaded());
  425. BOOST_TEST(!sl2);
  426. shared_library sl3(shared_library_path, ec);
  427. BOOST_TEST(!ec);
  428. BOOST_TEST(sl3.is_loaded());
  429. BOOST_TEST(sl3);
  430. sl.load("", ec);
  431. BOOST_TEST(ec);
  432. BOOST_TEST(!sl.is_loaded());
  433. BOOST_TEST(!sl);
  434. }
  435. shared_library_path = do_find_correct_libs_path(argc, argv, "library1");
  436. fs_copy_guard guard(shared_library_path);
  437. shared_library starts_with_lib(
  438. boost::dll::fs::path(guard.actual_path_).replace_extension(),
  439. load_mode::append_decorations
  440. );
  441. starts_with_lib.load(
  442. boost::dll::fs::path(guard.actual_path_).replace_extension(),
  443. load_mode::append_decorations
  444. );
  445. return boost::report_errors();
  446. }