1 
2 // Copyright 2017 Peter Dimov.
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 //
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 
9 // See library home page at http://www.boost.org/libs/system
10 
11 // Avoid spurious VC++ warnings
12 # define _CRT_SECURE_NO_WARNINGS
13 
14 #include <boost/system/error_code.hpp>
15 #include <boost/config.hpp>
16 #include <boost/config/pragma_message.hpp>
17 #include <iostream>
18 
19 #if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
20 
21 BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" )
22 
main()23 int main()
24 {
25   std::cout
26     << "The version of the C++ standard library being used does not"
27     " support header <system_error> so interoperation will not be tested.\n";
28 }
29 
30 #else
31 
32 #include <boost/core/lightweight_test.hpp>
33 #include <system_error>
34 #include <cerrno>
35 #include <string>
36 #include <cstdio>
37 
test_generic_category()38 static void test_generic_category()
39 {
40     boost::system::error_category const & bt = boost::system::generic_category();
41     std::error_category const & st = bt;
42 
43     BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
44 
45     int ev = ENOENT;
46 
47     BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
48 
49     {
50         boost::system::error_code bc( ev, bt );
51 
52         BOOST_TEST_EQ( bc.value(), ev );
53         BOOST_TEST_EQ( &bc.category(), &bt );
54 
55         std::error_code sc( bc );
56 
57         BOOST_TEST_EQ( sc.value(), ev );
58         BOOST_TEST_EQ( &sc.category(), &st );
59     }
60 
61     {
62         boost::system::error_condition bn = bt.default_error_condition( ev );
63 
64         BOOST_TEST_EQ( bn.value(), ev );
65         BOOST_TEST_EQ( &bn.category(), &bt );
66 
67         BOOST_TEST( bt.equivalent( ev, bn ) );
68 
69         std::error_condition sn( bn );
70 
71         BOOST_TEST_EQ( sn.value(), ev );
72         BOOST_TEST_EQ( &sn.category(), &st );
73 
74         BOOST_TEST( st.equivalent( ev, sn ) );
75     }
76 }
77 
test_system_category()78 static void test_system_category()
79 {
80     boost::system::error_category const & bt = boost::system::system_category();
81     std::error_category const & st = bt;
82 
83     BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
84 
85     {
86         int ev = 5;
87         BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
88 
89         {
90             boost::system::error_code bc( ev, bt );
91 
92             BOOST_TEST_EQ( bc.value(), ev );
93             BOOST_TEST_EQ( &bc.category(), &bt );
94 
95             std::error_code sc( bc );
96 
97             BOOST_TEST_EQ( sc.value(), ev );
98             BOOST_TEST_EQ( &sc.category(), &st );
99         }
100 
101         {
102             boost::system::error_condition bn = bt.default_error_condition( ev );
103             BOOST_TEST( bt.equivalent( ev, bn ) );
104 
105             std::error_condition sn( bn );
106             BOOST_TEST( st.equivalent( ev, sn ) );
107         }
108     }
109 
110     {
111         int ev = 4;
112         BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
113 
114         {
115             boost::system::error_code bc( ev, bt );
116 
117             BOOST_TEST_EQ( bc.value(), ev );
118             BOOST_TEST_EQ( &bc.category(), &bt );
119 
120             std::error_code sc( bc );
121 
122             BOOST_TEST_EQ( sc.value(), ev );
123             BOOST_TEST_EQ( &sc.category(), &st );
124         }
125 
126         {
127             boost::system::error_condition bn = bt.default_error_condition( ev );
128             BOOST_TEST( bt.equivalent( ev, bn ) );
129 
130             std::error_condition sn( bn );
131             BOOST_TEST( st.equivalent( ev, sn ) );
132         }
133     }
134 }
135 
136 // test_user_category
137 
138 class user_category_impl: public boost::system::error_category
139 {
140 public:
141 
name() const142     virtual const char * name() const BOOST_NOEXCEPT
143     {
144         return "user";
145     }
146 
message(int ev) const147     virtual std::string message( int ev ) const
148     {
149         char buffer[ 256 ];
150         std::sprintf( buffer, "user message %d", ev );
151 
152         return buffer;
153     }
154 
default_error_condition(int ev) const155     virtual boost::system::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT
156     {
157         if( ev == 4 )
158         {
159             return boost::system::error_condition( EMFILE, boost::system::generic_category() );
160         }
161         else if( ev == 5 )
162         {
163             return boost::system::error_condition( EACCES, boost::system::generic_category() );
164         }
165         else
166         {
167             return boost::system::error_condition( ev, *this );
168         }
169     }
170 
equivalent(int code,const boost::system::error_condition & condition) const171     virtual bool equivalent( int code, const boost::system::error_condition & condition ) const BOOST_NOEXCEPT
172     {
173         if( code == 4 && condition == make_error_condition( boost::system::errc::too_many_files_open_in_system ) )
174         {
175             return true;
176         }
177 
178         if( code == 4 && condition == make_error_condition( boost::system::errc::too_many_files_open ) )
179         {
180             return true;
181         }
182 
183         return default_error_condition( code ) == condition;
184     }
185 
186     // virtual bool equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT;
187 };
188 
user_category()189 boost::system::error_category const & user_category()
190 {
191     static user_category_impl cat_;
192     return cat_;
193 }
194 
test_user_category()195 static void test_user_category()
196 {
197     boost::system::error_category const & bt = user_category();
198     std::error_category const & st = bt;
199 
200     BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
201 
202     {
203         int ev = 5;
204         BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
205 
206         {
207             boost::system::error_code bc( ev, bt );
208 
209             BOOST_TEST_EQ( bc.value(), ev );
210             BOOST_TEST_EQ( &bc.category(), &bt );
211 
212             std::error_code sc( bc );
213 
214             BOOST_TEST_EQ( sc.value(), ev );
215             BOOST_TEST_EQ( &sc.category(), &st );
216         }
217 
218         {
219             boost::system::error_condition bn = bt.default_error_condition( ev );
220             BOOST_TEST( bt.equivalent( ev, bn ) );
221 
222             std::error_condition sn( bn );
223             BOOST_TEST( st.equivalent( ev, sn ) );
224         }
225     }
226 
227     {
228         int ev = 4;
229         BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
230 
231         {
232             boost::system::error_code bc( ev, bt );
233 
234             BOOST_TEST_EQ( bc.value(), ev );
235             BOOST_TEST_EQ( &bc.category(), &bt );
236 
237             std::error_code sc( bc );
238 
239             BOOST_TEST_EQ( sc.value(), ev );
240             BOOST_TEST_EQ( &sc.category(), &st );
241         }
242 
243         {
244             boost::system::error_condition bn = bt.default_error_condition( ev );
245             BOOST_TEST( bt.equivalent( ev, bn ) );
246 
247             std::error_condition sn( bn );
248             BOOST_TEST( st.equivalent( ev, sn ) );
249         }
250 
251         {
252             boost::system::error_condition bn = make_error_condition( boost::system::errc::too_many_files_open_in_system );
253             BOOST_TEST( bt.equivalent( ev, bn ) );
254 
255             std::error_condition sn( bn );
256             BOOST_TEST( st.equivalent( ev, sn ) );
257         }
258 
259         {
260             boost::system::error_condition bn = make_error_condition( boost::system::errc::too_many_files_open );
261             BOOST_TEST( bt.equivalent( ev, bn ) );
262 
263             std::error_condition sn( bn );
264             BOOST_TEST( st.equivalent( ev, sn ) );
265         }
266     }
267 }
268 
269 // test_user2_category
270 
271 enum user2_errc
272 {
273     my_enoent = 1,
274     my_einval,
275     my_other
276 };
277 
278 class user2_category_impl: public boost::system::error_category
279 {
280 public:
281 
name() const282     virtual const char * name() const BOOST_NOEXCEPT
283     {
284         return "user2";
285     }
286 
message(int ev) const287     virtual std::string message( int ev ) const
288     {
289         char buffer[ 256 ];
290         std::sprintf( buffer, "user2 message %d", ev );
291 
292         return buffer;
293     }
294 
default_error_condition(int ev) const295     virtual boost::system::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT
296     {
297         return boost::system::error_condition( ev, *this );
298     }
299 
equivalent(int code,const boost::system::error_condition & condition) const300     virtual bool equivalent( int code, const boost::system::error_condition & condition ) const BOOST_NOEXCEPT
301     {
302         return default_error_condition( code ) == condition;
303     }
304 
equivalent(const boost::system::error_code & code,int condition) const305     virtual bool equivalent( const boost::system::error_code & code, int condition ) const BOOST_NOEXCEPT
306     {
307         if( code.category() == *this )
308         {
309             return condition == code.value();
310         }
311         else if( condition == my_enoent )
312         {
313             return code == boost::system::errc::no_such_file_or_directory;
314         }
315         else if( condition == my_einval )
316         {
317             return code == boost::system::errc::invalid_argument;
318         }
319         else
320         {
321             return false;
322         }
323     }
324 };
325 
user2_category()326 boost::system::error_category const & user2_category()
327 {
328     static user2_category_impl cat_;
329     return cat_;
330 }
331 
test_user2_category()332 static void test_user2_category()
333 {
334     boost::system::error_category const & bt = user2_category();
335     std::error_category const & st = bt;
336 
337     int ev = my_enoent;
338 
339     boost::system::error_condition bn( ev, bt );
340 
341     BOOST_TEST_EQ( bn.value(), ev );
342     BOOST_TEST_EQ( &bn.category(), &bt );
343 
344     boost::system::error_code bc = make_error_code( boost::system::errc::no_such_file_or_directory );
345 
346     BOOST_TEST( bc == bn );
347 
348     std::error_condition sn( bn );
349 
350     BOOST_TEST_EQ( sn.value(), ev );
351     BOOST_TEST_EQ( &sn.category(), &st );
352 
353     std::error_code sc( bc );
354 
355     BOOST_TEST( sc == sn );
356 }
357 
358 //
359 
main()360 int main()
361 {
362     std::cout
363       << "The version of the C++ standard library being used"
364       " supports header <system_error> so interoperation will be tested.\n";
365     test_generic_category();
366     test_system_category();
367     test_user_category();
368     test_user2_category();
369 
370     return boost::report_errors();
371 }
372 
373 #endif
374