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