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.
25using 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
42namespace
43{
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
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
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(e: 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(e: 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(dividend: 10, divisor: 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
106int main( int, char ** )
107{
108
109 std::cout << "Conversion use cases...\n";
110 error_condition x1( errc::file_exists );
111 (void)x1;
112 //error_code x2( errc::file_exists ); // should fail to compile
113 make_error_code(e: errc::file_exists);
114 make_error_condition(e: errc::file_exists);
115
116 std::cout << "General tests...\n";
117 // unit tests:
118
119 BOOST_TEST( generic_category() == generic_category() );
120 BOOST_TEST( system_category() == system_category() );
121 BOOST_TEST( generic_category() != system_category() );
122 BOOST_TEST( system_category() != generic_category() );
123
124 BOOST_TEST_NE( generic_category() < system_category(), system_category() < generic_category() );
125
126 error_code ec;
127 error_condition econd;
128 BOOST_TEST( !ec );
129 BOOST_TEST( ec.value() == 0 );
130 econd = ec.default_error_condition();
131 BOOST_TEST( econd.value() == 0 );
132 BOOST_TEST( econd.category() == generic_category() );
133 BOOST_TEST( ec == errc::success );
134 BOOST_TEST( ec.category() == system_category() );
135 BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 );
136 BOOST_TEST( !(ec < error_code( 0, system_category() )) );
137 BOOST_TEST( !(error_code( 0, system_category() ) < ec) );
138 BOOST_TEST( ec < error_code( 1, system_category() ) );
139 BOOST_TEST( !(error_code( 1, system_category() ) < ec) );
140
141 error_code ec_0_system( 0, system_category() );
142 BOOST_TEST( !ec_0_system );
143 BOOST_TEST( ec_0_system.value() == 0 );
144 econd = ec_0_system.default_error_condition();
145 BOOST_TEST( econd.value() == 0 );
146 BOOST_TEST( econd.category() == generic_category() );
147 BOOST_TEST( ec_0_system == errc::success );
148 BOOST_TEST( ec_0_system.category() == system_category() );
149 BOOST_TEST( std::strcmp( ec_0_system.category().name(), "system") == 0 );
150 check_ostream( ec: ec_0_system, expected: "system:0" );
151
152 BOOST_TEST( ec_0_system == ec );
153
154 error_code ec_1_system( 1, system_category() );
155 BOOST_TEST( ec_1_system );
156 BOOST_TEST( ec_1_system.value() == 1 );
157 BOOST_TEST( ec_1_system.value() != 0 );
158 BOOST_TEST( ec != ec_1_system );
159 BOOST_TEST( ec_0_system != ec_1_system );
160 check_ostream( ec: ec_1_system, expected: "system:1" );
161
162 ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() );
163 BOOST_TEST( ec );
164 BOOST_TEST( ec.value() == BOOST_ACCESS_ERROR_MACRO );
165 econd = ec.default_error_condition();
166 BOOST_TEST( econd.value() == static_cast<int>(errc::permission_denied) );
167 BOOST_TEST( econd.category() == generic_category() );
168 BOOST_TEST( econd == error_condition( errc::permission_denied, generic_category() ) );
169 BOOST_TEST( econd == errc::permission_denied );
170 BOOST_TEST( errc::permission_denied == econd );
171 BOOST_TEST( ec == errc::permission_denied );
172 BOOST_TEST( ec.category() == system_category() );
173 BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 );
174
175 // test the explicit make_error_code conversion for errc
176 ec = make_error_code( e: errc::bad_message );
177 BOOST_TEST( ec );
178 BOOST_TEST( ec == errc::bad_message );
179 BOOST_TEST( errc::bad_message == ec );
180 BOOST_TEST( ec != errc::permission_denied );
181 BOOST_TEST( errc::permission_denied != ec );
182 BOOST_TEST( ec.category() == generic_category() );
183
184 //// test the deprecated predefined error_category synonyms
185 //BOOST_TEST( &system_category() == &native_ecat );
186 //BOOST_TEST( &generic_category() == &errno_ecat );
187 //BOOST_TEST( system_category() == native_ecat );
188 //BOOST_TEST( generic_category() == errno_ecat );
189
190 // test error_code and error_condition message();
191 // see Boost.Filesystem operations_test for code specific message() tests
192 ec = error_code( -1, system_category() );
193 std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n";
194 std::cout << "error_code message for 0 is \"" << ec_0_system.message() << "\"\n";
195#if defined(BOOST_WINDOWS_API)
196 // Borland appends newline, so just check text
197 BOOST_TEST( ec.message().substr(0,13) == "Unknown error" );
198 // Fails when the language isn't US English
199 // BOOST_TEST( ec_0_system.message().substr(0,36) == "The operation completed successfully" );
200#elif defined(linux) || defined(__linux) || defined(__linux__)
201 // Linux appends value to message as unsigned, so it varies with # of bits
202 BOOST_TEST( ec.message().substr(0,13) == "Unknown error" );
203#elif defined(__hpux)
204 BOOST_TEST( ec.message() == "" );
205#elif defined(__osf__)
206 BOOST_TEST( ec.message() == "Error -1 occurred." );
207#elif defined(__vms)
208 BOOST_TEST( ec.message() == "error -1" );
209#endif
210
211 ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() );
212 BOOST_TEST( ec.message() != "" );
213 BOOST_TEST( ec.message().substr( 0, 13) != "Unknown error" );
214
215 econd = error_condition( -1, generic_category() );
216 error_condition econd_ok;
217 std::cout << "error_condition message for -1 is \"" << econd.message() << "\"\n";
218 std::cout << "error_condition message for 0 is \"" << econd_ok.message() << "\"\n";
219#if defined(BOOST_WINDOWS_API)
220 // Borland appends newline, so just check text
221 BOOST_TEST( econd.message().substr(0,13) == "Unknown error" );
222 BOOST_TEST( econd_ok.message().substr(0,8) == "No error" );
223#elif defined(linux) || defined(__linux) || defined(__linux__)
224 // Linux appends value to message as unsigned, so it varies with # of bits
225 BOOST_TEST( econd.message().substr(0,13) == "Unknown error" );
226#elif defined(__hpux)
227 BOOST_TEST( econd.message() == "" );
228#elif defined(__osf__)
229 BOOST_TEST( econd.message() == "Error -1 occurred." );
230#elif defined(__vms)
231 BOOST_TEST( econd.message() == "error -1" );
232#endif
233
234 econd = error_condition( BOOST_ACCESS_ERROR_MACRO, generic_category() );
235 BOOST_TEST( econd.message() != "" );
236 BOOST_TEST( econd.message().substr( 0, 13) != "Unknown error" );
237
238 test_throws_usage();
239
240#ifdef BOOST_WINDOWS_API
241 std::cout << "Windows tests...\n";
242 // these tests probe the Windows errc decoder
243 // test the first entry in the decoder table:
244 ec = error_code( ERROR_ACCESS_DENIED, system_category() );
245 BOOST_TEST( ec.value() == ERROR_ACCESS_DENIED );
246 BOOST_TEST( ec == errc::permission_denied );
247 BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
248 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
249
250 // test the second entry in the decoder table:
251 ec = error_code( ERROR_ALREADY_EXISTS, system_category() );
252 BOOST_TEST( ec.value() == ERROR_ALREADY_EXISTS );
253 BOOST_TEST( ec == errc::file_exists );
254 BOOST_TEST( ec.default_error_condition().value() == errc::file_exists );
255 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
256
257 // test the third entry in the decoder table:
258 ec = error_code( ERROR_BAD_UNIT, system_category() );
259 BOOST_TEST( ec.value() == ERROR_BAD_UNIT );
260 BOOST_TEST( ec == errc::no_such_device );
261 BOOST_TEST( ec.default_error_condition().value() == errc::no_such_device );
262 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
263
264 // test the last non-Winsock entry in the decoder table:
265 ec = error_code( ERROR_WRITE_PROTECT, system_category() );
266 BOOST_TEST( ec.value() == ERROR_WRITE_PROTECT );
267 BOOST_TEST( ec == errc::permission_denied );
268 BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
269 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
270
271 // test the last Winsock entry in the decoder table:
272 ec = error_code( WSAEWOULDBLOCK, system_category() );
273 BOOST_TEST( ec.value() == WSAEWOULDBLOCK );
274 BOOST_TEST( ec == errc::operation_would_block );
275 BOOST_TEST( ec.default_error_condition().value() == errc::operation_would_block );
276 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
277
278 // test not-in-table condition:
279 ec = error_code( 1234567890, system_category() );
280 BOOST_TEST( ec.value() == 1234567890 );
281 BOOST_TEST( ec.default_error_condition().value() == 1234567890 );
282 BOOST_TEST( ec.default_error_condition().category() == system_category() );
283
284#else // POSIX
285
286 std::cout << "POSIX tests...\n";
287 ec = error_code( EACCES, system_category() );
288 BOOST_TEST( ec == error_code( errc::permission_denied, system_category() ) );
289 BOOST_TEST( error_code( errc::permission_denied, system_category() ) == ec );
290 BOOST_TEST( ec == errc::permission_denied );
291 BOOST_TEST( errc::permission_denied == ec );
292 BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
293 BOOST_TEST( ec.default_error_condition().category() == generic_category() );
294
295#endif
296
297 return ::boost::report_errors();
298}
299

source code of boost/libs/system/test/error_code_test.cpp