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