1 | //Copyright (c) 2006-2015 Emil Dotchevski and Reverge Studios, Inc. |
2 | |
3 | //Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #include <boost/config.hpp> |
7 | |
8 | #if defined( BOOST_NO_EXCEPTIONS ) |
9 | # error This program requires exception handling. |
10 | #endif |
11 | |
12 | #include <boost/exception/get_error_info.hpp> |
13 | #include <boost/exception/info_tuple.hpp> |
14 | #include <boost/exception_ptr.hpp> |
15 | #include <boost/detail/lightweight_test.hpp> |
16 | #include <boost/detail/workaround.hpp> |
17 | |
18 | struct throws_on_copy; |
19 | struct non_printable { }; |
20 | |
21 | struct |
22 | user_data |
23 | { |
24 | int & count; |
25 | |
26 | explicit |
27 | user_data( int & count ): |
28 | count(count) |
29 | { |
30 | ++count; |
31 | } |
32 | |
33 | user_data( user_data const & x ): |
34 | count(x.count) |
35 | { |
36 | ++count; |
37 | } |
38 | |
39 | ~user_data() |
40 | { |
41 | --count; |
42 | } |
43 | }; |
44 | |
45 | typedef boost::error_info<struct tag_test_1,int> test_1; |
46 | typedef boost::error_info<struct tag_test_2,unsigned int> test_2; |
47 | typedef boost::error_info<struct tag_test_3,float> test_3; |
48 | typedef boost::error_info<struct tag_test_4,throws_on_copy> test_4; |
49 | typedef boost::error_info<struct tag_test_5,std::string> test_5; |
50 | typedef boost::error_info<struct tag_test_6,non_printable> test_6; |
51 | typedef boost::error_info<struct tag_user_data,user_data> test_7; |
52 | |
53 | struct |
54 | test_exception: |
55 | boost::exception |
56 | { |
57 | }; |
58 | |
59 | struct |
60 | throws_on_copy |
61 | { |
62 | throws_on_copy() |
63 | { |
64 | } |
65 | |
66 | throws_on_copy( throws_on_copy const & ) |
67 | { |
68 | throw test_exception(); |
69 | } |
70 | }; |
71 | |
72 | void |
73 | basic_test() |
74 | { |
75 | try |
76 | { |
77 | test_exception x; |
78 | add_info(e: add_info(e: add_info(e: x,i: test_1(1)),i: test_2(2u)),i: test_3(3.14159f)); |
79 | throw x; |
80 | } |
81 | catch( |
82 | test_exception & x ) |
83 | { |
84 | ++*boost::get_error_info<test_1>(some_exception&: x); |
85 | ++*boost::get_error_info<test_2>(some_exception&: x); |
86 | ++*boost::get_error_info<test_3>(some_exception&: x); |
87 | BOOST_TEST(*boost::get_error_info<test_1>(x)==2); |
88 | BOOST_TEST(*boost::get_error_info<test_2>(x)==3u); |
89 | BOOST_TEST(*boost::get_error_info<test_3>(x)==4.14159f); |
90 | BOOST_TEST(!boost::get_error_info<test_4>(x)); |
91 | } |
92 | try |
93 | { |
94 | test_exception x; |
95 | add_info(e: add_info(e: add_info(e: x,i: test_1(1)),i: test_2(2u)),i: test_3(3.14159f)); |
96 | throw x; |
97 | } |
98 | catch( |
99 | test_exception const & x ) |
100 | { |
101 | BOOST_TEST(*boost::get_error_info<test_1>(x)==1); |
102 | BOOST_TEST(*boost::get_error_info<test_2>(x)==2u); |
103 | BOOST_TEST(*boost::get_error_info<test_3>(x)==3.14159f); |
104 | BOOST_TEST(!boost::get_error_info<test_4>(x)); |
105 | } |
106 | } |
107 | |
108 | void |
109 | exception_safety_test() |
110 | { |
111 | test_exception x; |
112 | try |
113 | { |
114 | add_info(e: x,i: test_4(throws_on_copy())); |
115 | BOOST_TEST(false); |
116 | } |
117 | catch( |
118 | test_exception & ) |
119 | { |
120 | BOOST_TEST(!boost::get_error_info<test_4>(x)); |
121 | } |
122 | } |
123 | |
124 | void |
125 | throw_empty() |
126 | { |
127 | throw test_exception(); |
128 | } |
129 | |
130 | void |
131 | throw_test_1( char const * value ) |
132 | { |
133 | throw add_info(e: test_exception(),i: test_5(std::string(value))); |
134 | } |
135 | |
136 | void |
137 | throw_test_2() |
138 | { |
139 | throw add_info(e: test_exception(),i: test_6(non_printable())); |
140 | } |
141 | |
142 | void |
143 | throw_catch_add_file_name( char const * name ) |
144 | { |
145 | try |
146 | { |
147 | throw_empty(); |
148 | BOOST_TEST(false); |
149 | } |
150 | catch( |
151 | boost::exception & x ) |
152 | { |
153 | add_info(e: x,i: test_5(std::string(name))); |
154 | throw; |
155 | } |
156 | } |
157 | |
158 | void |
159 | test_empty() |
160 | { |
161 | try |
162 | { |
163 | throw_empty(); |
164 | BOOST_TEST(false); |
165 | } |
166 | catch( |
167 | boost::exception & x ) |
168 | { |
169 | #ifndef BOOST_NO_RTTI |
170 | BOOST_TEST( dynamic_cast<test_exception *>(&x) ); |
171 | #endif |
172 | BOOST_TEST( !boost::get_error_info<test_1>(x) ); |
173 | } |
174 | catch( |
175 | ... ) |
176 | { |
177 | BOOST_TEST(false); |
178 | } |
179 | |
180 | try |
181 | { |
182 | throw_empty(); |
183 | BOOST_TEST(false); |
184 | } |
185 | catch( |
186 | test_exception & x ) |
187 | { |
188 | #ifndef BOOST_NO_RTTI |
189 | BOOST_TEST( dynamic_cast<boost::exception const *>(&x)!=0 ); |
190 | #endif |
191 | } |
192 | catch( |
193 | ... ) |
194 | { |
195 | BOOST_TEST(false); |
196 | } |
197 | } |
198 | |
199 | void |
200 | test_basic_throw_catch() |
201 | { |
202 | try |
203 | { |
204 | throw_test_1(value: "test" ); |
205 | BOOST_ASSERT(false); |
206 | } |
207 | catch( |
208 | boost::exception & x ) |
209 | { |
210 | BOOST_TEST(*boost::get_error_info<test_5>(x)==std::string("test" )); |
211 | } |
212 | catch( |
213 | ... ) |
214 | { |
215 | BOOST_TEST(false); |
216 | } |
217 | |
218 | try |
219 | { |
220 | throw_test_2(); |
221 | BOOST_ASSERT(false); |
222 | } |
223 | catch( |
224 | boost::exception & x ) |
225 | { |
226 | BOOST_TEST(boost::get_error_info<test_6>(x)); |
227 | } |
228 | catch( |
229 | ... ) |
230 | { |
231 | BOOST_TEST(false); |
232 | } |
233 | } |
234 | |
235 | void |
236 | test_catch_add_info() |
237 | { |
238 | try |
239 | { |
240 | throw_catch_add_file_name(name: "test" ); |
241 | BOOST_TEST(false); |
242 | } |
243 | catch( |
244 | boost::exception & x ) |
245 | { |
246 | BOOST_TEST(*boost::get_error_info<test_5>(x)==std::string("test" )); |
247 | } |
248 | catch( |
249 | ... ) |
250 | { |
251 | BOOST_TEST(false); |
252 | } |
253 | } |
254 | |
255 | void |
256 | test_add_tuple() |
257 | { |
258 | typedef boost::tuple<> tuple_test_; |
259 | typedef boost::tuple<test_1> tuple_test_1; |
260 | typedef boost::tuple<test_1,test_2> tuple_test_12; |
261 | typedef boost::tuple<test_1,test_2,test_3> tuple_test_123; |
262 | typedef boost::tuple<test_1,test_2,test_3,test_5> tuple_test_1235; |
263 | try |
264 | { |
265 | throw add_info(e: test_exception(),i: tuple_test_()); |
266 | } |
267 | catch( |
268 | test_exception & ) |
269 | { |
270 | } |
271 | catch( |
272 | ... ) |
273 | { |
274 | BOOST_TEST(false); |
275 | } |
276 | try |
277 | { |
278 | throw add_info(e: test_exception(),i: tuple_test_1(42)); |
279 | } |
280 | catch( |
281 | test_exception & x ) |
282 | { |
283 | BOOST_TEST( *boost::get_error_info<test_1>(x)==42 ); |
284 | } |
285 | catch( |
286 | ... ) |
287 | { |
288 | BOOST_TEST(false); |
289 | } |
290 | try |
291 | { |
292 | throw add_info(e: test_exception(),i: tuple_test_12(42,42u)); |
293 | } |
294 | catch( |
295 | test_exception & x ) |
296 | { |
297 | BOOST_TEST( *boost::get_error_info<test_1>(x)==42 ); |
298 | BOOST_TEST( *boost::get_error_info<test_2>(x)==42u ); |
299 | } |
300 | catch( |
301 | ... ) |
302 | { |
303 | BOOST_TEST(false); |
304 | } |
305 | try |
306 | { |
307 | throw add_info(e: test_exception(),i: tuple_test_123(42,42u,42.0f)); |
308 | } |
309 | catch( |
310 | test_exception & x ) |
311 | { |
312 | BOOST_TEST( *boost::get_error_info<test_1>(x)==42 ); |
313 | BOOST_TEST( *boost::get_error_info<test_2>(x)==42u ); |
314 | BOOST_TEST( *boost::get_error_info<test_3>(x)==42.0f ); |
315 | } |
316 | catch( |
317 | ... ) |
318 | { |
319 | BOOST_TEST(false); |
320 | } |
321 | try |
322 | { |
323 | throw add_info(e: test_exception(),i: tuple_test_1235(42,42u,42.0f,std::string("42" ))); |
324 | } |
325 | catch( |
326 | test_exception & x ) |
327 | { |
328 | BOOST_TEST( *boost::get_error_info<test_1>(x)==42 ); |
329 | BOOST_TEST( *boost::get_error_info<test_2>(x)==42u ); |
330 | BOOST_TEST( *boost::get_error_info<test_3>(x)==42.0f ); |
331 | BOOST_TEST( *boost::get_error_info<test_5>(x)=="42" ); |
332 | } |
333 | catch( |
334 | ... ) |
335 | { |
336 | BOOST_TEST(false); |
337 | } |
338 | } |
339 | |
340 | void |
341 | test_lifetime1() |
342 | { |
343 | int count=0; |
344 | try |
345 | { |
346 | throw add_info(e: test_exception(),i: test_7(user_data(count))); |
347 | } |
348 | catch( |
349 | boost::exception & x ) |
350 | { |
351 | BOOST_TEST(count==1); |
352 | BOOST_TEST( boost::get_error_info<test_7>(x) ); |
353 | } |
354 | catch( |
355 | ... ) |
356 | { |
357 | BOOST_TEST(false); |
358 | } |
359 | BOOST_TEST(!count); |
360 | } |
361 | |
362 | void |
363 | test_lifetime2() |
364 | { |
365 | int count=0; |
366 | { |
367 | boost::exception_ptr ep; |
368 | test_exception e; add_info(e,i: test_7(user_data(count))); |
369 | ep=boost::copy_exception(e); |
370 | BOOST_TEST(count>0); |
371 | } |
372 | BOOST_TEST(!count); |
373 | } |
374 | |
375 | bool |
376 | is_const( int const * ) |
377 | { |
378 | return true; |
379 | } |
380 | |
381 | bool |
382 | is_const( int * ) |
383 | { |
384 | return false; |
385 | } |
386 | |
387 | void |
388 | test_const() |
389 | { |
390 | test_exception e; |
391 | boost::exception const & c(e); |
392 | boost::exception & m(e); |
393 | BOOST_TEST(is_const(boost::get_error_info<test_1>(c))); |
394 | BOOST_TEST(!is_const(boost::get_error_info<test_1>(m))); |
395 | } |
396 | |
397 | int |
398 | main() |
399 | { |
400 | basic_test(); |
401 | exception_safety_test(); |
402 | test_empty(); |
403 | test_basic_throw_catch(); |
404 | test_catch_add_info(); |
405 | test_add_tuple(); |
406 | test_lifetime1(); |
407 | test_lifetime2(); |
408 | test_const(); |
409 | return boost::report_errors(); |
410 | } |
411 | |