]>
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 | ||
7c673cae | 14 | #include <boost/system/error_code.hpp> |
20effc67 | 15 | #include <boost/core/lightweight_test.hpp> |
7c673cae FG |
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 | ||
b32b8144 FG |
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 | |
7c673cae FG |
41 | |
42 | namespace | |
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 | } | |
b32b8144 FG |
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(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 | } | |
7c673cae FG |
100 | } |
101 | ||
102 | // main ------------------------------------------------------------------------------// | |
103 | ||
104 | // TODO: add hash_value tests | |
105 | ||
106 | int main( int, char ** ) | |
107 | { | |
108 | ||
109 | std::cout << "Conversion use cases...\n"; | |
110 | error_condition x1( errc::file_exists ); | |
1e59de90 | 111 | (void)x1; |
7c673cae FG |
112 | //error_code x2( errc::file_exists ); // should fail to compile |
113 | make_error_code(errc::file_exists); | |
114 | make_error_condition(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 | ||
92f5a8d4 | 124 | BOOST_TEST_NE( generic_category() < system_category(), system_category() < generic_category() ); |
7c673cae FG |
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_0_system, "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_1_system, "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( 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" ); | |
92f5a8d4 TL |
198 | // Fails when the language isn't US English |
199 | // BOOST_TEST( ec_0_system.message().substr(0,36) == "The operation completed successfully" ); | |
7c673cae FG |
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 | ||
b32b8144 FG |
238 | test_throws_usage(); |
239 | ||
7c673cae FG |
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 | ||
7c673cae FG |
295 | #endif |
296 | ||
297 | return ::boost::report_errors(); | |
298 | } |