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