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