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