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
user_datauser_data27 user_data( int & count ):
28 count(count)
29 {
30 ++count;
31 }
32
user_datauser_data33 user_data( user_data const & x ):
34 count(x.count)
35 {
36 ++count;
37 }
38
~user_datauser_data39 ~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 {
throws_on_copythrows_on_copy62 throws_on_copy()
63 {
64 }
65
throws_on_copythrows_on_copy66 throws_on_copy( throws_on_copy const & )
67 {
68 throw test_exception();
69 }
70 };
71
72 void
basic_test()73 basic_test()
74 {
75 try
76 {
77 test_exception x;
78 add_info(add_info(add_info(x,test_1(1)),test_2(2u)),test_3(3.14159f));
79 throw x;
80 }
81 catch(
82 test_exception & x )
83 {
84 ++*boost::get_error_info<test_1>(x);
85 ++*boost::get_error_info<test_2>(x);
86 ++*boost::get_error_info<test_3>(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(add_info(add_info(x,test_1(1)),test_2(2u)),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
exception_safety_test()109 exception_safety_test()
110 {
111 test_exception x;
112 try
113 {
114 add_info(x,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
throw_empty()125 throw_empty()
126 {
127 throw test_exception();
128 }
129
130 void
throw_test_1(char const * value)131 throw_test_1( char const * value )
132 {
133 throw add_info(test_exception(),test_5(std::string(value)));
134 }
135
136 void
throw_test_2()137 throw_test_2()
138 {
139 throw add_info(test_exception(),test_6(non_printable()));
140 }
141
142 void
throw_catch_add_file_name(char const * name)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(x,test_5(std::string(name)));
154 throw;
155 }
156 }
157
158 void
test_empty()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
test_basic_throw_catch()200 test_basic_throw_catch()
201 {
202 try
203 {
204 throw_test_1("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
test_catch_add_info()236 test_catch_add_info()
237 {
238 try
239 {
240 throw_catch_add_file_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
test_add_tuple()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(test_exception(),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(test_exception(),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(test_exception(),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(test_exception(),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(test_exception(),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
test_lifetime1()341 test_lifetime1()
342 {
343 int count=0;
344 try
345 {
346 throw add_info(test_exception(),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
test_lifetime2()363 test_lifetime2()
364 {
365 int count=0;
366 {
367 boost::exception_ptr ep;
368 test_exception e; add_info(e,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
is_const(int const *)376 is_const( int const * )
377 {
378 return true;
379 }
380
381 bool
is_const(int *)382 is_const( int * )
383 {
384 return false;
385 }
386
387 void
test_const()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
main()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