1 | // error_code_user_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 | // This program demonstrates creation and use of new categories of error |
13 | // codes. Several scenarios are demonstrated and tested. |
14 | |
15 | // Motivation was a Boost posting by Christopher Kohlhoff on June 28, 2006. |
16 | |
17 | #include <boost/system/error_code.hpp> |
18 | #include <boost/cerrno.hpp> |
19 | #include <string> |
20 | #include <cstdio> |
21 | #include <boost/detail/lightweight_test.hpp> |
22 | |
23 | #ifdef BOOST_POSIX_API |
24 | # include <sys/stat.h> |
25 | #else |
26 | # include <windows.h> |
27 | #endif |
28 | |
29 | // ------------------------------------------------------------------------ // |
30 | |
31 | // Library 1: User function passes through an error code from the |
32 | // operating system. |
33 | |
34 | |
35 | boost::system::error_code my_mkdir( const std::string & path ) |
36 | { |
37 | return boost::system::error_code( |
38 | # ifdef BOOST_POSIX_API |
39 | ::mkdir( path: path.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH ) == 0 ? 0 : errno, |
40 | # else |
41 | ::CreateDirectoryA( path.c_str(), 0 ) != 0 ? 0 : ::GetLastError(), |
42 | # endif |
43 | boost::system::system_category() ); |
44 | } |
45 | |
46 | // ------------------------------------------------------------------------ // |
47 | |
48 | // Library 2: User function passes through errno from the C-runtime. |
49 | |
50 | #include <cstdio> |
51 | |
52 | boost::system::error_code my_remove( const std::string & path ) |
53 | { |
54 | return boost::system::error_code( |
55 | std::remove( filename: path.c_str() ) == 0 ? 0 : errno, |
56 | boost::system::generic_category() ); // OK for both Windows and POSIX |
57 | // Alternatively, could use generic_category() |
58 | // on Windows and system_category() on |
59 | // POSIX-based systems. |
60 | } |
61 | |
62 | // ------------------------------------------------------------------------ // |
63 | |
64 | // Library 3: Library uses enum to identify library specific errors. |
65 | |
66 | // This particular example is for a library within the parent namespace. For |
67 | // an example of a library not within the parent namespace, see library 4. |
68 | |
69 | // header lib3.hpp: |
70 | |
71 | namespace boost |
72 | { |
73 | namespace lib3 |
74 | { |
75 | // lib3 has its own error_category: |
76 | const boost::system::error_category & get_lib3_error_category() BOOST_SYSTEM_NOEXCEPT; |
77 | const boost::system::error_category & lib3_error_category = get_lib3_error_category(); |
78 | |
79 | enum error |
80 | { |
81 | boo_boo=123, |
82 | big_boo_boo |
83 | }; |
84 | } |
85 | |
86 | namespace system |
87 | { |
88 | template<> struct is_error_code_enum<boost::lib3::error> |
89 | { static const bool value = true; }; |
90 | } |
91 | |
92 | namespace lib3 |
93 | { |
94 | inline boost::system::error_code make_error_code(error e) |
95 | { return boost::system::error_code(e,lib3_error_category); } |
96 | } |
97 | |
98 | } |
99 | |
100 | // implementation file lib3.cpp: |
101 | |
102 | // #include <lib3.hpp> |
103 | |
104 | namespace boost |
105 | { |
106 | namespace lib3 |
107 | { |
108 | class lib3_error_category_imp : public boost::system::error_category |
109 | { |
110 | public: |
111 | lib3_error_category_imp() : boost::system::error_category() { } |
112 | |
113 | const char * name() const BOOST_SYSTEM_NOEXCEPT |
114 | { |
115 | return "lib3" ; |
116 | } |
117 | |
118 | boost::system::error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT |
119 | { |
120 | return ev == boo_boo |
121 | ? boost::system::error_condition( boost::system::errc::io_error, |
122 | boost::system::generic_category() ) |
123 | : boost::system::error_condition( ev, |
124 | boost::lib3::lib3_error_category ); |
125 | } |
126 | |
127 | std::string message( int ev ) const |
128 | { |
129 | if ( ev == boo_boo ) return std::string("boo boo" ); |
130 | if ( ev == big_boo_boo ) return std::string("big boo boo" ); |
131 | return std::string("unknown error" ); |
132 | } |
133 | |
134 | }; |
135 | |
136 | const boost::system::error_category & get_lib3_error_category() BOOST_SYSTEM_NOEXCEPT |
137 | { |
138 | static const lib3_error_category_imp l3ecat; |
139 | return l3ecat; |
140 | } |
141 | } |
142 | } |
143 | |
144 | // ------------------------------------------------------------------------ // |
145 | |
146 | // Library 4: Library uses const error_code's to identify library specific |
147 | // errors. |
148 | |
149 | // This particular example is for a library not within the parent namespace. |
150 | // For an example of a library within the parent namespace, see library 3. |
151 | |
152 | // header lib4.hpp: |
153 | |
154 | namespace lib4 |
155 | { |
156 | // lib4 has its own error_category: |
157 | const boost::system::error_category & get_lib4_error_category() BOOST_SYSTEM_NOEXCEPT; |
158 | const boost::system::error_category & lib4_error_category = get_lib4_error_category(); |
159 | |
160 | extern const boost::system::error_code boo_boo; |
161 | extern const boost::system::error_code big_boo_boo; |
162 | } |
163 | |
164 | // implementation file lib4.cpp: |
165 | |
166 | // #include <lib4.hpp> |
167 | |
168 | namespace lib4 |
169 | { |
170 | class lib4_error_category_imp : public boost::system::error_category |
171 | { |
172 | public: |
173 | lib4_error_category_imp() : boost::system::error_category() { } |
174 | |
175 | const char * name() const BOOST_SYSTEM_NOEXCEPT |
176 | { |
177 | return "lib4" ; |
178 | } |
179 | |
180 | boost::system::error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT |
181 | { |
182 | return ev == boo_boo.value() |
183 | ? boost::system::error_condition( boost::system::errc::io_error, |
184 | boost::system::generic_category() ) |
185 | : boost::system::error_condition( ev, lib4::lib4_error_category ); |
186 | } |
187 | |
188 | std::string message( int ev ) const |
189 | { |
190 | if ( ev == boo_boo.value() ) return std::string("boo boo" ); |
191 | if ( ev == big_boo_boo.value() ) return std::string("big boo boo" ); |
192 | return std::string("unknown error" ); |
193 | } |
194 | }; |
195 | |
196 | const boost::system::error_category & get_lib4_error_category() BOOST_SYSTEM_NOEXCEPT |
197 | { |
198 | static const lib4_error_category_imp l4ecat; |
199 | return l4ecat; |
200 | } |
201 | |
202 | const boost::system::error_code boo_boo( 456, lib4_error_category ); |
203 | const boost::system::error_code big_boo_boo( 789, lib4_error_category ); |
204 | |
205 | } |
206 | |
207 | // ------------------------------------------------------------------------ // |
208 | |
209 | // Chris Kolhoff's Test3, modified to work with error_code.hpp |
210 | |
211 | // Test3 |
212 | // ===== |
213 | // Define error classes to check for success, permission_denied and |
214 | // out_of_memory, but add additional mappings for a user-defined error category. |
215 | // |
216 | |
217 | //namespace test3 { |
218 | |
219 | // enum user_err |
220 | // { |
221 | // user_success = 0, |
222 | // user_permission_denied, |
223 | // user_out_of_memory |
224 | // }; |
225 | // |
226 | // class user_error_category_imp : public boost::system::error_category |
227 | // { |
228 | // public: |
229 | // const std::string & name() const |
230 | // { |
231 | // static std::string s( "test3" ); |
232 | // return s; |
233 | // } |
234 | // |
235 | // boost::system::error_code portable_error_code( int ev ) const |
236 | // { |
237 | // switch (ev) |
238 | // { |
239 | // case user_success: |
240 | // return boost::system::error_code(boost::system::errc::success, boost::system::generic_category()); |
241 | // case user_permission_denied: |
242 | // return boost::system::error_code(boost::system::errc::permission_denied, boost::system::generic_category()); |
243 | // case user_out_of_memory: |
244 | // return boost::system::error_code(boost::system::errc::not_enough_memory, boost::system::generic_category()); |
245 | // default: |
246 | // break; |
247 | // } |
248 | // return boost::system::error_code(boost::system::errc::no_posix_equivalent, boost::system::generic_category()); |
249 | // } |
250 | // |
251 | // }; |
252 | // |
253 | // const user_error_category_imp user_error_category_const; |
254 | // |
255 | // const boost::system::error_category & user_error_category |
256 | // = user_error_category_const; |
257 | // |
258 | // template<> inline boost::system::error_code make_error_code(user_err e) |
259 | // { |
260 | // return boost::system::error_code(e, user_error_category); |
261 | // } |
262 | // |
263 | // // test code |
264 | // |
265 | // void check_success(const boost::system::error_code& ec, bool expect) |
266 | // { |
267 | // BOOST_TEST( (ec == boost::system::errc::success) == expect ); |
268 | // if (ec == boost::system::errc::success) |
269 | // std::cout << "yes... " << (expect ? "ok" : "fail") << '\n'; |
270 | // else |
271 | // std::cout << "no... " << (expect ? "fail" : "ok") << '\n'; |
272 | // } |
273 | // |
274 | // void check_permission_denied(const boost::system::error_code& ec, bool expect) |
275 | // { |
276 | // BOOST_TEST( (ec == boost::system::errc::permission_denied) == expect ); |
277 | // if (ec == boost::system::errc::permission_denied) |
278 | // std::cout << "yes... " << (expect ? "ok" : "fail") << '\n'; |
279 | // else |
280 | // std::cout << "no... " << (expect ? "fail" : "ok") << '\n'; |
281 | // } |
282 | // |
283 | // void check_out_of_memory(const boost::system::error_code& ec, bool expect) |
284 | // { |
285 | // BOOST_TEST( (ec == boost::system::errc::not_enough_memory) == expect ); |
286 | // if (ec == boost::system::errc::not_enough_memory) |
287 | // std::cout << "yes... " << (expect ? "ok" : "fail") << '\n'; |
288 | // else |
289 | // std::cout << "no... " << (expect ? "fail" : "ok") << '\n'; |
290 | // } |
291 | // |
292 | // void run() |
293 | // { |
294 | // printf("Test3\n"); |
295 | // printf("=====\n"); |
296 | // boost::system::error_code ec; |
297 | // check_success(ec, true); |
298 | // check_success(boost::system::errc::success, true); |
299 | // check_success(boost::system::errc::permission_denied, false); |
300 | // check_success(boost::system::errc::not_enough_memory, false); |
301 | // check_success(user_success, true); |
302 | // check_success(user_permission_denied, false); |
303 | // check_success(user_out_of_memory, false); |
304 | // check_permission_denied(ec, false); |
305 | // check_permission_denied(boost::system::errc::success, false); |
306 | // check_permission_denied(boost::system::errc::permission_denied, true); |
307 | // check_permission_denied(boost::system::errc::not_enough_memory, false); |
308 | // check_permission_denied(user_success, false); |
309 | // check_permission_denied(user_permission_denied, true); |
310 | // check_permission_denied(user_out_of_memory, false); |
311 | // check_out_of_memory(ec, false); |
312 | // check_out_of_memory(boost::system::errc::success, false); |
313 | // check_out_of_memory(boost::system::errc::permission_denied, false); |
314 | // check_out_of_memory(boost::system::errc::not_enough_memory, true); |
315 | // check_out_of_memory(user_success, false); |
316 | // check_out_of_memory(user_permission_denied, false); |
317 | // check_out_of_memory(user_out_of_memory, true); |
318 | // |
319 | //# ifdef BOOST_WINDOWS_API |
320 | // check_success(boost::system::windows::success, true); |
321 | // check_success(boost::system::windows::access_denied, false); |
322 | // check_success(boost::system::windows::not_enough_memory, false); |
323 | // check_permission_denied(boost::system::windows::success, false); |
324 | // check_permission_denied(boost::system::windows::access_denied, true); |
325 | // check_permission_denied(boost::system::windows::not_enough_memory, false); |
326 | // check_out_of_memory(boost::system::windows::success, false); |
327 | // check_out_of_memory(boost::system::windows::access_denied, false); |
328 | // check_out_of_memory(boost::system::windows::not_enough_memory, true); |
329 | //# endif |
330 | // |
331 | // printf("\n"); |
332 | // } |
333 | // |
334 | //} // namespace test3 |
335 | |
336 | |
337 | |
338 | // ------------------------------------------------------------------------ // |
339 | |
340 | int main( int, char *[] ) |
341 | { |
342 | boost::system::error_code ec; |
343 | |
344 | // Library 1 tests: |
345 | |
346 | ec = my_mkdir( path: "/no-such-file-or-directory/will-not-succeed" ); |
347 | std::cout << "ec.value() is " << ec.value() << '\n'; |
348 | |
349 | BOOST_TEST( ec ); |
350 | BOOST_TEST( ec == boost::system::errc::no_such_file_or_directory ); |
351 | BOOST_TEST( ec.category() == boost::system::system_category() ); |
352 | |
353 | // Library 2 tests: |
354 | |
355 | ec = my_remove( path: "/no-such-file-or-directory" ); |
356 | std::cout << "ec.value() is " << ec.value() << '\n'; |
357 | |
358 | BOOST_TEST( ec ); |
359 | BOOST_TEST( ec == boost::system::errc::no_such_file_or_directory ); |
360 | BOOST_TEST( ec.category() == boost::system::generic_category() ); |
361 | |
362 | // Library 3 tests: |
363 | |
364 | ec = boost::lib3::boo_boo; |
365 | std::cout << "ec.value() is " << ec.value() << '\n'; |
366 | |
367 | BOOST_TEST( ec ); |
368 | BOOST_TEST( ec == boost::lib3::boo_boo ); |
369 | BOOST_TEST( ec.value() == boost::lib3::boo_boo ); |
370 | BOOST_TEST( ec.category() == boost::lib3::lib3_error_category ); |
371 | |
372 | BOOST_TEST( ec == boost::system::errc::io_error ); |
373 | |
374 | boost::system::error_code ec3( boost::lib3::boo_boo+100, |
375 | boost::lib3::lib3_error_category ); |
376 | BOOST_TEST( ec3.category() == boost::lib3::lib3_error_category ); |
377 | BOOST_TEST( ec3.default_error_condition().category() |
378 | == boost::lib3::lib3_error_category ); |
379 | |
380 | // Library 4 tests: |
381 | |
382 | ec = lib4::boo_boo; |
383 | std::cout << "ec.value() is " << ec.value() << '\n'; |
384 | |
385 | BOOST_TEST( ec ); |
386 | BOOST_TEST( ec == lib4::boo_boo ); |
387 | BOOST_TEST( ec.value() == lib4::boo_boo.value() ); |
388 | BOOST_TEST( ec.category() == lib4::lib4_error_category ); |
389 | |
390 | BOOST_TEST( ec == boost::system::errc::io_error ); |
391 | |
392 | boost::system::error_code ec4( lib4::boo_boo.value()+100, |
393 | lib4::lib4_error_category ); |
394 | BOOST_TEST( ec4.default_error_condition().category() |
395 | == lib4::lib4_error_category ); |
396 | |
397 | // Test 3 |
398 | |
399 | //test3::run(); |
400 | |
401 | return ::boost::report_errors(); |
402 | } |
403 | |