// Copyright 2011-2012 Renato Tegon Forti // Copyright 2015-2019 Antony Polukhin // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include "../example/b2_workarounds.hpp" #include #include // Unit Tests namespace boost { namespace dll { namespace fs { #ifdef BOOST_DLL_USE_STD_FS using std::filesystem::remove; using std::filesystem::copy; #else using boost::filesystem::remove; using boost::filesystem::copy; #endif }}} inline boost::dll::fs::path drop_version(const boost::dll::fs::path& lhs) { boost::dll::fs::path ext = lhs.filename().extension(); if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) { ext = lhs; ext.replace_extension().replace_extension().replace_extension(); return ext; } return lhs; } inline bool lib_path_equal(const boost::dll::fs::path& lhs, const boost::dll::fs::path& rhs) { const bool res = (drop_version(lhs).filename() == drop_version(rhs).filename()); if (!res) { std::cerr << "lhs != rhs: " << lhs << " != " << rhs << '\n'; } return res; } struct fs_copy_guard { const boost::dll::fs::path actual_path_; const bool same_; inline explicit fs_copy_guard(const boost::dll::fs::path& shared_library_path) : actual_path_( drop_version(shared_library_path) ) , same_(actual_path_ == shared_library_path) { if (!same_) { boost::dll::fs::error_code ignore; boost::dll::fs::remove(actual_path_, ignore); boost::dll::fs::copy(shared_library_path, actual_path_, ignore); } } inline ~fs_copy_guard() { if (!same_) { boost::dll::fs::error_code ignore; boost::dll::fs::remove(actual_path_, ignore); } } }; // Disgusting workarounds for b2 on Windows platform inline boost::dll::fs::path do_find_correct_libs_path(int argc, char* argv[], const char* lib_name) { boost::dll::fs::path ret; for (int i = 1; i < argc; ++i) { ret = argv[i]; if (ret.string().find(lib_name) != std::string::npos && b2_workarounds::is_shared_library(ret)) { return ret; } } return lib_name; } int main(int argc, char* argv[]) { using namespace boost::dll; BOOST_TEST(argc >= 3); boost::dll::fs::path shared_library_path = do_find_correct_libs_path(argc, argv, "test_library"); std::cout << "Library: " << shared_library_path; { shared_library sl(shared_library_path); BOOST_TEST(sl.is_loaded()); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); shared_library sl2; BOOST_TEST(!sl2.is_loaded()); BOOST_TEST(!sl2); swap(sl, sl2); BOOST_TEST(!sl.is_loaded()); BOOST_TEST(!sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); sl.assign(sl2); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); BOOST_TEST(sl2.location() == sl.location()); sl.assign(sl2); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); BOOST_TEST(sl2.location() == sl.location()); sl2.assign(sl); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); BOOST_TEST(sl2.location() == sl.location()); // Assigning an empty shared library sl2.assign(shared_library()); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!sl2.is_loaded()); BOOST_TEST(!sl2); boost::dll::fs::error_code ec; BOOST_TEST(sl2.location(ec) != sl.location()); BOOST_TEST(ec); } { boost::dll::fs::error_code ec; shared_library sl(shared_library_path, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); BOOST_TEST(!ec); // Checking self assignment #1 sl.assign(sl); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); // Checking self assignment #2 sl.assign(sl, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); } { shared_library sl; BOOST_TEST(!sl.is_loaded()); sl.assign(sl); BOOST_TEST(!sl); shared_library sl2(sl); BOOST_TEST(!sl); BOOST_TEST(!sl2); sl2.assign(sl); BOOST_TEST(!sl); BOOST_TEST(!sl2); } { shared_library sl; sl.load(shared_library_path); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl; boost::dll::fs::error_code ec; sl.load(shared_library_path, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl(shared_library_path, load_mode::load_with_altered_search_path ); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { boost::dll::fs::error_code ec; shared_library sl(shared_library_path, load_mode::load_with_altered_search_path, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); BOOST_TEST(!ec); } { boost::dll::fs::error_code ec; shared_library sl(shared_library_path, load_mode::search_system_folders, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); BOOST_TEST(lib_path_equal(sl.location(ec), shared_library_path)); BOOST_TEST(!ec); } { try { #if BOOST_OS_WINDOWS boost::dll::shared_library("winmm.dll"); #elif BOOST_OS_LINUX boost::dll::shared_library("libdl.so"); #endif BOOST_TEST(false); } catch (...) {} } { try { #if BOOST_OS_WINDOWS boost::dll::shared_library("winmm", load_mode::search_system_folders | load_mode::append_decorations); #elif BOOST_OS_LINUX boost::dll::shared_library("dl", boost::dll::load_mode::search_system_folders | load_mode::append_decorations); #endif } catch (...) { BOOST_TEST(false); } } { shared_library sl; sl.load(shared_library_path, load_mode::load_with_altered_search_path); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl; boost::dll::fs::error_code ec; sl.load(shared_library_path, load_mode::load_with_altered_search_path, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl(shared_library_path, load_mode::rtld_local); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl(shared_library_path, load_mode::rtld_now); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { fs_copy_guard guard(shared_library_path); boost::dll::fs::path platform_independent_path = guard.actual_path_; platform_independent_path.replace_extension(); if (platform_independent_path.filename().wstring().find(L"lib") == 0) { platform_independent_path = platform_independent_path.parent_path() / platform_independent_path.filename().wstring().substr(3); } std::cerr << "platform_independent_path: " << platform_independent_path << '\n'; shared_library sl(platform_independent_path, load_mode::append_decorations); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); sl.unload(); BOOST_TEST(!sl.is_loaded()); BOOST_TEST(!sl); } { shared_library sl(shared_library_path, load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); } { boost::dll::fs::error_code ec; shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { shared_library sl; sl.load(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); } { // Non-default flags with assignment shared_library sl(shared_library_path, load_mode::rtld_now | load_mode::rtld_global | load_mode::load_with_altered_search_path // `load_mode::rtld_deepbind` is incompatible with sanitizers: // You are trying to dlopen a libtest_library.so shared library with RTLD_DEEPBIND flag which is incompatibe with sanitizer runtime // (see https://github.com/google/sanitizers/issues/611 for details). #ifndef BOOST_TRAVISCI_BUILD | load_mode::rtld_deepbind #endif ); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); boost::dll::fs::error_code ec; shared_library sl2(sl, ec); BOOST_TEST(!ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); BOOST_TEST(sl2.location() == sl.location()); shared_library sl3(sl); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl3.is_loaded()); BOOST_TEST(sl3); shared_library sl4; sl4.assign(sl, ec); BOOST_TEST(!ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl4.is_loaded()); BOOST_TEST(sl4); } { // Non-default flags with assignment and error_code boost::dll::fs::error_code ec; shared_library sl(shared_library_path, load_mode::rtld_lazy | load_mode::rtld_global, ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(!ec); BOOST_TEST(lib_path_equal(sl.location(), shared_library_path)); shared_library sl2(sl, ec); BOOST_TEST(!ec); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl2.is_loaded()); BOOST_TEST(sl2); BOOST_TEST(sl2.location() == sl.location()); shared_library sl3(sl); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); BOOST_TEST(sl3.is_loaded()); BOOST_TEST(sl3); BOOST_TEST(sl3.location() == sl.location()); } { // self_load shared_library sl(program_location()); BOOST_TEST(sl.is_loaded()); BOOST_TEST(sl); std::cout << "\nProgram location: " << program_location(); std::cout << "\nLibrary location: " << sl.location(); BOOST_TEST( boost::dll::fs::equivalent(sl.location(), program_location()) ); boost::dll::fs::error_code ec; shared_library sl2(program_location()); BOOST_TEST(sl2.is_loaded()); BOOST_TEST( boost::dll::fs::equivalent(sl2.location(), program_location()) ); BOOST_TEST(sl2); BOOST_TEST(!ec); BOOST_TEST(sl == sl2); BOOST_TEST(!(sl < sl2 || sl2