• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2 // Copyright 2015-2020 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 
8 // For more information, see http://www.boost.org
9 
10 #include "../example/b2_workarounds.hpp"
11 #include <boost/dll.hpp>
12 #include <boost/dll/runtime_symbol_info.hpp>
13 #include <boost/filesystem/operations.hpp>
14 
15 #include <boost/core/lightweight_test.hpp>
16 
17 #include <boost/predef/os.h>
18 
19 
20 #include <cmath>
21 #include <exception> // std::set_terminate
22 #include <signal.h> // ::signal
23 
24 // Makes global error variables dirty. Useful for preventing issues like https://github.com/boostorg/dll/issues/16
make_error_code_dirty()25 void make_error_code_dirty() {
26     using namespace std;
27     (void)log(-1.0);
28 
29 #if BOOST_OS_WINDOWS
30     boost::winapi::WCHAR_ path_hldr[10];
31     int some_invalid_value_for_handle = 0xFF004242;
32     boost::winapi::HMODULE_ some_invalid_handle;
33     memcpy(&some_invalid_handle, &some_invalid_value_for_handle, sizeof(some_invalid_value_for_handle));
34     boost::winapi::GetModuleFileNameW(some_invalid_handle, path_hldr, 10);
35 #endif
36 }
37 
38 
39 
40 // lib functions
41 
42 typedef float (lib_version_func)();
43 typedef void  (say_hello_func)  ();
44 typedef int   (increment)       (int);
45 
46 // exe function
exef()47 extern "C" int BOOST_SYMBOL_EXPORT exef() {
48     return 15;
49 }
50 
51 
my_terminate_handler()52 extern "C" void BOOST_SYMBOL_EXPORT my_terminate_handler() {
53     std::abort();
54 }
55 
my_signal_handler(int)56 extern "C" void BOOST_SYMBOL_EXPORT my_signal_handler(int) {
57     std::abort();
58 }
59 
internal_function()60 void internal_function() {}
61 int internal_variable = 1;
62 
63 // Unit Tests
main(int argc,char * argv[])64 int main(int argc, char* argv[]) {
65     using namespace boost::dll;
66 
67     boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv);
68     BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos);
69 
70     make_error_code_dirty();
71 
72     shared_library lib(shared_library_path);
73 
74     std::cout << std::endl;
75     std::cout << "shared_library: " << shared_library_path << std::endl;
76     std::cout << "symbol_location: " << symbol_location(lib.get<int>("integer_g")) << std::endl;
77     std::cout << "lib.location():      " << lib.location() << std::endl;
78     BOOST_TEST(
79         symbol_location(lib.get<int>("integer_g")) == lib.location()
80     );
81 
82     make_error_code_dirty();
83 
84     BOOST_TEST(
85         symbol_location(lib.get<say_hello_func>("say_hello")) == lib.location()
86     );
87 
88     BOOST_TEST(
89         symbol_location(lib.get<lib_version_func>("lib_version")) == lib.location()
90     );
91 
92     make_error_code_dirty();
93 
94     BOOST_TEST(
95         symbol_location(lib.get<const int>("const_integer_g")) == lib.location()
96     );
97 
98     // Checking that symbols are still available, after another load+unload of the library
99     { shared_library sl2(shared_library_path); }
100 
101     BOOST_TEST(
102         symbol_location(lib.get<int>("integer_g")) == lib.location()
103     );
104 
105 
106     make_error_code_dirty();
107 
108     // Checking aliases
109     BOOST_TEST(
110         symbol_location(lib.get<std::size_t(*)(const std::vector<int>&)>("foo_bar")) == lib.location()
111     );
112     BOOST_TEST(
113         symbol_location(lib.get_alias<std::size_t(const std::vector<int>&)>("foo_bar")) == lib.location()
114     );
115 
116 
117     BOOST_TEST(
118         symbol_location(lib.get<std::size_t*>("foo_variable")) == lib.location()
119     );
120     BOOST_TEST(
121         symbol_location(lib.get_alias<std::size_t>("foo_variable")) == lib.location()
122     );
123 
124     { // self
125 
126         make_error_code_dirty();
127 
128         shared_library sl(program_location());
129 
130         make_error_code_dirty();
131 
132         BOOST_TEST(
133             (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef")), argv[0]))
134         );
135     }
136 
137     { // self with error_code
138         boost::dll::fs::error_code ec;
139         shared_library sl(program_location(ec));
140         BOOST_TEST(!ec);
141 
142         BOOST_TEST(
143             (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef"), ec), argv[0]))
144         );
145         BOOST_TEST(!ec);
146 
147         symbol_location(&sl.get<int(void)>("exef"), ec);
148         BOOST_TEST(ec);
149     }
150 
151     std::cout << "\ninternal_function: " << symbol_location(internal_function);
152     std::cout << "\nargv[0]          : " << boost::filesystem::absolute(argv[0]);
153     BOOST_TEST(
154         (boost::dll::fs::equivalent(symbol_location(internal_function), argv[0]))
155     );
156 
157     BOOST_TEST(
158         (boost::dll::fs::equivalent(symbol_location(internal_variable), argv[0]))
159     );
160 
161     make_error_code_dirty();
162 
163     BOOST_TEST(
164         (boost::dll::fs::equivalent(this_line_location(), argv[0]))
165     );
166 
167     { // this_line_location with error_code
168         boost::dll::fs::error_code ec;
169         make_error_code_dirty();
170         BOOST_TEST(
171             (boost::dll::fs::equivalent(this_line_location(ec), argv[0]))
172         );
173         BOOST_TEST(!ec);
174     }
175 
176     BOOST_TEST(
177         lib.get_alias<boost::dll::fs::path()>("module_location_from_itself")() == lib.location()
178     );
179 
180     // Checking docs content
181     std::cout << "\nsymbol_location(std::cerr); // " << symbol_location(std::cerr);
182     std::cout << "\nsymbol_location(std::puts); // " << symbol_location(std::puts);
183 
184     std::set_terminate(&my_terminate_handler);
185     BOOST_TEST((boost::dll::fs::equivalent(
186         symbol_location_ptr(std::set_terminate(0)),
187         argv[0]
188     )));
189 
190     {
191         boost::dll::fs::error_code ec;
192         boost::dll::fs::path p = symbol_location_ptr(std::set_terminate(0), ec);
193         BOOST_TEST(ec || !p.empty());
194     }
195 
196     {
197         boost::dll::fs::error_code ec;
198         symbol_location(std::set_terminate(0), ec),
199         BOOST_TEST(ec);
200     }
201 
202     {
203         std::set_terminate(&my_terminate_handler);
204         boost::dll::fs::error_code ec;
205         make_error_code_dirty();
206         symbol_location(std::set_terminate(0), ec),
207         BOOST_TEST(ec);
208     }
209 
210     {
211         boost::dll::fs::error_code ec;
212         ::signal(SIGSEGV, &my_signal_handler);
213         boost::dll::fs::path p = symbol_location_ptr(::signal(SIGSEGV, SIG_DFL), ec);
214         BOOST_TEST((boost::dll::fs::equivalent(
215             p,
216             argv[0]
217         )) || ec);
218     }
219 
220     {
221         ::signal(SIGSEGV, &my_signal_handler);
222         boost::dll::fs::error_code ec;
223         make_error_code_dirty();
224         symbol_location(::signal(SIGSEGV, SIG_DFL), ec);
225         BOOST_TEST(ec);
226     }
227 
228 
229     return boost::report_errors();
230 }
231 
232