1 // (C) Copyright Gennadiy Rozental 2005-2014.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // See http://www.boost.org/libs/test for the library home page.
7
8 // Boost.Test
9 #ifndef BOOST_TEST_DYN_LINK
10 #define BOOST_TEST_DYN_LINK
11 #endif
12 #include <boost/test/unit_test.hpp>
13
14 // Boost.Runtime.Param
15 //#include <boost/test/utils/runtime/cla/named_parameter.hpp>
16 #include <boost/test/utils/named_params.hpp>
17 #include <boost/test/utils/runtime/cla/parser.hpp>
18
19 namespace rt = boost::runtime;
20 namespace cla = boost::runtime::cla;
21
22 // STL
23 #include <iostream>
24
25 //_________________________________________________________________//
26
27 // System API
28
29 namespace dyn_lib {
30
31 #if defined(BOOST_WINDOWS) && !defined(BOOST_DISABLE_WIN32) // WIN32 API
32
33 #include <windows.h>
34
35 typedef HINSTANCE handle;
36
37 inline handle
open(std::string const & file_name)38 open( std::string const& file_name )
39 {
40 return LoadLibrary( file_name.c_str() );
41 }
42
43 //_________________________________________________________________//
44
45 template<typename TargType>
46 inline TargType
locate_symbol(handle h,std::string const & symbol)47 locate_symbol( handle h, std::string const& symbol )
48 {
49 return reinterpret_cast<TargType>( GetProcAddress( h, symbol.c_str() ) );
50 }
51
52 //_________________________________________________________________//
53
54 inline void
close(handle h)55 close( handle h )
56 {
57 if( h )
58 FreeLibrary( h );
59 }
60
61 //_________________________________________________________________//
62
63 inline std::string
error()64 error()
65 {
66 LPTSTR msg = NULL;
67
68 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
69 NULL,
70 GetLastError(),
71 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
72 (LPTSTR)&msg,
73 0, NULL );
74
75 std::string res( msg );
76
77 if( msg )
78 LocalFree( msg );
79
80 return res;
81 }
82
83 //_________________________________________________________________//
84
85 #elif defined(BOOST_HAS_UNISTD_H) // POSIX API
86
87 #include <dlfcn.h>
88
89 #include <sys/types.h>
90 #include <sys/stat.h>
91 #include <fcntl.h>
92
93
94 typedef void* handle;
95
96 inline handle
97 open( std::string const& file_name )
98 {
99 return dlopen( file_name.c_str(), RTLD_LOCAL | RTLD_LAZY );
100 }
101
102 //_________________________________________________________________//
103
104 template<typename TargType>
105 inline TargType
106 locate_symbol( handle h, std::string const& symbol )
107 {
108 return reinterpret_cast<TargType>( dlsym( h, symbol.c_str() ) );
109 }
110
111 //_________________________________________________________________//
112
113 inline void
114 close( handle h )
115 {
116 if( h )
117 dlclose( h );
118 }
119
120 //_________________________________________________________________//
121
122 inline std::string
123 error()
124 {
125 return dlerror();
126 }
127
128 //_________________________________________________________________//
129
130 #else
131
132 #error "Dynamic library API is unknown"
133
134 #endif
135
136 } // namespace dyn_lib
137
138 //____________________________________________________________________________//
139
140 static std::string test_lib_name;
141 static std::string init_func_name( "init_unit_test" );
142
143 dyn_lib::handle test_lib_handle;
144
load_test_lib()145 bool load_test_lib()
146 {
147 typedef bool (*init_func_ptr)();
148 init_func_ptr init_func;
149
150 test_lib_handle = dyn_lib::open( test_lib_name );
151 if( !test_lib_handle )
152 throw std::logic_error( std::string("Fail to load test library: ")
153 .append( dyn_lib::error() ) );
154
155 init_func = dyn_lib::locate_symbol<init_func_ptr>( test_lib_handle, init_func_name );
156
157 if( !init_func )
158 throw std::logic_error( std::string("Can't locate test initilization function ")
159 .append( init_func_name )
160 .append( ": " )
161 .append( dyn_lib::error() ) );
162
163 return (*init_func)();
164 }
165
166 //____________________________________________________________________________//
167
main(int argc,char * argv[])168 int main( int argc, char* argv[] )
169 {
170 try {
171
172 rt::parameters_store store;
173
174 rt::parameter<rt::cstring, rt::REQUIRED_PARAM> p_test( "test" );
175 p_test.add_cla_id( "--", "test", " " );
176 store.add( p_test );
177
178 rt::parameter<rt::cstring> p_init( "init" );
179 p_init.add_cla_id( "--", "init", " " );
180 store.add( p_init );
181
182 rt::cla::parser P( store );
183
184 rt::arguments_store args_store;
185
186 P.parse( argc, argv, args_store );
187
188 test_lib_name = args_store.get<std::string>( "test" );
189 if( args_store.has("init") )
190 init_func_name = args_store.get<std::string>( "init" );
191
192 int res = ::boost::unit_test::unit_test_main( &load_test_lib, argc, argv );
193
194 ::boost::unit_test::framework::clear();
195 dyn_lib::close( test_lib_handle );
196
197 return res;
198 }
199 catch( rt::param_error const& ex ) {
200 std::cout << "Fail to parse command line arguments: " << ex.msg << std::endl;
201 return -1;
202 }
203 }
204
205 //____________________________________________________________________________//
206
207 // EOF
208