]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
7c673cae FG |
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 | ||
b32b8144 FG |
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 | |
7c673cae FG |
44 | |
45 | namespace | |
46 | { | |
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 | } | |
b32b8144 FG |
56 | |
57 | // throws_function_test ------------------------------------------------------------// | |
58 | ||
59 | // usage example | |
60 | ||
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 | ||
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 | } | |
7c673cae FG |
103 | } |
104 | ||
105 | // main ------------------------------------------------------------------------------// | |
106 | ||
107 | // TODO: add hash_value tests | |
108 | ||
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 | if ( std::less<const error_category*>()( &generic_category(), &system_category() ) ) | |
127 | { | |
128 | BOOST_TEST( generic_category() < system_category() ); | |
129 | BOOST_TEST( !(system_category() < generic_category()) ); | |
130 | } | |
131 | else | |
132 | { | |
133 | BOOST_TEST( system_category() < generic_category() ); | |
134 | BOOST_TEST( !(generic_category() < system_category()) ); | |
135 | } | |
136 | ||
137 | ||
138 | error_code ec; | |
139 | error_condition econd; | |
140 | BOOST_TEST( !ec ); | |
141 | BOOST_TEST( ec.value() == 0 ); | |
142 | econd = ec.default_error_condition(); | |
143 | BOOST_TEST( econd.value() == 0 ); | |
144 | BOOST_TEST( econd.category() == generic_category() ); | |
145 | BOOST_TEST( ec == errc::success ); | |
146 | BOOST_TEST( ec.category() == system_category() ); | |
147 | BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 ); | |
148 | BOOST_TEST( !(ec < error_code( 0, system_category() )) ); | |
149 | BOOST_TEST( !(error_code( 0, system_category() ) < ec) ); | |
150 | BOOST_TEST( ec < error_code( 1, system_category() ) ); | |
151 | BOOST_TEST( !(error_code( 1, system_category() ) < ec) ); | |
152 | ||
153 | error_code ec_0_system( 0, system_category() ); | |
154 | BOOST_TEST( !ec_0_system ); | |
155 | BOOST_TEST( ec_0_system.value() == 0 ); | |
156 | econd = ec_0_system.default_error_condition(); | |
157 | BOOST_TEST( econd.value() == 0 ); | |
158 | BOOST_TEST( econd.category() == generic_category() ); | |
159 | BOOST_TEST( ec_0_system == errc::success ); | |
160 | BOOST_TEST( ec_0_system.category() == system_category() ); | |
161 | BOOST_TEST( std::strcmp( ec_0_system.category().name(), "system") == 0 ); | |
162 | check_ostream( ec_0_system, "system:0" ); | |
163 | ||
164 | BOOST_TEST( ec_0_system == ec ); | |
165 | ||
166 | error_code ec_1_system( 1, system_category() ); | |
167 | BOOST_TEST( ec_1_system ); | |
168 | BOOST_TEST( ec_1_system.value() == 1 ); | |
169 | BOOST_TEST( ec_1_system.value() != 0 ); | |
170 | BOOST_TEST( ec != ec_1_system ); | |
171 | BOOST_TEST( ec_0_system != ec_1_system ); | |
172 | check_ostream( ec_1_system, "system:1" ); | |
173 | ||
174 | ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() ); | |
175 | BOOST_TEST( ec ); | |
176 | BOOST_TEST( ec.value() == BOOST_ACCESS_ERROR_MACRO ); | |
177 | econd = ec.default_error_condition(); | |
178 | BOOST_TEST( econd.value() == static_cast<int>(errc::permission_denied) ); | |
179 | BOOST_TEST( econd.category() == generic_category() ); | |
180 | BOOST_TEST( econd == error_condition( errc::permission_denied, generic_category() ) ); | |
181 | BOOST_TEST( econd == errc::permission_denied ); | |
182 | BOOST_TEST( errc::permission_denied == econd ); | |
183 | BOOST_TEST( ec == errc::permission_denied ); | |
184 | BOOST_TEST( ec.category() == system_category() ); | |
185 | BOOST_TEST( std::strcmp( ec.category().name(), "system") == 0 ); | |
186 | ||
187 | // test the explicit make_error_code conversion for errc | |
188 | ec = make_error_code( errc::bad_message ); | |
189 | BOOST_TEST( ec ); | |
190 | BOOST_TEST( ec == errc::bad_message ); | |
191 | BOOST_TEST( errc::bad_message == ec ); | |
192 | BOOST_TEST( ec != errc::permission_denied ); | |
193 | BOOST_TEST( errc::permission_denied != ec ); | |
194 | BOOST_TEST( ec.category() == generic_category() ); | |
195 | ||
196 | //// test the deprecated predefined error_category synonyms | |
197 | //BOOST_TEST( &system_category() == &native_ecat ); | |
198 | //BOOST_TEST( &generic_category() == &errno_ecat ); | |
199 | //BOOST_TEST( system_category() == native_ecat ); | |
200 | //BOOST_TEST( generic_category() == errno_ecat ); | |
201 | ||
202 | // test error_code and error_condition message(); | |
203 | // see Boost.Filesystem operations_test for code specific message() tests | |
204 | ec = error_code( -1, system_category() ); | |
205 | std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n"; | |
206 | std::cout << "error_code message for 0 is \"" << ec_0_system.message() << "\"\n"; | |
207 | #if defined(BOOST_WINDOWS_API) | |
208 | // Borland appends newline, so just check text | |
209 | BOOST_TEST( ec.message().substr(0,13) == "Unknown error" ); | |
210 | BOOST_TEST( ec_0_system.message().substr(0,36) == "The operation completed successfully" ); | |
211 | #elif defined(linux) || defined(__linux) || defined(__linux__) | |
212 | // Linux appends value to message as unsigned, so it varies with # of bits | |
213 | BOOST_TEST( ec.message().substr(0,13) == "Unknown error" ); | |
214 | #elif defined(__hpux) | |
215 | BOOST_TEST( ec.message() == "" ); | |
216 | #elif defined(__osf__) | |
217 | BOOST_TEST( ec.message() == "Error -1 occurred." ); | |
218 | #elif defined(__vms) | |
219 | BOOST_TEST( ec.message() == "error -1" ); | |
220 | #endif | |
221 | ||
222 | ec = error_code( BOOST_ACCESS_ERROR_MACRO, system_category() ); | |
223 | BOOST_TEST( ec.message() != "" ); | |
224 | BOOST_TEST( ec.message().substr( 0, 13) != "Unknown error" ); | |
225 | ||
226 | econd = error_condition( -1, generic_category() ); | |
227 | error_condition econd_ok; | |
228 | std::cout << "error_condition message for -1 is \"" << econd.message() << "\"\n"; | |
229 | std::cout << "error_condition message for 0 is \"" << econd_ok.message() << "\"\n"; | |
230 | #if defined(BOOST_WINDOWS_API) | |
231 | // Borland appends newline, so just check text | |
232 | BOOST_TEST( econd.message().substr(0,13) == "Unknown error" ); | |
233 | BOOST_TEST( econd_ok.message().substr(0,8) == "No error" ); | |
234 | #elif defined(linux) || defined(__linux) || defined(__linux__) | |
235 | // Linux appends value to message as unsigned, so it varies with # of bits | |
236 | BOOST_TEST( econd.message().substr(0,13) == "Unknown error" ); | |
237 | #elif defined(__hpux) | |
238 | BOOST_TEST( econd.message() == "" ); | |
239 | #elif defined(__osf__) | |
240 | BOOST_TEST( econd.message() == "Error -1 occurred." ); | |
241 | #elif defined(__vms) | |
242 | BOOST_TEST( econd.message() == "error -1" ); | |
243 | #endif | |
244 | ||
245 | econd = error_condition( BOOST_ACCESS_ERROR_MACRO, generic_category() ); | |
246 | BOOST_TEST( econd.message() != "" ); | |
247 | BOOST_TEST( econd.message().substr( 0, 13) != "Unknown error" ); | |
248 | ||
b32b8144 FG |
249 | test_throws_usage(); |
250 | ||
7c673cae FG |
251 | #ifdef BOOST_WINDOWS_API |
252 | std::cout << "Windows tests...\n"; | |
253 | // these tests probe the Windows errc decoder | |
254 | // test the first entry in the decoder table: | |
255 | ec = error_code( ERROR_ACCESS_DENIED, system_category() ); | |
256 | BOOST_TEST( ec.value() == ERROR_ACCESS_DENIED ); | |
257 | BOOST_TEST( ec == errc::permission_denied ); | |
258 | BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); | |
259 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
260 | ||
261 | // test the second entry in the decoder table: | |
262 | ec = error_code( ERROR_ALREADY_EXISTS, system_category() ); | |
263 | BOOST_TEST( ec.value() == ERROR_ALREADY_EXISTS ); | |
264 | BOOST_TEST( ec == errc::file_exists ); | |
265 | BOOST_TEST( ec.default_error_condition().value() == errc::file_exists ); | |
266 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
267 | ||
268 | // test the third entry in the decoder table: | |
269 | ec = error_code( ERROR_BAD_UNIT, system_category() ); | |
270 | BOOST_TEST( ec.value() == ERROR_BAD_UNIT ); | |
271 | BOOST_TEST( ec == errc::no_such_device ); | |
272 | BOOST_TEST( ec.default_error_condition().value() == errc::no_such_device ); | |
273 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
274 | ||
275 | // test the last non-Winsock entry in the decoder table: | |
276 | ec = error_code( ERROR_WRITE_PROTECT, system_category() ); | |
277 | BOOST_TEST( ec.value() == ERROR_WRITE_PROTECT ); | |
278 | BOOST_TEST( ec == errc::permission_denied ); | |
279 | BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); | |
280 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
281 | ||
282 | // test the last Winsock entry in the decoder table: | |
283 | ec = error_code( WSAEWOULDBLOCK, system_category() ); | |
284 | BOOST_TEST( ec.value() == WSAEWOULDBLOCK ); | |
285 | BOOST_TEST( ec == errc::operation_would_block ); | |
286 | BOOST_TEST( ec.default_error_condition().value() == errc::operation_would_block ); | |
287 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
288 | ||
289 | // test not-in-table condition: | |
290 | ec = error_code( 1234567890, system_category() ); | |
291 | BOOST_TEST( ec.value() == 1234567890 ); | |
292 | BOOST_TEST( ec.default_error_condition().value() == 1234567890 ); | |
293 | BOOST_TEST( ec.default_error_condition().category() == system_category() ); | |
294 | ||
295 | #else // POSIX | |
296 | ||
297 | std::cout << "POSIX tests...\n"; | |
298 | ec = error_code( EACCES, system_category() ); | |
299 | BOOST_TEST( ec == error_code( errc::permission_denied, system_category() ) ); | |
300 | BOOST_TEST( error_code( errc::permission_denied, system_category() ) == ec ); | |
301 | BOOST_TEST( ec == errc::permission_denied ); | |
302 | BOOST_TEST( errc::permission_denied == ec ); | |
303 | BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied ); | |
304 | BOOST_TEST( ec.default_error_condition().category() == generic_category() ); | |
305 | ||
306 | # ifdef __CYGWIN__ | |
307 | ||
308 | std::cout << "Cygwin tests...\n"; | |
309 | ec = cygwin_error::no_package; | |
310 | BOOST_TEST( ec == cygwin_error::no_package ); | |
311 | BOOST_TEST( ec == error_code( ENOPKG, system_category() ) ); | |
312 | BOOST_TEST( ec == error_code( cygwin_error::no_package, system_category() ) ); | |
313 | BOOST_TEST( ec.default_error_condition().category() == system_category() ); | |
314 | ||
315 | # elif defined(linux) || defined(__linux) || defined(__linux__) | |
316 | ||
317 | std::cout << "Linux tests...\n"; | |
318 | ec = linux_error::dot_dot_error; | |
319 | BOOST_TEST( ec == linux_error::dot_dot_error ); | |
320 | BOOST_TEST( ec == error_code( EDOTDOT, system_category() ) ); | |
321 | BOOST_TEST( ec == error_code( linux_error::dot_dot_error, system_category() ) ); | |
322 | BOOST_TEST( ec.default_error_condition().category() == system_category() ); | |
323 | ||
324 | # endif | |
325 | ||
326 | #endif | |
327 | ||
328 | return ::boost::report_errors(); | |
329 | } | |
330 | ||
331 |