diff options
author | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2009-07-03 03:05:16 +0000 |
---|---|---|
committer | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2009-07-03 03:05:16 +0000 |
commit | 4faef16792bd0a33274147315017578994a39eb5 (patch) | |
tree | 1123ced30511ecc36b29d75253a8b8d8e4f0c2bc | |
parent | d13b27359e58220368c9a8b9f5dc1306ce3bdd4c (diff) | |
download | ATCD-4faef16792bd0a33274147315017578994a39eb5.tar.gz |
Fri Jul 3 03:03:56 UTC 2009 Carlos O'Ryan <coryan@glamdring>
* tests/run_test.lst:
* tests/Makefile.am:
* tests/tests.mpc:
* tests/Compiler_Features_10_Test.cpp:
Add new test for exceptions. Verify that <stdexcept> is there,
that we can raise exceptions, and that object destruction during
exceptions is sound.
-rw-r--r-- | ACE/ChangeLog | 10 | ||||
-rw-r--r-- | ACE/tests/Compiler_Features_10_Test.cpp | 287 | ||||
-rw-r--r-- | ACE/tests/Makefile.am | 20 | ||||
-rw-r--r-- | ACE/tests/run_test.lst | 1 | ||||
-rw-r--r-- | ACE/tests/tests.mpc | 7 |
5 files changed, 325 insertions, 0 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog index a739ff79d31..9cb21e7a093 100644 --- a/ACE/ChangeLog +++ b/ACE/ChangeLog @@ -1,3 +1,13 @@ +Fri Jul 3 03:03:56 UTC 2009 Carlos O'Ryan <coryan@glamdring> + + * tests/run_test.lst: + * tests/Makefile.am: + * tests/tests.mpc: + * tests/Compiler_Features_10_Test.cpp: + Add new test for exceptions. Verify that <stdexcept> is there, + that we can raise exceptions, and that object destruction during + exceptions is sound. + Thu Jul 2 12:05:03 UTC 2009 Carlos O'Ryan <coryan@glamdring> * tests/Compiler_Features_07_Test.cpp: 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; +} + +} diff --git a/ACE/tests/Makefile.am b/ACE/tests/Makefile.am index a287ac14afb..74a2882126e 100644 --- a/ACE/tests/Makefile.am +++ b/ACE/tests/Makefile.am @@ -823,6 +823,26 @@ Compiler_Features_09_Test_LDADD = \ endif !BUILD_ACE_FOR_TAO +## Makefile.Compiler_Features_10_Test.am + +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += Compiler_Features_10_Test + +Compiler_Features_10_Test_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) + +Compiler_Features_10_Test_SOURCES = \ + $(ACE_ROOT)/tests/Main.cpp \ + Compiler_Features_10_Test.cpp \ + +Compiler_Features_10_Test_LDADD = \ + libTest_Output.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +endif !BUILD_ACE_FOR_TAO + ## Makefile.Config_Test.am if !BUILD_ACE_FOR_TAO diff --git a/ACE/tests/run_test.lst b/ACE/tests/run_test.lst index 888f36629d8..ba963edd98f 100644 --- a/ACE/tests/run_test.lst +++ b/ACE/tests/run_test.lst @@ -70,6 +70,7 @@ Compiler_Features_06_Test Compiler_Features_07_Test Compiler_Features_08_Test Compiler_Features_09_Test +Compiler_Features_10_Test Config_Test: !LynxOS !VxWorks !ACE_FOR_TAO Conn_Test: !ACE_FOR_TAO DLL_Test: !Unicos !STATIC !KCC_Linux diff --git a/ACE/tests/tests.mpc b/ACE/tests/tests.mpc index eb6223505aa..4f54ee75522 100644 --- a/ACE/tests/tests.mpc +++ b/ACE/tests/tests.mpc @@ -499,6 +499,13 @@ project(Compiler_Features_09_Test) : acetest { } } +project(Compiler_Features_10_Test) : acetest { + exename = Compiler_Features_10_Test + Source_Files { + Compiler_Features_10_Test.cpp + } +} + project(Config Test) : acetest { avoids += ace_for_tao exename = Config_Test |