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