1 // Copyright 2011-2012 Renato Tegon Forti
2 // Copyright Antony Polukhin, 2015-2022
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)
8 // For more information, see http://www.boost.org
10 #include "../example/b2_workarounds.hpp"
11 #include <boost/dll.hpp>
12 #include <boost/core/lightweight_test.hpp>
15 namespace boost
{ namespace dll
{ namespace fs
{
17 #ifdef BOOST_DLL_USE_STD_FS
18 using std::filesystem::remove
;
19 using std::filesystem::copy
;
21 using boost::filesystem::remove
;
22 using boost::filesystem::copy
;
27 inline boost::dll::fs::path
drop_version(const boost::dll::fs::path
& lhs
) {
28 boost::dll::fs::path ext
= lhs
.filename().extension();
29 if (ext
.native().size() > 1 && std::isdigit(ext
.string()[1])) {
31 ext
.replace_extension().replace_extension().replace_extension();
38 inline bool lib_path_equal(const boost::dll::fs::path
& lhs
, const boost::dll::fs::path
& rhs
) {
39 const bool res
= (drop_version(lhs
).filename() == drop_version(rhs
).filename());
41 std::cerr
<< "lhs != rhs: " << lhs
<< " != " << rhs
<< '\n';
46 struct fs_copy_guard
{
47 const boost::dll::fs::path actual_path_
;
50 inline explicit fs_copy_guard(const boost::dll::fs::path
& shared_library_path
)
51 : actual_path_( drop_version(shared_library_path
) )
52 , same_(actual_path_
== shared_library_path
)
55 boost::dll::fs::error_code ignore
;
56 boost::dll::fs::remove(actual_path_
, ignore
);
57 boost::dll::fs::copy(shared_library_path
, actual_path_
, ignore
);
61 inline ~fs_copy_guard() {
63 boost::dll::fs::error_code ignore
;
64 boost::dll::fs::remove(actual_path_
, ignore
);
69 // Disgusting workarounds for b2 on Windows platform
70 inline boost::dll::fs::path
do_find_correct_libs_path(int argc
, char* argv
[], const char* lib_name
) {
71 boost::dll::fs::path ret
;
73 for (int i
= 1; i
< argc
; ++i
) {
75 if (ret
.string().find(lib_name
) != std::string::npos
&& b2_workarounds::is_shared_library(ret
)) {
83 int main(int argc
, char* argv
[])
85 using namespace boost::dll
;
87 BOOST_TEST(argc
>= 3);
88 boost::dll::fs::path shared_library_path
= do_find_correct_libs_path(argc
, argv
, "test_library");
89 std::cout
<< "Library: " << shared_library_path
;
92 shared_library
sl(shared_library_path
);
93 BOOST_TEST(sl
.is_loaded());
94 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
97 BOOST_TEST(!sl2
.is_loaded());
101 BOOST_TEST(!sl
.is_loaded());
103 BOOST_TEST(sl2
.is_loaded());
107 BOOST_TEST(sl
.is_loaded());
109 BOOST_TEST(sl2
.is_loaded());
111 BOOST_TEST(sl2
.location() == sl
.location());
114 BOOST_TEST(sl
.is_loaded());
116 BOOST_TEST(sl2
.is_loaded());
118 BOOST_TEST(sl2
.location() == sl
.location());
121 BOOST_TEST(sl
.is_loaded());
123 BOOST_TEST(sl2
.is_loaded());
125 BOOST_TEST(sl2
.location() == sl
.location());
127 // Assigning an empty shared library
128 sl2
.assign(shared_library());
129 BOOST_TEST(sl
.is_loaded());
131 BOOST_TEST(!sl2
.is_loaded());
133 boost::dll::fs::error_code ec
;
134 BOOST_TEST(sl2
.location(ec
) != sl
.location());
139 boost::dll::fs::error_code ec
;
140 shared_library
sl(shared_library_path
, ec
);
141 BOOST_TEST(sl
.is_loaded());
144 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
145 BOOST_TEST(lib_path_equal(sl
.location(ec
), shared_library_path
));
148 // Checking self assignment #1
150 BOOST_TEST(sl
.is_loaded());
153 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
154 BOOST_TEST(lib_path_equal(sl
.location(ec
), shared_library_path
));
156 // Checking self assignment #2
158 BOOST_TEST(sl
.is_loaded());
161 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
162 BOOST_TEST(lib_path_equal(sl
.location(ec
), shared_library_path
));
167 BOOST_TEST(!sl
.is_loaded());
172 shared_library
sl2(sl
);
183 sl
.load(shared_library_path
);
184 BOOST_TEST(sl
.is_loaded());
186 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
191 boost::dll::fs::error_code ec
;
192 sl
.load(shared_library_path
, ec
);
193 BOOST_TEST(sl
.is_loaded());
196 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
200 shared_library
sl(shared_library_path
, load_mode::load_with_altered_search_path
);
201 BOOST_TEST(sl
.is_loaded());
203 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
207 boost::dll::fs::error_code ec
;
208 shared_library
sl(shared_library_path
, load_mode::load_with_altered_search_path
, ec
);
209 BOOST_TEST(sl
.is_loaded());
212 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
213 BOOST_TEST(lib_path_equal(sl
.location(ec
), shared_library_path
));
218 boost::dll::fs::error_code ec
;
219 shared_library
sl(shared_library_path
, load_mode::search_system_folders
, ec
);
220 BOOST_TEST(sl
.is_loaded());
223 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
224 BOOST_TEST(lib_path_equal(sl
.location(ec
), shared_library_path
));
231 boost::dll::shared_library("winmm.dll");
234 boost::dll::shared_library("libdl.so");
243 boost::dll::shared_library("winmm", load_mode::search_system_folders
| load_mode::append_decorations
);
245 boost::dll::shared_library("dl", boost::dll::load_mode::search_system_folders
| load_mode::append_decorations
);
254 sl
.load(shared_library_path
, load_mode::load_with_altered_search_path
);
255 BOOST_TEST(sl
.is_loaded());
257 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
262 boost::dll::fs::error_code ec
;
263 sl
.load(shared_library_path
, load_mode::load_with_altered_search_path
, ec
);
264 BOOST_TEST(sl
.is_loaded());
266 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
270 shared_library
sl(shared_library_path
, load_mode::rtld_lazy
| load_mode::rtld_global
);
271 BOOST_TEST(sl
.is_loaded());
273 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
277 shared_library
sl(shared_library_path
, load_mode::rtld_local
);
278 BOOST_TEST(sl
.is_loaded());
280 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
284 shared_library
sl(shared_library_path
, load_mode::rtld_now
);
285 BOOST_TEST(sl
.is_loaded());
287 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
291 fs_copy_guard
guard(shared_library_path
);
293 boost::dll::fs::path platform_independent_path
= guard
.actual_path_
;
294 platform_independent_path
.replace_extension();
295 if (platform_independent_path
.filename().wstring().find(L
"lib") == 0) {
296 platform_independent_path
297 = platform_independent_path
.parent_path() / platform_independent_path
.filename().wstring().substr(3);
299 std::cerr
<< "platform_independent_path: " << platform_independent_path
<< '\n';
301 shared_library
sl(platform_independent_path
, load_mode::append_decorations
);
302 BOOST_TEST(sl
.is_loaded());
304 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
307 BOOST_TEST(!sl
.is_loaded());
312 shared_library
sl(shared_library_path
, load_mode::rtld_now
| load_mode::rtld_global
| load_mode::load_with_altered_search_path
);
313 BOOST_TEST(sl
.is_loaded());
318 boost::dll::fs::error_code ec
;
319 shared_library
sl(shared_library_path
, load_mode::rtld_lazy
| load_mode::rtld_global
, ec
);
320 BOOST_TEST(sl
.is_loaded());
323 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
328 sl
.load(shared_library_path
, load_mode::rtld_lazy
| load_mode::rtld_global
);
329 BOOST_TEST(sl
.is_loaded());
331 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
335 { // Non-default flags with assignment
336 shared_library
sl(shared_library_path
,
337 load_mode::rtld_now
| load_mode::rtld_global
| load_mode::load_with_altered_search_path
339 // `load_mode::rtld_deepbind` is incompatible with sanitizers:
340 // You are trying to dlopen a libtest_library.so shared library with RTLD_DEEPBIND flag which is incompatibe with sanitizer runtime
341 // (see https://github.com/google/sanitizers/issues/611 for details).
342 #ifndef BOOST_TRAVISCI_BUILD
343 | load_mode::rtld_deepbind
347 BOOST_TEST(sl
.is_loaded());
350 boost::dll::fs::error_code ec
;
351 shared_library
sl2(sl
, ec
);
353 BOOST_TEST(sl
.is_loaded());
355 BOOST_TEST(sl2
.is_loaded());
357 BOOST_TEST(sl2
.location() == sl
.location());
359 shared_library
sl3(sl
);
360 BOOST_TEST(sl
.is_loaded());
362 BOOST_TEST(sl3
.is_loaded());
368 BOOST_TEST(sl
.is_loaded());
370 BOOST_TEST(sl4
.is_loaded());
374 { // Non-default flags with assignment and error_code
375 boost::dll::fs::error_code ec
;
376 shared_library
sl(shared_library_path
, load_mode::rtld_lazy
| load_mode::rtld_global
, ec
);
377 BOOST_TEST(sl
.is_loaded());
380 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
382 shared_library
sl2(sl
, ec
);
384 BOOST_TEST(sl
.is_loaded());
386 BOOST_TEST(sl2
.is_loaded());
388 BOOST_TEST(sl2
.location() == sl
.location());
390 shared_library
sl3(sl
);
391 BOOST_TEST(sl
.is_loaded());
393 BOOST_TEST(sl3
.is_loaded());
395 BOOST_TEST(sl3
.location() == sl
.location());
399 shared_library
sl(program_location());
400 BOOST_TEST(sl
.is_loaded());
402 std::cout
<< "\nProgram location: " << program_location();
403 std::cout
<< "\nLibrary location: " << sl
.location();
404 BOOST_TEST( boost::dll::fs::equivalent(sl
.location(), program_location()) );
406 boost::dll::fs::error_code ec
;
407 shared_library
sl2(program_location());
408 BOOST_TEST(sl2
.is_loaded());
409 BOOST_TEST( boost::dll::fs::equivalent(sl2
.location(), program_location()) );
413 BOOST_TEST(sl
== sl2
);
414 BOOST_TEST(!(sl
< sl2
|| sl2
<sl
));
415 BOOST_TEST(!(sl
!= sl2
));
417 sl
.load(shared_library_path
);
418 BOOST_TEST(sl
!= sl2
);
419 BOOST_TEST(sl
< sl2
|| sl2
<sl
);
420 BOOST_TEST(!(sl
== sl2
));
424 BOOST_TEST(sl
!= sl2
);
425 BOOST_TEST(sl
< sl2
|| sl2
<sl
);
426 BOOST_TEST(!(sl
== sl2
));
430 BOOST_TEST(sl
== sl2
);
431 BOOST_TEST(!(sl
< sl2
|| sl2
<sl
));
432 BOOST_TEST(!(sl
!= sl2
));
435 sl
.load(program_location());
437 BOOST_TEST(sl
== sl2
);
438 BOOST_TEST(sl
.location() == sl2
.location());
443 boost::dll::fs::error_code ec
;
444 sl
.load(shared_library_path
, load_mode::rtld_lazy
| load_mode::rtld_global
, ec
);
445 BOOST_TEST(sl
.is_loaded());
448 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
450 sl
.load(program_location());
451 BOOST_TEST(sl
.is_loaded());
454 sl
.load(program_location());
455 BOOST_TEST(sl
.is_loaded());
462 boost::dll::fs::error_code ec
;
463 sl
.load(program_location());
464 BOOST_TEST(sl
.is_loaded());
470 shared_library
sl(shared_library_path
);
471 BOOST_TEST(sl
.is_loaded());
473 BOOST_TEST(lib_path_equal(sl
.location(), shared_library_path
));
475 BOOST_TEST(!sl
.is_loaded());
480 { // error_code load calls test
481 boost::dll::fs::error_code ec
;
482 shared_library
sl(shared_library_path
/ "dir_that_does_not_exist", ec
);
484 BOOST_TEST(!sl
.is_loaded());
487 boost::dll::fs::path
bad_path(shared_library_path
);
488 bad_path
+= ".1.1.1.1.1.1";
489 sl
.load(bad_path
, ec
);
491 BOOST_TEST(!sl
.is_loaded());
494 sl
.load(shared_library_path
, ec
);
496 BOOST_TEST(sl
.is_loaded());
499 shared_library
sl2(bad_path
, ec
);
501 BOOST_TEST(!sl2
.is_loaded());
504 shared_library
sl3(shared_library_path
, ec
);
506 BOOST_TEST(sl3
.is_loaded());
511 BOOST_TEST(!sl
.is_loaded());
516 shared_library_path
= do_find_correct_libs_path(argc
, argv
, "library1");
517 fs_copy_guard
guard(shared_library_path
);
518 shared_library
starts_with_lib(
519 boost::dll::fs::path(guard
.actual_path_
).replace_extension(),
520 load_mode::append_decorations
523 starts_with_lib
.load(
524 boost::dll::fs::path(guard
.actual_path_
).replace_extension(),
525 load_mode::append_decorations
528 return boost::report_errors();