Doxygen changes
[ACE_TAO.git] / ACE / tests / Compiler_Features_10_Test.cpp
blob6882b31631579e5975b1a85bf65dccc8d7b41c15
1 /**
2 * @file
4 * This program checks if the compiler / platform supports exceptions,
5 * in particular, if raising exceptions in constructors work. The
6 * motivation for this test was a discussion on the development
7 * mailing list, and the documentation was captured in:
9 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3715
12 #include "test_config.h"
14 // The first part of the test is to compile this line. If the program
15 // does not compile the platform is just too broken.
16 #include <memory>
18 // ... using exceptions with C++ also implies using the standard
19 // exceptions ...
20 #include <stdexcept>
22 // For extra challenge, we use the anonymous namespace
23 namespace
25 int constructors = 0;
26 int destructors = 0;
27 int allocs = 0;
28 int deallocs = 0;
29 bool had_failure = false;
31 void check_constructor_count(int expected,
32 char const * filename,
33 int lineno);
34 void check_destructor_count(int expected,
35 char const * filename,
36 int lineno);
37 void check_alloc_count(int expected,
38 char const * filename,
39 int lineno);
40 void reset_counts();
41 void never_reached(char const * filename,
42 int lineno);
43 int status();
45 /**
46 * @class Base
48 class Base
50 public:
51 Base()
53 ++constructors;
55 Base(Base const & )
57 ++constructors;
59 ~Base()
61 ++destructors;
64 void * operator new(size_t n)
66 ++allocs;
67 return ::operator new(n);
69 void operator delete(void * x)
71 ++deallocs;
72 return ::operator delete(x);
76 /**
77 * @class May_Pop
79 * Create a class that can raise exceptions in its constructor
82 class May_Pop : public Base
84 public:
85 explicit May_Pop(bool do_raise)
86 // Even if an exception is raised, the base object is fully
87 // constructed and must be fully destructed ...
88 : Base()
90 if (do_raise)
92 throw std::runtime_error("requested exception");
94 // ... if an exception is raised this object is never
95 // initialized and no constructor / destructor calls should take
96 // place ...
97 Base tmp;
102 * @class Aggregate
104 class Aggregate : public Base
106 private:
107 May_Pop m1;
108 May_Pop m2;
109 May_Pop m3;
111 public:
113 * Constructor. Element m1 is fully initialized, its constructors
114 * and destructors should run, m2 is partially initialized, its
115 * destructor never runs, m3 is never initialized, neither its
116 * constructor nor destructor runs.
118 Aggregate()
119 : Base()
120 , m1(false)
121 , m2(true)
122 , m3(false)
130 run_main (int, ACE_TCHAR *[])
132 ACE_START_TEST (ACE_TEXT("Compiler_Features_10_Test"));
135 // ... start the test fresh ...
136 reset_counts();
137 // Let's try to build a simple object and destroy it, without any
138 // exceptions raised ...
139 May_Pop m1(false);
140 // ... two instances of the base class should be created ...
141 check_constructor_count(2, __FILE__, __LINE__);
142 // ... but only one instance is destroyed at this point ...
143 check_destructor_count(1, __FILE__, __LINE__);
145 catch (...)
147 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Error: Unexpected exception caught\n")));
149 // ... now both instances are gone ...
150 check_destructor_count(2, __FILE__, __LINE__);
154 // ... start the test fresh ...
155 reset_counts();
156 // ... now raise an exception ...
157 May_Pop m1(true);
158 never_reached(__FILE__, __LINE__);
160 catch(...)
162 // ... only one instance gets created ...
163 check_constructor_count(1, __FILE__, __LINE__);
164 // ... and it is gone ...
165 check_destructor_count(1, __FILE__, __LINE__);
170 // ... start the test fresh ...
171 reset_counts();
172 // ... now build a complex object with a failure in the middle ...
173 Aggregate a;
174 never_reached(__FILE__, __LINE__);
176 catch(...)
178 // ... check the expectations ...
179 check_constructor_count(4, __FILE__, __LINE__);
180 check_destructor_count(4, __FILE__, __LINE__);
185 // ... start the test fresh ...
186 reset_counts();
187 std::auto_ptr<Aggregate> b(new Aggregate);
188 never_reached(__FILE__, __LINE__);
190 catch(...)
192 // ... check the expectations ...
193 check_constructor_count(4, __FILE__, __LINE__);
194 check_destructor_count(4, __FILE__, __LINE__);
195 check_alloc_count(1, __FILE__, __LINE__);
198 ACE_END_TEST;
199 return status();
202 namespace
205 void
206 check_constructor_count(int expected,
207 char const * filename,
208 int lineno)
210 if (constructors == expected)
212 return;
214 had_failure = true;
215 ACE_ERROR ((LM_ERROR,
216 ACE_TEXT("Expected %d constructor calls, had %d -- (%s:%d)\n"),
217 expected, constructors, filename, lineno));
220 void
221 check_destructor_count(int expected,
222 char const * filename,
223 int lineno)
225 if (destructors == expected)
227 return;
229 had_failure = true;
230 ACE_ERROR ((LM_ERROR,
231 ACE_TEXT("Expected %d destructor calls, had %d -- (%s:%d)\n"),
232 expected, destructors, filename, lineno));
235 void
236 check_alloc_count(int expected,
237 char const * filename,
238 int lineno)
240 if (allocs == expected && deallocs == expected)
242 return;
244 had_failure = true;
245 if (allocs != expected)
247 ACE_ERROR ((LM_ERROR,
248 ACE_TEXT("Expected %d alloc calls, had %d -- (%s:%d)\n"),
249 expected, allocs, filename, lineno));
251 if (deallocs != expected)
253 ACE_ERROR ((LM_ERROR,
254 ACE_TEXT("Expected %d dealloc calls, had %d -- (%s:%d)\n"),
255 expected, deallocs, filename, lineno));
259 void
260 never_reached(char const * filename,
261 int lineno)
263 had_failure = true;
264 ACE_ERROR ((LM_ERROR,
265 ACE_TEXT("Code should not have reached (%s:%d)\n"),
266 filename, lineno));
269 void
270 reset_counts()
272 constructors = 0;
273 destructors = 0;
274 allocs = 0;
275 deallocs = 0;
279 status()
281 if (had_failure)
283 return 1;
285 return 0;