// error_code_test.cpp -----------------------------------------------------// // Copyright Beman Dawes 2006 // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See library home page at http://www.boost.org/libs/system //----------------------------------------------------------------------------// #include #include #include #include #include #include #include #include #include #include #include #include // Although using directives are not the best programming practice, testing // with a boost::system using directive increases use scenario coverage. using namespace boost::system; #if defined( BOOST_WINDOWS_API ) // Neither MinGW or Cygwin versions of winerror.h work if used alone, so on // either of those platforms include the full windows.h # if defined(__MINGW32__) || defined(__CYGWIN__) # include # else # include # endif # define BOOST_ACCESS_ERROR_MACRO ERROR_ACCESS_DENIED #elif defined( BOOST_POSIX_API ) # define BOOST_ACCESS_ERROR_MACRO EACCES #else # error "Only supported for POSIX and Windows" #endif namespace { void check_ostream( error_code ec, const char * expected ) { std::stringstream ss; std::string s; ss << ec; ss >> s; BOOST_TEST( s == expected ); } // throws_function_test ------------------------------------------------------------// // usage example int divide(int dividend, int divisor, boost::system::error_code& ec = boost::throws()) { if (divisor == 0) // is there an error? { if (&ec == &boost::throws()) // throw on error throw "oops!"; // whatever exception you prefer ec = error_code(EDOM, generic_category()); // report error via error_code return 0; } if (&ec != &boost::throws()) // error reporting via error_code ec.clear(); return dividend / divisor; } // test usage example void test_throws_usage() { std::cout << "Test throws() example and usage...\n"; error_code ec; // no error tests BOOST_TEST_EQ((divide(10, 2)), 5); // no error, report via exception ec = make_error_code(errc::argument_out_of_domain); BOOST_TEST_EQ((divide(10, 5, ec)), 2); // no error, report via error_code BOOST_TEST(!ec); ec = make_error_code(errc::argument_out_of_domain); BOOST_TEST_EQ((divide(10, 0, ec)), 0); // error, report via error_code BOOST_TEST(ec); bool exception_thrown = false; try { divide(10, 0); } // error, report via exception catch (...) { exception_thrown = true; } BOOST_TEST(exception_thrown); //error_code should_fail(boost::throws()); // should fail at runtime //boost::throws() = ec; // should fail at runtime } } // main ------------------------------------------------------------------------------// // TODO: add hash_value tests int main( int, char ** ) { std::cout << "Conversion use cases...\n"; error_condition x1( errc::file_exists ); //error_code x2( errc::file_exists ); // should fail to compile make_error_code(errc::file_exists); make_error_condition(errc::file_exists); std::cout << "General tests...\n"; // unit tests: BOOST_TEST( generic_category() == generic_category() ); BOOST_TEST( system_category() == system_category() ); BOOST_TEST( generic_category() != system_category() ); BOOST_TEST( system_category() != generic_category() ); BOOST_TEST_NE( generic_category() < system_category(), system_category() < generic_category() ); error_code ec; error_condition econd; BOOST_TEST( !ec ); BOOST_TEST( ec.value() == 0 ); econd = ec.default_error_condition(); BOOST_TEST( econd.value() == 0 ); BOOST_TEST( econd.category() == generic_category() ); BOOST_TEST( ec == errc::success ); BOOST_TEST( ec.category() == system_category() ); BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 ); BOOST_TEST( !(ec < error_code( 0, system_category() )) ); BOOST_TEST( !(error_code( 0, system_category() ) < ec) ); BOOST_TEST( ec < error_code( 1, system_category() ) ); BOOST_TEST( !(error_code( 1, system_category() ) < ec) ); error_code ec_0_system( 0, system_category() ); BOOST_TEST( !ec_0_system ); BOOST_TEST( ec_0_system.value() == 0 ); econd = ec_0_system.default_error_condition(); BOOST_TEST( econd.value() == 0 ); BOOST_TEST( econd.category() == generic_category() ); BOOST_TEST( ec_0_system == errc::success ); BOOST_TEST( ec_0_system.category() == system_category() ); BOOST_TEST( std::strcmp( ec_0_system.category().name(), "system") == 0 ); check_ostream( ec_0_system, "system:0" ); BOOST_TEST( ec_0_system == ec ); error_code ec_1_system( 1, system_category() ); BOOST_TEST( ec_1_system ); BOOST_TEST( ec_1_system.value() == 1 ); BOOST_TEST( ec_1_system.value() != 0 ); BOOST_TEST( ec != ec_1_system ); BOOST_TEST( ec_0_system != ec_1_system ); check_ostream( ec_1_system, "system:1" ); ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() ); BOOST_TEST( ec ); BOOST_TEST( ec.value() == BOOST_ACCESS_ERROR_MACRO ); econd = ec.default_error_condition(); BOOST_TEST( econd.value() == static_cast(errc::permission_denied) ); BOOST_TEST( econd.category() == generic_category() ); BOOST_TEST( econd == error_condition( errc::permission_denied, generic_category() ) ); BOOST_TEST( econd == errc::permission_denied ); BOOST_TEST( errc::permission_denied == econd ); BOOST_TEST( ec == errc::permission_denied ); BOOST_TEST( ec.category() == system_category() ); BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 ); // test the explicit make_error_code conversion for errc ec = make_error_code( errc::bad_message ); BOOST_TEST( ec ); BOOST_TEST( ec == errc::bad_message ); BOOST_TEST( errc::bad_message == ec ); BOOST_TEST( ec != errc::permission_denied ); BOOST_TEST( errc::permission_denied != ec ); BOOST_TEST( ec.category() == generic_category() ); //// test the deprecated predefined error_category synonyms //BOOST_TEST( &system_category() == &native_ecat ); //BOOST_TEST( &generic_category() == &errno_ecat ); //BOOST_TEST( system_category() == native_ecat ); //BOOST_TEST( generic_category() == errno_ecat ); // test error_code and error_condition message(); // see Boost.Filesystem operations_test for code specific message() tests ec = error_code( -1, system_category() ); std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n"; std::cout << "error_code message for 0 is \"" << ec_0_system.message() << "\"\n"; #if defined(BOOST_WINDOWS_API) // Borland appends newline, so just check text BOOST_TEST( ec.message().substr(0,13) == "Unknown error" ); // Fails when the language isn't US English // BOOST_TEST( ec_0_system.message().substr(0,36) == "The operation completed successfully" ); #elif defined(linux) || defined(__linux) || defined(__linux__) // Linux appends value to message as unsigned, so it varies with # of bits BOOST_TEST( ec.message().substr(0,13) == "Unknown error" ); #elif defined(__hpux) BOOST_TEST( ec.message() == "" ); #elif defined(__osf__) BOOST_TEST( ec.message() == "Error -1 occurred." ); #elif defined(__vms) BOOST_TEST( ec.message() == "error -1" ); #endif ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() ); BOOST_TEST( ec.message() != "" ); BOOST_TEST( ec.message().substr( 0, 13) != "Unknown error" ); econd = error_condition( -1, generic_category() ); error_condition econd_ok; std::cout << "error_condition message for -1 is \"" << econd.message() << "\"\n"; std::cout << "error_condition message for 0 is \"" << econd_ok.message() << "\"\n"; #if defined(BOOST_WINDOWS_API) // Borland appends newline, so just check text BOOST_TEST( econd.message().substr(0,13) == "Unknown error" ); BOOST_TEST( econd_ok.message().substr(0,8) == "No error" ); #elif defined(linux) || defined(__linux) || defined(__linux__) // Linux appends value to message as unsigned, so it varies with # of bits BOOST_TEST( econd.message().substr(0,13) == "Unknown error" ); #elif defined(__hpux) BOOST_TEST( econd.message() == "" ); #elif defined(__osf__) BOOST_TEST( econd.message() == "Error -1 occurred." ); #elif defined(__vms) BOOST_TEST( econd.message() == "error -1" ); #endif econd = error_condition( BOOST_ACCESS_ERROR_MACRO, generic_category() ); BOOST_TEST( econd.message() != "" ); BOOST_TEST( econd.message().substr( 0, 13) != "Unknown error" ); test_throws_usage(); #ifdef BOOST_WINDOWS_API std::cout << "Windows tests...\n"; // these tests probe the Windows errc decoder // test the first entry in the decoder table: ec = error_code( ERROR_ACCESS_DENIED, system_category() ); BOOST_TEST( ec.value() == ERROR_ACCESS_DENIED ); BOOST_TEST( ec == errc::permission_denied ); BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); // test the second entry in the decoder table: ec = error_code( ERROR_ALREADY_EXISTS, system_category() ); BOOST_TEST( ec.value() == ERROR_ALREADY_EXISTS ); BOOST_TEST( ec == errc::file_exists ); BOOST_TEST( ec.default_error_condition().value() == errc::file_exists ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); // test the third entry in the decoder table: ec = error_code( ERROR_BAD_UNIT, system_category() ); BOOST_TEST( ec.value() == ERROR_BAD_UNIT ); BOOST_TEST( ec == errc::no_such_device ); BOOST_TEST( ec.default_error_condition().value() == errc::no_such_device ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); // test the last non-Winsock entry in the decoder table: ec = error_code( ERROR_WRITE_PROTECT, system_category() ); BOOST_TEST( ec.value() == ERROR_WRITE_PROTECT ); BOOST_TEST( ec == errc::permission_denied ); BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); // test the last Winsock entry in the decoder table: ec = error_code( WSAEWOULDBLOCK, system_category() ); BOOST_TEST( ec.value() == WSAEWOULDBLOCK ); BOOST_TEST( ec == errc::operation_would_block ); BOOST_TEST( ec.default_error_condition().value() == errc::operation_would_block ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); // test not-in-table condition: ec = error_code( 1234567890, system_category() ); BOOST_TEST( ec.value() == 1234567890 ); BOOST_TEST( ec.default_error_condition().value() == 1234567890 ); BOOST_TEST( ec.default_error_condition().category() == system_category() ); #else // POSIX std::cout << "POSIX tests...\n"; ec = error_code( EACCES, system_category() ); BOOST_TEST( ec == error_code( errc::permission_denied, system_category() ) ); BOOST_TEST( error_code( errc::permission_denied, system_category() ) == ec ); BOOST_TEST( ec == errc::permission_denied ); BOOST_TEST( errc::permission_denied == ec ); BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); BOOST_TEST( ec.default_error_condition().category() == generic_category() ); # ifdef __CYGWIN__ std::cout << "Cygwin tests...\n"; ec = cygwin_error::no_package; BOOST_TEST( ec == cygwin_error::no_package ); BOOST_TEST( ec == error_code( ENOPKG, system_category() ) ); BOOST_TEST( ec == error_code( cygwin_error::no_package, system_category() ) ); BOOST_TEST( ec.default_error_condition().category() == system_category() ); # elif defined(linux) || defined(__linux) || defined(__linux__) std::cout << "Linux tests...\n"; ec = linux_error::dot_dot_error; BOOST_TEST( ec == linux_error::dot_dot_error ); BOOST_TEST( ec == error_code( EDOTDOT, system_category() ) ); BOOST_TEST( ec == error_code( linux_error::dot_dot_error, system_category() ) ); BOOST_TEST( ec.default_error_condition().category() == system_category() ); # endif #endif return ::boost::report_errors(); }