Imported Upstream version 1.64.0
[platform/upstream/boost.git] / libs / dll / test / cpp_load_test.cpp
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
180     BOOST_TEST((oc.*get)() == 0);           BOOST_TEST(this_dll == this_exe);
181
182     ctor_i.call_standard(&oc, 12);          BOOST_TEST(this_dll == this_exe);
183
184     BOOST_TEST(static_val == 12);
185     BOOST_TEST((oc.*get)() == 456);         BOOST_TEST(this_dll == this_exe);
186     (oc.*set)(42);
187     BOOST_TEST((oc.*get)() == 42);          BOOST_TEST(this_dll == this_exe);
188
189
190     BOOST_TEST((oc.*func_dd)(3,2)   == 6);  BOOST_TEST(this_dll == this_exe);
191     BOOST_TEST((oc.*func_ii)(1,2)   == 3);  BOOST_TEST(this_dll == this_exe);
192     BOOST_TEST((oc.*func_ddc)(10,2) == 5);  BOOST_TEST(this_dll == this_exe);
193     BOOST_TEST((oc.*func_iiv)(9,2)  == 7);  BOOST_TEST(this_dll == this_exe);
194
195     dtor.call_standard(&oc);                BOOST_TEST(this_dll == this_exe);
196     BOOST_TEST(static_val == 0);
197
198     const auto& ti = sm.get_type_info<override_class>();
199     BOOST_TEST(ti.name() != 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