diff options
Diffstat (limited to 'ACE/tests/Compiler_Features_10_Test.cpp')
-rw-r--r-- | ACE/tests/Compiler_Features_10_Test.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/ACE/tests/Compiler_Features_10_Test.cpp b/ACE/tests/Compiler_Features_10_Test.cpp new file mode 100644 index 00000000000..b18ef901005 --- /dev/null +++ b/ACE/tests/Compiler_Features_10_Test.cpp @@ -0,0 +1,287 @@ +// $Id$ + +/** + * @file + * + * This program checks if the compiler / platform supports exceptions, + * in particular, if raising exceptions in constructors work. The + * motivation for this test was a discussion on the development + * mailing list, and the documentation was captured in: + * + * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3715 + * + */ + +#include "test_config.h" + +// The first part of the test is to compile this line. If the program +// does not compile the platform is just too broken. +#include <memory> + +// ... using exceptions with C++ also implies using the standard +// exceptions ... +#include <stdexcept> + +// For extra challenge, we use the anonymous namespace +namespace +{ + int constructors = 0; + int destructors = 0; + int allocs = 0; + int deallocs = 0; + bool had_failure = false; + + void check_constructor_count(int expected, + char const * filename, + int lineno); + void check_destructor_count(int expected, + char const * filename, + int lineno); + void check_alloc_count(int expected, + char const * filename, + int lineno); + void reset_counts(); + void never_reached(char const * filename, + int lineno); + int status(); + + /** + * @class Base + */ + class Base + { + public: + Base() + { + ++constructors; + } + Base(Base const & ) + { + ++constructors; + } + ~Base() + { + ++destructors; + } + + void * operator new(size_t n) + { + ++allocs; + return ::operator new(n); + } + void operator delete(void * x) + { + ++deallocs; + return ::operator delete(x); + } + }; + + /** + * @class May_Pop + * + * Create a class that can raise exceptions in its constructor + * + */ + class May_Pop : public Base + { + public: + explicit May_Pop(bool do_raise) + // Even if an exception is raised, the base object is fully + // constructed and must be fully destructed ... + : Base() + { + if (do_raise) + { + throw std::runtime_error("requested exception"); + } + // ... if an exception is raised this object is never + // initialized and no constructor / destructor calls should take + // place ... + Base tmp; + } + }; + + /** + * @class Aggregate + */ + class Aggregate : public Base + { + private: + May_Pop m1; + May_Pop m2; + May_Pop m3; + + public: + /** + * Constructor. Element m1 is fully initialized, its constructors + * and destructors should run, m2 is partially initialized, its + * destructor never runs, m3 is never initialized, neither its + * constructor nor destructor runs. + */ + Aggregate() + : Base() + , m1(false) + , m2(true) + , m3(false) + {} + }; +} + +ACE_RCSID(tests, Compiler_Features_10_Test, "$Id$") + +int +run_main (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT("Compiler_Features_10_Test")); + + { + // ... start the test fresh ... + reset_counts(); + // Let's try to build a simple object and destroy it, without any + // exceptions raised ... + May_Pop m1(false); + // ... two instances of the base class should be created ... + check_constructor_count(2, __FILE__, __LINE__); + // ... but only one instance is destroyed at this point ... + check_destructor_count(1, __FILE__, __LINE__); + } + // ... now both instances are gone ... + check_destructor_count(2, __FILE__, __LINE__); + + try + { + // ... start the test fresh ... + reset_counts(); + // ... now raise an exception ... + May_Pop m1(true); + never_reached(__FILE__, __LINE__); + } + catch(...) + { + // ... only one instance gets created ... + check_constructor_count(1, __FILE__, __LINE__); + // ... and it is gone ... + check_destructor_count(1, __FILE__, __LINE__); + } + + try + { + // ... start the test fresh ... + reset_counts(); + // ... now build a complex object with a failure in the middle ... + Aggregate a; + never_reached(__FILE__, __LINE__); + } + catch(...) + { + // ... check the expectations ... + check_constructor_count(4, __FILE__, __LINE__); + check_destructor_count(4, __FILE__, __LINE__); + } + + try + { + // ... start the test fresh ... + reset_counts(); + std::auto_ptr<Aggregate> b(new Aggregate); + never_reached(__FILE__, __LINE__); + } + catch(...) + { + // ... check the expectations ... + check_constructor_count(4, __FILE__, __LINE__); + check_destructor_count(4, __FILE__, __LINE__); + check_alloc_count(1, __FILE__, __LINE__); + } + + ACE_END_TEST; + return status(); +} + +namespace +{ + +void +check_constructor_count(int expected, + char const * filename, + int lineno) +{ + if (constructors == expected) + { + return; + } + had_failure = true; + ACE_ERROR ((LM_ERROR, + ACE_TEXT("Expected %d constructor calls, had %d -- (%s:%d)\n"), + expected, constructors, filename, lineno)); +} + +void +check_destructor_count(int expected, + char const * filename, + int lineno) +{ + if (destructors == expected) + { + return; + } + had_failure = true; + ACE_ERROR ((LM_ERROR, + ACE_TEXT("Expected %d destructor calls, had %d -- (%s:%d)\n"), + expected, destructors, filename, lineno)); +} + +void +check_alloc_count(int expected, + char const * filename, + int lineno) +{ + if (allocs == expected && deallocs == expected) + { + return; + } + had_failure = true; + if (allocs != expected) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("Expected %d alloc calls, had %d -- (%s:%d)\n"), + expected, allocs, filename, lineno)); + } + if (deallocs != expected) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("Expected %d dealloc calls, had %d -- (%s:%d)\n"), + expected, deallocs, filename, lineno)); + } +} + +void +never_reached(char const * filename, + int lineno) +{ + had_failure = true; + ACE_ERROR ((LM_ERROR, + ACE_TEXT("Code should not have reached (%s:%d)\n"), + filename, lineno)); +} + +void +reset_counts() +{ + constructors = 0; + destructors = 0; + allocs = 0; + deallocs = 0; +} + +int +status() +{ + if (had_failure) + { + return 1; + } + return 0; +} + +} |