genericopenlibs/cppstdlib/stl/test/eh/LeakCheck.h
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/cppstdlib/stl/test/eh/LeakCheck.h	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 1997
+ * Mark of the Unicorn, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Mark of the Unicorn makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+/***********************************************************************************
+  LeakCheck.h
+
+    SUMMARY: A suite of template functions for verifying the behavior of
+      operations in the presence of exceptions. Requires that the operations
+      be written so that each operation that could cause an exception causes
+      simulate_possible_failure() to be called (see "nc_alloc.h").
+
+***********************************************************************************/
+#ifndef INCLUDED_MOTU_LeakCheck
+#define INCLUDED_MOTU_LeakCheck 1
+
+#include "Prefix.h"
+
+#include "nc_alloc.h"
+
+#include <cstdio>
+#include <cassert>
+#include <iterator>
+
+#include <iostream>
+
+EH_BEGIN_NAMESPACE
+
+template <class T1, class T2>
+inline ostream& operator << (
+ostream& s,
+const pair <T1, T2>& p) {
+    return s<<'['<<p.first<<":"<<p.second<<']';
+}
+EH_END_NAMESPACE
+
+/*===================================================================================
+  CheckInvariant
+
+  EFFECTS:  Generalized function to check an invariant on a container. Specialize
+    this for particular containers if such a check is available.
+====================================================================================*/
+template <class C>
+void CheckInvariant(const C&)
+{}
+
+/*===================================================================================
+  WeakCheck
+
+  EFFECTS: Given a value and an operation, repeatedly applies the operation to a
+    copy of the value triggering the nth possible exception, where n increments
+    with each repetition until no exception is thrown or max_iters is reached.
+    Reports any detected memory leaks and checks any invariant defined for the
+    value type whether the operation succeeds or fails.
+====================================================================================*/
+template <class Value, class Operation>
+void WeakCheck(const Value& v, const Operation& op, long max_iters = 2000000) {
+  bool succeeded = false;
+  bool failed = false;
+  gTestController.SetCurrentTestCategory("weak");
+  for (long count = 0; !succeeded && !failed && count < max_iters; ++count) {
+    gTestController.BeginLeakDetection();
+    {
+      Value dup = v;
+#ifndef EH_NO_EXCEPTIONS
+      try {
+#endif
+        gTestController.SetFailureCountdown(count);
+        op( dup );
+        succeeded = true;
+#ifndef EH_NO_EXCEPTIONS
+      }
+      catch (...) {}  // Just try again.
+#endif
+      gTestController.CancelFailureCountdown();
+      CheckInvariant(dup);
+    }
+    failed = gTestController.ReportLeaked();
+    EH_ASSERT( !failed );
+
+    if ( succeeded )
+      gTestController.ReportSuccess(count);
+  }
+  EH_ASSERT( succeeded || failed );  // Make sure the count hasn't gone over
+}
+
+/*===================================================================================
+  ConstCheck
+
+  EFFECTS:  Similar to WeakCheck (above), but for operations which may not modify
+    their arguments. The operation is performed on the value itself, and no
+    invariant checking is performed. Leak checking still occurs.
+====================================================================================*/
+template <class Value, class Operation>
+void ConstCheck(const Value& v, const Operation& op, long max_iters = 2000000) {
+  bool succeeded = false;
+  bool failed = false;
+  gTestController.SetCurrentTestCategory("const");
+  for (long count = 0; !succeeded && !failed && count < max_iters; ++count) {
+    gTestController.BeginLeakDetection();
+    {
+#ifndef EH_NO_EXCEPTIONS
+      try {
+#endif
+        gTestController.SetFailureCountdown(count);
+        op( v );
+        succeeded = true;
+#ifndef EH_NO_EXCEPTIONS
+      }
+      catch(...) {}  // Just try again.
+# endif
+      gTestController.CancelFailureCountdown();
+    }
+    failed = gTestController.ReportLeaked();
+    EH_ASSERT( !failed );
+
+    if ( succeeded )
+      gTestController.ReportSuccess(count);
+  }
+  EH_ASSERT( succeeded || failed );  // Make sure the count hasn't gone over
+}
+
+/*===================================================================================
+  StrongCheck
+
+  EFFECTS:  Similar to WeakCheck (above), but additionally checks a component of
+    the "strong guarantee": if the operation fails due to an exception, the
+    value being operated on must be unchanged, as checked with operator==().
+
+  CAVEATS: Note that this does not check everything required for the strong
+    guarantee, which says that if an exception is thrown, the operation has no
+    effects. Do do that we would have to check that no there were no side-effects
+    on objects which are not part of v (e.g. iterator validity must be preserved).
+
+====================================================================================*/
+template <class Value, class Operation>
+void StrongCheck(const Value& v, const Operation& op, long max_iters = 2000000) {
+  bool succeeded = false;
+  bool failed = false;
+  gTestController.SetCurrentTestCategory("strong");
+  for ( long count = 0; !succeeded && !failed && count < max_iters; count++ ) {
+    gTestController.BeginLeakDetection();
+
+    {
+      Value dup = v;
+      {
+#ifndef EH_NO_EXCEPTIONS
+        try {
+#endif
+          gTestController.SetFailureCountdown(count);
+          op( dup );
+          succeeded = true;
+          gTestController.CancelFailureCountdown();
+# ifndef EH_NO_EXCEPTIONS
+        }
+        catch (...) {
+          gTestController.CancelFailureCountdown();
+          bool unchanged = (dup == v);
+          EH_ASSERT( unchanged );
+
+          if ( !unchanged ) {
+#if 0
+            typedef typename Value::value_type value_type;
+            EH_STD::ostream_iterator<value_type> o(EH_STD::cerr, " ");
+            EH_STD::cerr<<"EH test FAILED:\nStrong guaranee failed !\n";
+            EH_STD::copy(dup.begin(), dup.end(), o);
+            EH_STD::cerr<<"\nOriginal is:\n";
+            EH_STD::copy(v.begin(), v.end(), o);
+            EH_STD::cerr<<EH_STD::endl;
+#endif
+            failed = true;
+          }
+        }  // Just try again.
+# endif
+        CheckInvariant(v);
+      }
+    }
+
+    bool leaked = gTestController.ReportLeaked();
+    EH_ASSERT( !leaked );
+    if ( leaked )
+      failed = true;
+
+    if ( succeeded )
+      gTestController.ReportSuccess(count);
+  }
+  EH_ASSERT( succeeded || failed );  // Make sure the count hasn't gone over
+}
+
+#endif // INCLUDED_MOTU_LeakCheck