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#include <boost/system/error_code.hpp>
12#include <boost/core/lightweight_test.hpp>
13#include <boost/core/snprintf.hpp>
14#include <system_error>
15#include <cerrno>
16#include <string>
17#include <cstdio>
18
19static void test_generic_category()
20{
21 boost::system::error_category const & bt = boost::system::generic_category();
22 std::error_category const & st = bt;
23
24 BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
25
26 int ev = ENOENT;
27
28 // Under MSVC, it's "no such file or directory" instead of "No such file or directory"
29 BOOST_TEST_EQ( bt.message( ev ).substr( 1 ), st.message( ev ).substr( 1 ) );
30
31 {
32 boost::system::error_code bc( ev, bt );
33
34 BOOST_TEST_EQ( bc.value(), ev );
35 BOOST_TEST_EQ( &bc.category(), &bt );
36
37 std::error_code sc( bc );
38
39 BOOST_TEST_EQ( sc.value(), ev );
40 BOOST_TEST_EQ( &sc.category(), &st );
41 }
42
43 {
44 boost::system::error_condition bn = bt.default_error_condition( ev );
45
46 BOOST_TEST_EQ( bn.value(), ev );
47 BOOST_TEST_EQ( &bn.category(), &bt );
48
49 BOOST_TEST( bt.equivalent( ev, bn ) );
50
51 std::error_condition sn( bn );
52
53 BOOST_TEST_EQ( sn.value(), ev );
54 BOOST_TEST_EQ( &sn.category(), &st );
55
56 BOOST_TEST( st.equivalent( ev, sn ) );
57 }
58}
59
60static void test_system_category()
61{
62 boost::system::error_category const & bt = boost::system::system_category();
63 std::error_category const & st = bt;
64
65 BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
66
67 for( int ev = 1; ev < 6; ++ev )
68 {
69 std::string bm = bt.message( ev );
70 std::string sm = st.message( ev );
71
72 // We strip whitespace and the trailing dot, MSVC not so much
73 BOOST_TEST_EQ( bm, sm.substr( 0, bm.size() ) );
74
75 {
76 boost::system::error_code bc( ev, bt );
77
78 BOOST_TEST_EQ( bc.value(), ev );
79 BOOST_TEST_EQ( &bc.category(), &bt );
80
81 std::error_code sc( bc );
82
83 BOOST_TEST_EQ( sc.value(), ev );
84 BOOST_TEST_EQ( &sc.category(), &st );
85 }
86
87 {
88 boost::system::error_condition bn = bt.default_error_condition( ev );
89 BOOST_TEST( bt.equivalent( ev, bn ) );
90
91 std::error_condition sn( bn );
92 BOOST_TEST( st.equivalent( ev, sn ) );
93 }
94 }
95}
96
97// test_user_category
98
99class user_category_impl: public boost::system::error_category
100{
101public:
102
103 virtual const char * name() const noexcept
104 {
105 return "user";
106 }
107
108 virtual std::string message( int ev ) const
109 {
110 char buffer[ 256 ];
111 boost::core::snprintf( s: buffer, maxlen: sizeof( buffer ), format: "user message %d", ev );
112
113 return buffer;
114 }
115
116 virtual boost::system::error_condition default_error_condition( int ev ) const noexcept
117 {
118 if( ev == 4 )
119 {
120 return boost::system::error_condition( EMFILE, boost::system::generic_category() );
121 }
122 else if( ev == 5 )
123 {
124 return boost::system::error_condition( EACCES, boost::system::generic_category() );
125 }
126 else
127 {
128 return boost::system::error_condition( ev, *this );
129 }
130 }
131
132 virtual bool equivalent( int code, const boost::system::error_condition & condition ) const noexcept
133 {
134 if( code == 4 && condition == make_error_condition( e: boost::system::errc::too_many_files_open_in_system ) )
135 {
136 return true;
137 }
138
139 if( code == 4 && condition == make_error_condition( e: boost::system::errc::too_many_files_open ) )
140 {
141 return true;
142 }
143
144 return default_error_condition( ev: code ) == condition;
145 }
146
147 // virtual bool equivalent( const error_code & code, int condition ) const noexcept;
148};
149
150boost::system::error_category const & user_category()
151{
152 static user_category_impl cat_;
153 return cat_;
154}
155
156static void test_user_category()
157{
158 boost::system::error_category const & bt = user_category();
159 std::error_category const & st = bt;
160
161 BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
162
163 {
164 int ev = 5;
165 BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
166
167 {
168 boost::system::error_code bc( ev, bt );
169
170 BOOST_TEST_EQ( bc.value(), ev );
171 BOOST_TEST_EQ( &bc.category(), &bt );
172
173 std::error_code sc( bc );
174
175 BOOST_TEST_EQ( sc.value(), ev );
176 BOOST_TEST_EQ( &sc.category(), &st );
177 }
178
179 {
180 boost::system::error_condition bn = bt.default_error_condition( ev );
181 BOOST_TEST( bt.equivalent( ev, bn ) );
182
183 std::error_condition sn( bn );
184 BOOST_TEST( st.equivalent( ev, sn ) );
185 }
186 }
187
188 {
189 int ev = 4;
190 BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
191
192 {
193 boost::system::error_code bc( ev, bt );
194
195 BOOST_TEST_EQ( bc.value(), ev );
196 BOOST_TEST_EQ( &bc.category(), &bt );
197
198 std::error_code sc( bc );
199
200 BOOST_TEST_EQ( sc.value(), ev );
201 BOOST_TEST_EQ( &sc.category(), &st );
202 }
203
204 {
205 boost::system::error_condition bn = bt.default_error_condition( ev );
206 BOOST_TEST( bt.equivalent( ev, bn ) );
207
208 std::error_condition sn( bn );
209 BOOST_TEST( st.equivalent( ev, sn ) );
210 }
211
212 {
213 boost::system::error_condition bn = make_error_condition( e: boost::system::errc::too_many_files_open_in_system );
214 BOOST_TEST( bt.equivalent( ev, bn ) );
215
216 std::error_condition sn( bn );
217 BOOST_TEST( st.equivalent( ev, sn ) );
218 }
219
220 {
221 boost::system::error_condition bn = make_error_condition( e: boost::system::errc::too_many_files_open );
222 BOOST_TEST( bt.equivalent( ev, bn ) );
223
224 std::error_condition sn( bn );
225 BOOST_TEST( st.equivalent( ev, sn ) );
226 }
227 }
228}
229
230// test_user2_category
231
232enum user2_errc
233{
234 my_enoent = 1,
235 my_einval,
236 my_other
237};
238
239class user2_category_impl: public boost::system::error_category
240{
241public:
242
243 virtual const char * name() const noexcept
244 {
245 return "user2";
246 }
247
248 virtual std::string message( int ev ) const
249 {
250 char buffer[ 256 ];
251 boost::core::snprintf( s: buffer, maxlen: sizeof( buffer ), format: "user2 message %d", ev );
252
253 return buffer;
254 }
255
256 virtual boost::system::error_condition default_error_condition( int ev ) const noexcept
257 {
258 return boost::system::error_condition( ev, *this );
259 }
260
261 virtual bool equivalent( int code, const boost::system::error_condition & condition ) const noexcept
262 {
263 return default_error_condition( ev: code ) == condition;
264 }
265
266 virtual bool equivalent( const boost::system::error_code & code, int condition ) const noexcept
267 {
268 if( code.category() == *this )
269 {
270 return condition == code.value();
271 }
272 else if( condition == my_enoent )
273 {
274 return code == boost::system::errc::no_such_file_or_directory;
275 }
276 else if( condition == my_einval )
277 {
278 return code == boost::system::errc::invalid_argument;
279 }
280 else
281 {
282 return false;
283 }
284 }
285};
286
287boost::system::error_category const & user2_category()
288{
289 static user2_category_impl cat_;
290 return cat_;
291}
292
293static void test_user2_category()
294{
295 boost::system::error_category const & bt = user2_category();
296 std::error_category const & st = bt;
297
298 int ev = my_enoent;
299
300 boost::system::error_condition bn( ev, bt );
301
302 BOOST_TEST_EQ( bn.value(), ev );
303 BOOST_TEST_EQ( &bn.category(), &bt );
304
305 boost::system::error_code bc = make_error_code( e: boost::system::errc::no_such_file_or_directory );
306
307 BOOST_TEST( bc == bn );
308
309 std::error_condition sn( bn );
310
311 BOOST_TEST_EQ( sn.value(), ev );
312 BOOST_TEST_EQ( &sn.category(), &st );
313
314 std::error_code sc( bc );
315
316 BOOST_TEST( sc == sn );
317}
318
319//
320
321int main()
322{
323 test_generic_category();
324 test_system_category();
325 test_user_category();
326 test_user2_category();
327
328 return boost::report_errors();
329}
330

source code of boost/libs/system/test/std_interop_test.cpp