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
my_mkdir(const std::string & path)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.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
my_remove(const std::string & path)52 boost::system::error_code my_remove( const std::string & path )
53 {
54 return boost::system::error_code(
55 std::remove( 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 {
make_error_code(error e)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:
lib3_error_category_imp()111 lib3_error_category_imp() : boost::system::error_category() { }
112
name() const113 const char * name() const BOOST_SYSTEM_NOEXCEPT
114 {
115 return "lib3";
116 }
117
default_error_condition(int ev) const118 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
message(int ev) const127 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
get_lib3_error_category()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:
lib4_error_category_imp()173 lib4_error_category_imp() : boost::system::error_category() { }
174
name() const175 const char * name() const BOOST_SYSTEM_NOEXCEPT
176 {
177 return "lib4";
178 }
179
default_error_condition(int ev) const180 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
message(int ev) const188 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
get_lib4_error_category()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
main(int,char * [])340 int main( int, char *[] )
341 {
342 boost::system::error_code ec;
343
344 // Library 1 tests:
345
346 ec = my_mkdir( "/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( "/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