error_code_test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // error_code_test.cpp -----------------------------------------------------//
  2. // Copyright Beman Dawes 2006
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See library home page at http://www.boost.org/libs/system
  6. //----------------------------------------------------------------------------//
  7. #include <boost/config/warning_disable.hpp>
  8. #include <boost/detail/lightweight_test.hpp>
  9. #include <boost/system/error_code.hpp>
  10. #include <boost/system/cygwin_error.hpp>
  11. #include <boost/system/linux_error.hpp>
  12. #include <boost/system/windows_error.hpp>
  13. #include <iostream>
  14. #include <sstream>
  15. #include <string>
  16. #include <cstring>
  17. #include <functional>
  18. #include <boost/cerrno.hpp>
  19. // Although using directives are not the best programming practice, testing
  20. // with a boost::system using directive increases use scenario coverage.
  21. using namespace boost::system;
  22. #if defined( BOOST_WINDOWS_API )
  23. // Neither MinGW or Cygwin versions of winerror.h work if used alone, so on
  24. // either of those platforms include the full windows.h
  25. # if defined(__MINGW32__) || defined(__CYGWIN__)
  26. # include <windows.h>
  27. # else
  28. # include <winerror.h>
  29. # endif
  30. # define BOOST_ACCESS_ERROR_MACRO ERROR_ACCESS_DENIED
  31. #elif defined( BOOST_POSIX_API )
  32. # define BOOST_ACCESS_ERROR_MACRO EACCES
  33. #else
  34. # error "Only supported for POSIX and Windows"
  35. #endif
  36. namespace
  37. {
  38. void check_ostream( error_code ec, const char * expected )
  39. {
  40. std::stringstream ss;
  41. std::string s;
  42. ss << ec;
  43. ss >> s;
  44. BOOST_TEST( s == expected );
  45. }
  46. // throws_function_test ------------------------------------------------------------//
  47. // usage example
  48. int divide(int dividend, int divisor, boost::system::error_code& ec = boost::throws())
  49. {
  50. if (divisor == 0) // is there an error?
  51. {
  52. if (&ec == &boost::throws()) // throw on error
  53. throw "oops!"; // whatever exception you prefer
  54. ec = error_code(EDOM, generic_category()); // report error via error_code
  55. return 0;
  56. }
  57. if (&ec != &boost::throws()) // error reporting via error_code
  58. ec.clear();
  59. return dividend / divisor;
  60. }
  61. // test usage example
  62. void test_throws_usage()
  63. {
  64. std::cout << "Test throws() example and usage...\n";
  65. error_code ec;
  66. // no error tests
  67. BOOST_TEST_EQ((divide(10, 2)), 5); // no error, report via exception
  68. ec = make_error_code(errc::argument_out_of_domain);
  69. BOOST_TEST_EQ((divide(10, 5, ec)), 2); // no error, report via error_code
  70. BOOST_TEST(!ec);
  71. ec = make_error_code(errc::argument_out_of_domain);
  72. BOOST_TEST_EQ((divide(10, 0, ec)), 0); // error, report via error_code
  73. BOOST_TEST(ec);
  74. bool exception_thrown = false;
  75. try
  76. { divide(10, 0); } // error, report via exception
  77. catch (...)
  78. { exception_thrown = true; }
  79. BOOST_TEST(exception_thrown);
  80. //error_code should_fail(boost::throws()); // should fail at runtime
  81. //boost::throws() = ec; // should fail at runtime
  82. }
  83. }
  84. // main ------------------------------------------------------------------------------//
  85. // TODO: add hash_value tests
  86. int main( int, char ** )
  87. {
  88. std::cout << "Conversion use cases...\n";
  89. error_condition x1( errc::file_exists );
  90. //error_code x2( errc::file_exists ); // should fail to compile
  91. make_error_code(errc::file_exists);
  92. make_error_condition(errc::file_exists);
  93. std::cout << "General tests...\n";
  94. // unit tests:
  95. BOOST_TEST( generic_category() == generic_category() );
  96. BOOST_TEST( system_category() == system_category() );
  97. BOOST_TEST( generic_category() != system_category() );
  98. BOOST_TEST( system_category() != generic_category() );
  99. BOOST_TEST_NE( generic_category() < system_category(), system_category() < generic_category() );
  100. error_code ec;
  101. error_condition econd;
  102. BOOST_TEST( !ec );
  103. BOOST_TEST( ec.value() == 0 );
  104. econd = ec.default_error_condition();
  105. BOOST_TEST( econd.value() == 0 );
  106. BOOST_TEST( econd.category() == generic_category() );
  107. BOOST_TEST( ec == errc::success );
  108. BOOST_TEST( ec.category() == system_category() );
  109. BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 );
  110. BOOST_TEST( !(ec < error_code( 0, system_category() )) );
  111. BOOST_TEST( !(error_code( 0, system_category() ) < ec) );
  112. BOOST_TEST( ec < error_code( 1, system_category() ) );
  113. BOOST_TEST( !(error_code( 1, system_category() ) < ec) );
  114. error_code ec_0_system( 0, system_category() );
  115. BOOST_TEST( !ec_0_system );
  116. BOOST_TEST( ec_0_system.value() == 0 );
  117. econd = ec_0_system.default_error_condition();
  118. BOOST_TEST( econd.value() == 0 );
  119. BOOST_TEST( econd.category() == generic_category() );
  120. BOOST_TEST( ec_0_system == errc::success );
  121. BOOST_TEST( ec_0_system.category() == system_category() );
  122. BOOST_TEST( std::strcmp( ec_0_system.category().name(), "system") == 0 );
  123. check_ostream( ec_0_system, "system:0" );
  124. BOOST_TEST( ec_0_system == ec );
  125. error_code ec_1_system( 1, system_category() );
  126. BOOST_TEST( ec_1_system );
  127. BOOST_TEST( ec_1_system.value() == 1 );
  128. BOOST_TEST( ec_1_system.value() != 0 );
  129. BOOST_TEST( ec != ec_1_system );
  130. BOOST_TEST( ec_0_system != ec_1_system );
  131. check_ostream( ec_1_system, "system:1" );
  132. ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() );
  133. BOOST_TEST( ec );
  134. BOOST_TEST( ec.value() == BOOST_ACCESS_ERROR_MACRO );
  135. econd = ec.default_error_condition();
  136. BOOST_TEST( econd.value() == static_cast<int>(errc::permission_denied) );
  137. BOOST_TEST( econd.category() == generic_category() );
  138. BOOST_TEST( econd == error_condition( errc::permission_denied, generic_category() ) );
  139. BOOST_TEST( econd == errc::permission_denied );
  140. BOOST_TEST( errc::permission_denied == econd );
  141. BOOST_TEST( ec == errc::permission_denied );
  142. BOOST_TEST( ec.category() == system_category() );
  143. BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 );
  144. // test the explicit make_error_code conversion for errc
  145. ec = make_error_code( errc::bad_message );
  146. BOOST_TEST( ec );
  147. BOOST_TEST( ec == errc::bad_message );
  148. BOOST_TEST( errc::bad_message == ec );
  149. BOOST_TEST( ec != errc::permission_denied );
  150. BOOST_TEST( errc::permission_denied != ec );
  151. BOOST_TEST( ec.category() == generic_category() );
  152. //// test the deprecated predefined error_category synonyms
  153. //BOOST_TEST( &system_category() == &native_ecat );
  154. //BOOST_TEST( &generic_category() == &errno_ecat );
  155. //BOOST_TEST( system_category() == native_ecat );
  156. //BOOST_TEST( generic_category() == errno_ecat );
  157. // test error_code and error_condition message();
  158. // see Boost.Filesystem operations_test for code specific message() tests
  159. ec = error_code( -1, system_category() );
  160. std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n";
  161. std::cout << "error_code message for 0 is \"" << ec_0_system.message() << "\"\n";
  162. #if defined(BOOST_WINDOWS_API)
  163. // Borland appends newline, so just check text
  164. BOOST_TEST( ec.message().substr(0,13) == "Unknown error" );
  165. // Fails when the language isn't US English
  166. // BOOST_TEST( ec_0_system.message().substr(0,36) == "The operation completed successfully" );
  167. #elif defined(linux) || defined(__linux) || defined(__linux__)
  168. // Linux appends value to message as unsigned, so it varies with # of bits
  169. BOOST_TEST( ec.message().substr(0,13) == "Unknown error" );
  170. #elif defined(__hpux)
  171. BOOST_TEST( ec.message() == "" );
  172. #elif defined(__osf__)
  173. BOOST_TEST( ec.message() == "Error -1 occurred." );
  174. #elif defined(__vms)
  175. BOOST_TEST( ec.message() == "error -1" );
  176. #endif
  177. ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() );
  178. BOOST_TEST( ec.message() != "" );
  179. BOOST_TEST( ec.message().substr( 0, 13) != "Unknown error" );
  180. econd = error_condition( -1, generic_category() );
  181. error_condition econd_ok;
  182. std::cout << "error_condition message for -1 is \"" << econd.message() << "\"\n";
  183. std::cout << "error_condition message for 0 is \"" << econd_ok.message() << "\"\n";
  184. #if defined(BOOST_WINDOWS_API)
  185. // Borland appends newline, so just check text
  186. BOOST_TEST( econd.message().substr(0,13) == "Unknown error" );
  187. BOOST_TEST( econd_ok.message().substr(0,8) == "No error" );
  188. #elif defined(linux) || defined(__linux) || defined(__linux__)
  189. // Linux appends value to message as unsigned, so it varies with # of bits
  190. BOOST_TEST( econd.message().substr(0,13) == "Unknown error" );
  191. #elif defined(__hpux)
  192. BOOST_TEST( econd.message() == "" );
  193. #elif defined(__osf__)
  194. BOOST_TEST( econd.message() == "Error -1 occurred." );
  195. #elif defined(__vms)
  196. BOOST_TEST( econd.message() == "error -1" );
  197. #endif
  198. econd = error_condition( BOOST_ACCESS_ERROR_MACRO, generic_category() );
  199. BOOST_TEST( econd.message() != "" );
  200. BOOST_TEST( econd.message().substr( 0, 13) != "Unknown error" );
  201. test_throws_usage();
  202. #ifdef BOOST_WINDOWS_API
  203. std::cout << "Windows tests...\n";
  204. // these tests probe the Windows errc decoder
  205. // test the first entry in the decoder table:
  206. ec = error_code( ERROR_ACCESS_DENIED, system_category() );
  207. BOOST_TEST( ec.value() == ERROR_ACCESS_DENIED );
  208. BOOST_TEST( ec == errc::permission_denied );
  209. BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
  210. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  211. // test the second entry in the decoder table:
  212. ec = error_code( ERROR_ALREADY_EXISTS, system_category() );
  213. BOOST_TEST( ec.value() == ERROR_ALREADY_EXISTS );
  214. BOOST_TEST( ec == errc::file_exists );
  215. BOOST_TEST( ec.default_error_condition().value() == errc::file_exists );
  216. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  217. // test the third entry in the decoder table:
  218. ec = error_code( ERROR_BAD_UNIT, system_category() );
  219. BOOST_TEST( ec.value() == ERROR_BAD_UNIT );
  220. BOOST_TEST( ec == errc::no_such_device );
  221. BOOST_TEST( ec.default_error_condition().value() == errc::no_such_device );
  222. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  223. // test the last non-Winsock entry in the decoder table:
  224. ec = error_code( ERROR_WRITE_PROTECT, system_category() );
  225. BOOST_TEST( ec.value() == ERROR_WRITE_PROTECT );
  226. BOOST_TEST( ec == errc::permission_denied );
  227. BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
  228. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  229. // test the last Winsock entry in the decoder table:
  230. ec = error_code( WSAEWOULDBLOCK, system_category() );
  231. BOOST_TEST( ec.value() == WSAEWOULDBLOCK );
  232. BOOST_TEST( ec == errc::operation_would_block );
  233. BOOST_TEST( ec.default_error_condition().value() == errc::operation_would_block );
  234. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  235. // test not-in-table condition:
  236. ec = error_code( 1234567890, system_category() );
  237. BOOST_TEST( ec.value() == 1234567890 );
  238. BOOST_TEST( ec.default_error_condition().value() == 1234567890 );
  239. BOOST_TEST( ec.default_error_condition().category() == system_category() );
  240. #else // POSIX
  241. std::cout << "POSIX tests...\n";
  242. ec = error_code( EACCES, system_category() );
  243. BOOST_TEST( ec == error_code( errc::permission_denied, system_category() ) );
  244. BOOST_TEST( error_code( errc::permission_denied, system_category() ) == ec );
  245. BOOST_TEST( ec == errc::permission_denied );
  246. BOOST_TEST( errc::permission_denied == ec );
  247. BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
  248. BOOST_TEST( ec.default_error_condition().category() == generic_category() );
  249. # ifdef __CYGWIN__
  250. std::cout << "Cygwin tests...\n";
  251. ec = cygwin_error::no_package;
  252. BOOST_TEST( ec == cygwin_error::no_package );
  253. BOOST_TEST( ec == error_code( ENOPKG, system_category() ) );
  254. BOOST_TEST( ec == error_code( cygwin_error::no_package, system_category() ) );
  255. BOOST_TEST( ec.default_error_condition().category() == system_category() );
  256. # elif defined(linux) || defined(__linux) || defined(__linux__)
  257. std::cout << "Linux tests...\n";
  258. ec = linux_error::dot_dot_error;
  259. BOOST_TEST( ec == linux_error::dot_dot_error );
  260. BOOST_TEST( ec == error_code( EDOTDOT, system_category() ) );
  261. BOOST_TEST( ec == error_code( linux_error::dot_dot_error, system_category() ) );
  262. BOOST_TEST( ec.default_error_condition().category() == system_category() );
  263. # endif
  264. #endif
  265. return ::boost::report_errors();
  266. }