]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2016 Klemens Morgenstern |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | // For more information, see http://www.boost.org | |
8 | ||
9 | #include <boost/predef.h> | |
10 | ||
11 | #if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) | |
12 | ||
13 | #include "../example/b2_workarounds.hpp" | |
14 | ||
15 | #include <boost/dll/smart_library.hpp> | |
16 | #include <boost/core/lightweight_test.hpp> | |
17 | #include <boost/filesystem.hpp> | |
18 | #include <boost/variant.hpp> | |
19 | ||
20 | #include <iostream> | |
21 | ||
22 | struct override_class | |
23 | { | |
24 | int arr[32]; | |
25 | }; | |
26 | ||
27 | ||
28 | int main(int argc, char* argv[]) | |
29 | { | |
30 | using namespace boost::dll; | |
31 | using namespace boost::dll::experimental; | |
32 | boost::filesystem::path pt = b2_workarounds::first_lib_from_argv(argc, argv); | |
33 | ||
34 | BOOST_TEST(!pt.empty()); | |
35 | std::cout << "Library: " << pt << std::endl; | |
36 | ||
37 | smart_library sm(pt); | |
38 | ||
39 | auto& unscoped_var = sm.get_variable<int>("unscoped_var"); | |
40 | BOOST_TEST(unscoped_var == 42); | |
41 | ||
42 | auto& unscoped_c_var = sm.get_variable<const double>("unscoped_c_var"); | |
43 | BOOST_TEST(unscoped_c_var == 1.234); | |
44 | ||
45 | ||
46 | auto& sp_variable = sm.get_variable<double>("some_space::variable"); | |
47 | BOOST_TEST(sp_variable == 0.2); | |
48 | ||
49 | ||
50 | auto scoped_fun = sm.get_function<const int&()>("some_space::scoped_fun"); | |
51 | BOOST_TEST(scoped_fun != nullptr); | |
52 | { | |
53 | auto &res = scoped_fun(); | |
54 | const int expected = 0xDEADBEEF; | |
55 | BOOST_TEST(res == expected); | |
56 | } | |
57 | ||
58 | auto ovl1 = sm.get_function<void(int)> ("overloaded"); | |
59 | auto ovl2 = sm.get_function<void(double)>("overloaded"); | |
60 | ||
61 | BOOST_TEST(ovl1 != nullptr); | |
62 | BOOST_TEST(ovl2 != nullptr); | |
63 | BOOST_TEST(reinterpret_cast<void*>(ovl1) != reinterpret_cast<void*>(ovl2)); | |
64 | ||
65 | ovl1(12); | |
66 | BOOST_TEST(unscoped_var == 12); | |
67 | ovl2(5.0); | |
68 | BOOST_TEST(sp_variable == 5.0); | |
69 | ||
70 | ||
71 | ||
72 | auto var1 = sm.get_function<void(boost::variant<int, double> &)>("use_variant"); | |
73 | auto var2 = sm.get_function<void(boost::variant<double, int> &)>("use_variant"); | |
74 | ||
75 | BOOST_TEST(var1 != nullptr); | |
76 | BOOST_TEST(var2 != nullptr); | |
77 | BOOST_TEST(reinterpret_cast<void*>(var1) != reinterpret_cast<void*>(var2)); | |
78 | ||
79 | { | |
80 | boost::variant<int, double> v1 = 232.22; | |
81 | boost::variant<double, int> v2 = -1; | |
82 | ||
83 | var1(v1); | |
84 | var2(v2); | |
85 | ||
86 | struct : boost::static_visitor<void> | |
87 | { | |
88 | void operator()(double) {BOOST_TEST(false);} | |
89 | void operator()(int i) {BOOST_TEST(i == 42);} | |
90 | } vis1; | |
91 | ||
92 | struct : boost::static_visitor<void> | |
93 | { | |
94 | void operator()(double d) {BOOST_TEST(d == 3.124);} | |
95 | void operator()(int ) {BOOST_TEST(false);} | |
96 | } vis2; | |
97 | ||
98 | boost::apply_visitor(vis1, v1); | |
99 | boost::apply_visitor(vis2, v2); | |
100 | ||
101 | } | |
102 | ||
103 | /* now test the class stuff */ | |
104 | ||
105 | //first we import and test the global variables | |
106 | ||
107 | auto& father_val = sm.get_variable<int>("some_space::father_value"); | |
108 | auto& static_val = sm.get_variable<int>("some_space::some_class::value"); | |
109 | BOOST_TEST(father_val == 12); | |
110 | BOOST_TEST(static_val == -1); | |
111 | ||
112 | //now get the static function. | |
113 | auto set_value = sm.get_function<void(const int &)>("some_space::some_class::set_value"); | |
114 | BOOST_TEST(set_value != nullptr); | |
115 | ||
116 | set_value(42); | |
117 | BOOST_TEST(static_val == 42); //alright, static method works. | |
118 | ||
119 | ||
120 | //alright, now import the class members | |
121 | //first add the type alias. | |
122 | sm.add_type_alias<override_class>("some_space::some_class"); | |
123 | ||
124 | auto set = sm.get_mem_fn<override_class, void(int)>("set"); | |
125 | ||
126 | ||
127 | try { | |
128 | sm.get_mem_fn<override_class, int()>("get"); | |
129 | BOOST_TEST(false); | |
130 | } catch(boost::system::system_error &) {} | |
131 | auto get = sm.get_mem_fn<const override_class, int()>("get"); | |
132 | ||
133 | BOOST_TEST(get != nullptr); | |
134 | BOOST_TEST(set != nullptr); | |
135 | ||
136 | auto func_dd = sm.get_mem_fn<override_class, double(double, double)>("func"); | |
137 | auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func"); | |
138 | auto func_iiv = sm.get_mem_fn<volatile override_class, int(int, int)> ("func"); | |
139 | auto func_ddc = sm.get_mem_fn<const volatile override_class, double(double, double)>("func"); | |
140 | ||
141 | ||
142 | BOOST_TEST(func_dd != nullptr); | |
143 | BOOST_TEST(func_ii != nullptr); | |
144 | ||
145 | ||
146 | auto ctor_v = sm.get_constructor<override_class()>(); | |
147 | auto ctor_i = sm.get_constructor<override_class(int)>(); | |
148 | ||
149 | auto dtor = sm.get_destructor<override_class>(); | |
150 | ||
151 | //actually never used. | |
152 | if (ctor_v.has_allocating()) | |
153 | { | |
154 | //allocate | |
155 | auto p = ctor_v.call_allocating(); | |
156 | ||
157 | //assert it works | |
158 | auto val = (p->*get)(); | |
159 | BOOST_TEST(val == 123); | |
160 | //deallocate | |
161 | dtor.call_deleting(p); | |
162 | //now i cannot assert that it deletes, since it would crash. | |
163 | } | |
164 | //More tests to assure the correct this-ptr | |
165 | ||
166 | typedef override_class * override_class_p; | |
167 | override_class_p &this_dll = sm.shared_lib().get<override_class_p>("this_"); | |
168 | ||
169 | ||
170 | //ok, now load the ctor/dtor | |
171 | override_class oc; | |
172 | ||
173 | override_class_p this_exe = &oc; | |
174 | ||
175 | for (auto & i : oc.arr) | |
176 | i = 0; | |
177 | ||
178 | ||
179 | BOOST_TEST((oc.*get)() == 0); BOOST_TEST(this_dll == this_exe); | |
180 | ||
181 | ctor_i.call_standard(&oc, 12); BOOST_TEST(this_dll == this_exe); | |
182 | ||
183 | BOOST_TEST(static_val == 12); | |
184 | BOOST_TEST((oc.*get)() == 456); BOOST_TEST(this_dll == this_exe); | |
185 | (oc.*set)(42); | |
186 | BOOST_TEST((oc.*get)() == 42); BOOST_TEST(this_dll == this_exe); | |
187 | ||
188 | ||
189 | BOOST_TEST((oc.*func_dd)(3,2) == 6); BOOST_TEST(this_dll == this_exe); | |
190 | BOOST_TEST((oc.*func_ii)(1,2) == 3); BOOST_TEST(this_dll == this_exe); | |
191 | BOOST_TEST((oc.*func_ddc)(10,2) == 5); BOOST_TEST(this_dll == this_exe); | |
192 | BOOST_TEST((oc.*func_iiv)(9,2) == 7); BOOST_TEST(this_dll == this_exe); | |
193 | ||
194 | dtor.call_standard(&oc); BOOST_TEST(this_dll == this_exe); | |
195 | BOOST_TEST(static_val == 0); | |
196 | ||
197 | const auto & ti = sm.get_type_info<override_class>(); | |
198 | ||
199 | BOOST_TEST(&ti != nullptr); | |
200 | ||
201 | ||
202 | //test the ovls helper. | |
203 | { | |
204 | namespace ex = boost::dll::experimental; | |
205 | auto &var = ex::get<double>(sm, "some_space::variable"); | |
206 | BOOST_TEST(&var == &sp_variable); | |
207 | ||
208 | auto fun = ex::get<void(int)>(sm, "overloaded"); | |
209 | BOOST_TEST(fun == ovl1); | |
210 | ||
211 | auto func_ii = sm.get_mem_fn<override_class, int(int, int)> ("func"); | |
212 | ||
213 | auto mem_fn = ex::get<override_class, int(int, int)>(sm, "func"); | |
214 | ||
215 | BOOST_TEST(mem_fn == func_ii); | |
216 | } | |
217 | ||
218 | ||
219 | return boost::report_errors(); | |
220 | } | |
221 | ||
222 | #else | |
223 | int main() {return 0;} | |
224 | #endif |