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 | |
19 | static 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 | |
60 | static 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 | |
99 | class user_category_impl: public boost::system::error_category |
100 | { |
101 | public: |
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 | |
150 | boost::system::error_category const & user_category() |
151 | { |
152 | static user_category_impl cat_; |
153 | return cat_; |
154 | } |
155 | |
156 | static 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 | |
232 | enum user2_errc |
233 | { |
234 | my_enoent = 1, |
235 | my_einval, |
236 | my_other |
237 | }; |
238 | |
239 | class user2_category_impl: public boost::system::error_category |
240 | { |
241 | public: |
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 | |
287 | boost::system::error_category const & user2_category() |
288 | { |
289 | static user2_category_impl cat_; |
290 | return cat_; |
291 | } |
292 | |
293 | static 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 | |
321 | int 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 | |