LeakCheck.h

00001 /*
00002  * Copyright (c) 1997
00003  * Mark of the Unicorn, Inc.
00004  *
00005  * Permission to use, copy, modify, distribute and sell this software
00006  * and its documentation for any purpose is hereby granted without fee,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.  Mark of the Unicorn makes no
00010  * representations about the suitability of this software for any
00011  * purpose.  It is provided "as is" without express or implied warranty.
00012  */
00013 /***********************************************************************************
00014         LeakCheck.h
00015         
00016                 SUMMARY: A suite of template functions for verifying the behavior of
00017                         operations in the presence of exceptions. Requires that the operations
00018                         be written so that each operation that could cause an exception causes
00019                         simulate_possible_failure() to be called (see "nc_alloc.h").
00020                 
00021 ***********************************************************************************/
00022 #if !INCLUDED_MOTU_LeakCheck
00023 #define INCLUDED_MOTU_LeakCheck 1
00024 
00025 # include "Prefix.h"
00026 
00027 # include "nc_alloc.h"
00028 
00029 # if defined (EH_NEW_HEADERS)
00030 #  include <cstdio>
00031 #  include <cassert>
00032 #  include <iterator>
00033 # else
00034 #  include <stdio.h>
00035 #  include <assert.h>
00036 #  include <iterator.h>
00037 # endif
00038 
00039 # if defined (EH_NEW_IOSTREAMS)
00040 #  include <iostream>
00041 # else
00042 #  include <iostream.h>
00043 # endif
00044 
00045 EH_BEGIN_NAMESPACE
00046 
00047 template <class T1, class T2>
00048 inline ostream& operator << ( 
00049 ostream& s, 
00050 const pair <T1, T2>& p) {
00051     return s<<'['<<p.first<<":"<<p.second<<']';
00052 }
00053 EH_END_NAMESPACE
00054 
00055 /*===================================================================================
00056         CheckInvariant
00057 
00058         EFFECTS:  Generalized function to check an invariant on a container. Specialize
00059                 this for particular containers if such a check is available.
00060 ====================================================================================*/
00061 template <class C>
00062 void CheckInvariant(const C&)
00063 {
00064 }
00065 
00066 /*===================================================================================
00067         WeakCheck
00068 
00069         EFFECTS: Given a value and an operation, repeatedly applies the operation to a
00070                 copy of the value triggering the nth possible exception, where n increments
00071                 with each repetition until no exception is thrown or max_iters is reached.
00072                 Reports any detected memory leaks and checks any invariant defined for the
00073                 value type whether the operation succeeds or fails.
00074 ====================================================================================*/
00075 template <class Value, class Operation>
00076 void WeakCheck( const Value& v, const Operation& op, long max_iters = 2000000 )
00077 {
00078     bool succeeded = false;
00079     bool failed = false;
00080     gTestController.SetCurrentTestCategory("weak");
00081     for ( long count = 0; !succeeded && !failed && count < max_iters; count++ )
00082     {
00083         gTestController.BeginLeakDetection();
00084         {
00085             Value dup = v;
00086 # ifndef EH_NO_EXCEPTIONS
00087             try {
00088 # endif
00089                 gTestController.SetFailureCountdown(count);
00090                 op( dup );
00091                 succeeded = true;
00092 # ifndef EH_NO_EXCEPTIONS
00093             }
00094             catch(...) {}       // Just try again.
00095 # endif
00096             gTestController.CancelFailureCountdown();
00097             CheckInvariant(dup);
00098         }
00099         failed = gTestController.ReportLeaked();
00100         EH_ASSERT( !failed );
00101         
00102         if ( succeeded )
00103                         gTestController.ReportSuccess(count);
00104     }
00105     EH_ASSERT( succeeded || failed );   // Make sure the count hasn't gone over
00106 }
00107 
00108 /*===================================================================================
00109         ConstCheck
00110 
00111         EFFECTS:  Similar to WeakCheck (above), but for operations which may not modify
00112                 their arguments. The operation is performed on the value itself, and no
00113                 invariant checking is performed. Leak checking still occurs.
00114 ====================================================================================*/
00115 template <class Value, class Operation>
00116 void ConstCheck( const Value& v, const Operation& op, long max_iters = 2000000 )
00117 {
00118     bool succeeded = false;
00119     bool failed = false;
00120     gTestController.SetCurrentTestCategory("const");
00121     for ( long count = 0; !succeeded && !failed && count < max_iters; count++ )
00122     {
00123         gTestController.BeginLeakDetection();
00124         {
00125 # ifndef EH_NO_EXCEPTIONS
00126             try {
00127 # endif
00128                 gTestController.SetFailureCountdown(count);
00129                 op( v );
00130                 succeeded = true;
00131 # ifndef EH_NO_EXCEPTIONS
00132             }
00133             catch(...) {}       // Just try again.
00134 # endif
00135             gTestController.CancelFailureCountdown();
00136         }
00137         failed = gTestController.ReportLeaked();
00138         EH_ASSERT( !failed );
00139 
00140         if ( succeeded )
00141                         gTestController.ReportSuccess(count);
00142     }
00143     EH_ASSERT( succeeded || failed );   // Make sure the count hasn't gone over
00144 }
00145 
00146 /*===================================================================================
00147         StrongCheck
00148 
00149         EFFECTS:  Similar to WeakCheck (above), but additionally checks a component of
00150                 the "strong guarantee": if the operation fails due to an exception, the
00151                 value being operated on must be unchanged, as checked with operator==().
00152                 
00153         CAVEATS: Note that this does not check everything required for the strong
00154                 guarantee, which says that if an exception is thrown, the operation has no
00155                 effects. Do do that we would have to check that no there were no side-effects
00156                 on objects which are not part of v (e.g. iterator validity must be preserved).
00157                 
00158 ====================================================================================*/
00159 template <class Value, class Operation>
00160 void StrongCheck( const Value& v, const Operation& op, long max_iters = 2000000 )
00161 {
00162     bool succeeded = false;
00163     bool failed = false;
00164     gTestController.SetCurrentTestCategory("strong");
00165     for ( long count = 0; !succeeded && !failed && count < max_iters; count++ )
00166     {
00167         gTestController.BeginLeakDetection();
00168 
00169         {
00170             Value dup = v;
00171             {
00172 # ifndef EH_NO_EXCEPTIONS
00173             try
00174 # endif
00175                         {
00176                 gTestController.SetFailureCountdown(count);
00177                 op( dup );
00178                 succeeded = true;
00179                 gTestController.CancelFailureCountdown();
00180                         }
00181 # ifndef EH_NO_EXCEPTIONS
00182             catch(...)
00183             {
00184                 gTestController.CancelFailureCountdown();
00185                 bool unchanged = dup == v;
00186                 EH_ASSERT( unchanged );
00187                 
00188                 if ( !unchanged )
00189                 {
00190 #if 0
00191                     typedef typename Value::value_type value_type;
00192                     EH_STD::ostream_iterator<value_type> o(EH_STD::cerr, " ");
00193                     EH_STD::cerr<<"EH test FAILED:\nStrong guaranee failed !\n";
00194                     EH_STD::copy(dup.begin(), dup.end(), o);
00195                     EH_STD::cerr<<"\nOriginal is:\n";
00196                     EH_STD::copy(v.begin(), v.end(), o);
00197                     EH_STD::cerr<<EH_STD::endl;
00198 #endif
00199                     failed = true;
00200                 }
00201             }   // Just try again.
00202 # endif
00203             CheckInvariant(v);
00204         }
00205 
00206         }
00207 
00208         bool leaked = gTestController.ReportLeaked();
00209         EH_ASSERT( !leaked );
00210         if ( leaked )
00211           failed = true;
00212     
00213         if ( succeeded )
00214                         gTestController.ReportSuccess(count);
00215     }
00216     EH_ASSERT( succeeded || failed );   // Make sure the count hasn't gone over
00217 }
00218 
00219 #endif // INCLUDED_MOTU_LeakCheck

Generated on Mon Jun 5 10:20:48 2006 for Intelligence.kdevelop by  doxygen 1.4.6