// Copyright 2014 Renato Tegon Forti, Antony Polukhin. // 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 #include #include #include #include #include // std::set_terminate #include // ::signal // Makes global error variables dirty. Useful for preventing issues like https://github.com/boostorg/dll/issues/16 void make_error_code_dirty() { using namespace std; (void)log(-1.0); #if BOOST_OS_WINDOWS boost::winapi::WCHAR_ path_hldr[10]; int some_invalid_value_for_handle = 0xFF004242; boost::winapi::HMODULE_ some_invalid_handle; memcpy(&some_invalid_handle, &some_invalid_value_for_handle, sizeof(some_invalid_value_for_handle)); boost::winapi::GetModuleFileNameW(some_invalid_handle, path_hldr, 10); #endif } // lib functions typedef float (lib_version_func)(); typedef void (say_hello_func) (); typedef int (increment) (int); // exe function extern "C" int BOOST_SYMBOL_EXPORT exef() { return 15; } extern "C" void BOOST_SYMBOL_EXPORT my_terminate_handler() { std::abort(); } extern "C" void BOOST_SYMBOL_EXPORT my_signal_handler(int) { std::abort(); } void internal_function() {} int internal_variable = 1; // Unit Tests int main(int argc, char* argv[]) { using namespace boost::dll; boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv); BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos); make_error_code_dirty(); shared_library lib(shared_library_path); std::cout << std::endl; std::cout << "shared_library: " << shared_library_path << std::endl; std::cout << "symbol_location: " << symbol_location(lib.get("integer_g")) << std::endl; std::cout << "lib.location(): " << lib.location() << std::endl; BOOST_TEST( symbol_location(lib.get("integer_g")) == lib.location() ); make_error_code_dirty(); BOOST_TEST( symbol_location(lib.get("say_hello")) == lib.location() ); BOOST_TEST( symbol_location(lib.get("lib_version")) == lib.location() ); make_error_code_dirty(); BOOST_TEST( symbol_location(lib.get("const_integer_g")) == lib.location() ); // Checking that symbols are still available, after another load+unload of the library { shared_library sl2(shared_library_path); } BOOST_TEST( symbol_location(lib.get("integer_g")) == lib.location() ); make_error_code_dirty(); // Checking aliases BOOST_TEST( symbol_location(lib.get&)>("foo_bar")) == lib.location() ); BOOST_TEST( symbol_location(lib.get_alias&)>("foo_bar")) == lib.location() ); BOOST_TEST( symbol_location(lib.get("foo_variable")) == lib.location() ); BOOST_TEST( symbol_location(lib.get_alias("foo_variable")) == lib.location() ); { // self make_error_code_dirty(); shared_library sl(program_location()); make_error_code_dirty(); BOOST_TEST( (boost::dll::fs::equivalent(symbol_location(sl.get("exef")), argv[0])) ); } { // self with error_code boost::dll::fs::error_code ec; shared_library sl(program_location(ec)); BOOST_TEST(!ec); BOOST_TEST( (boost::dll::fs::equivalent(symbol_location(sl.get("exef"), ec), argv[0])) ); BOOST_TEST(!ec); symbol_location(&sl.get("exef"), ec); BOOST_TEST(ec); } std::cout << "\ninternal_function: " << symbol_location(internal_function); std::cout << "\nargv[0] : " << boost::filesystem::absolute(argv[0]); BOOST_TEST( (boost::dll::fs::equivalent(symbol_location(internal_function), argv[0])) ); BOOST_TEST( (boost::dll::fs::equivalent(symbol_location(internal_variable), argv[0])) ); make_error_code_dirty(); BOOST_TEST( (boost::dll::fs::equivalent(this_line_location(), argv[0])) ); { // this_line_location with error_code boost::dll::fs::error_code ec; make_error_code_dirty(); BOOST_TEST( (boost::dll::fs::equivalent(this_line_location(ec), argv[0])) ); BOOST_TEST(!ec); } BOOST_TEST( lib.get_alias("module_location_from_itself")() == lib.location() ); // Checking docs content std::cout << "\nsymbol_location(std::cerr); // " << symbol_location(std::cerr); std::cout << "\nsymbol_location(std::puts); // " << symbol_location(std::puts); std::set_terminate(&my_terminate_handler); BOOST_TEST((boost::dll::fs::equivalent( symbol_location_ptr(std::set_terminate(0)), argv[0] ))); { boost::dll::fs::error_code ec; boost::dll::fs::path p = symbol_location_ptr(std::set_terminate(0), ec); BOOST_TEST(ec || !p.empty()); } { boost::dll::fs::error_code ec; symbol_location(std::set_terminate(0), ec), BOOST_TEST(ec); } { std::set_terminate(&my_terminate_handler); boost::dll::fs::error_code ec; make_error_code_dirty(); symbol_location(std::set_terminate(0), ec), BOOST_TEST(ec); } { boost::dll::fs::error_code ec; ::signal(SIGSEGV, &my_signal_handler); boost::dll::fs::path p = symbol_location_ptr(::signal(SIGSEGV, SIG_DFL), ec); BOOST_TEST((boost::dll::fs::equivalent( p, argv[0] )) || ec); } { ::signal(SIGSEGV, &my_signal_handler); boost::dll::fs::error_code ec; make_error_code_dirty(); symbol_location(::signal(SIGSEGV, SIG_DFL), ec); BOOST_TEST(ec); } return boost::report_errors(); }