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