summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2009-07-03 03:05:16 +0000
committercoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2009-07-03 03:05:16 +0000
commit4faef16792bd0a33274147315017578994a39eb5 (patch)
tree1123ced30511ecc36b29d75253a8b8d8e4f0c2bc
parentd13b27359e58220368c9a8b9f5dc1306ce3bdd4c (diff)
downloadATCD-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/ChangeLog10
-rw-r--r--ACE/tests/Compiler_Features_10_Test.cpp287
-rw-r--r--ACE/tests/Makefile.am20
-rw-r--r--ACE/tests/run_test.lst1
-rw-r--r--ACE/tests/tests.mpc7
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