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