1e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* 2e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1997 3e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Mark of the Unicorn, Inc. 4e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * 5e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to use, copy, modify, distribute and sell this software 6e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * and its documentation for any purpose is hereby granted without fee, 7e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * provided that the above copyright notice appear in all copies and 8e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * that both that copyright notice and this permission notice appear 9e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * in supporting documentation. Mark of the Unicorn makes no 10e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * representations about the suitability of this software for any 11e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * purpose. It is provided "as is" without express or implied warranty. 12e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */ 13e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*********************************************************************************** 14e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott LeakCheck.h 15e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 16e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott SUMMARY: A suite of template functions for verifying the behavior of 17e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott operations in the presence of exceptions. Requires that the operations 18e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott be written so that each operation that could cause an exception causes 19e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott simulate_possible_failure() to be called (see "nc_alloc.h"). 20e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 21e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott***********************************************************************************/ 22e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef INCLUDED_MOTU_LeakCheck 23e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#define INCLUDED_MOTU_LeakCheck 1 24e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 25e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "Prefix.h" 26e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 27e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "nc_alloc.h" 28e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 29e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <cstdio> 30e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <cassert> 31e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <iterator> 32e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 33e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <iostream> 34e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 35e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick ScottEH_BEGIN_NAMESPACE 36e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 37e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class T1, class T2> 38e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline ostream& operator << ( 39e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottostream& s, 40e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottconst pair <T1, T2>& p) { 41e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott return s<<'['<<p.first<<":"<<p.second<<']'; 42e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 43e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick ScottEH_END_NAMESPACE 44e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 45e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*=================================================================================== 46e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott CheckInvariant 47e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 48e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EFFECTS: Generalized function to check an invariant on a container. Specialize 49e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott this for particular containers if such a check is available. 50e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott====================================================================================*/ 51e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class C> 52e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid CheckInvariant(const C&) 53e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{} 54e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 55e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*=================================================================================== 56e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott WeakCheck 57e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 58e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EFFECTS: Given a value and an operation, repeatedly applies the operation to a 59e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott copy of the value triggering the nth possible exception, where n increments 60e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott with each repetition until no exception is thrown or max_iters is reached. 61e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott Reports any detected memory leaks and checks any invariant defined for the 62e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott value type whether the operation succeeds or fails. 63e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott====================================================================================*/ 64e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class Value, class Operation> 65e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid WeakCheck(const Value& v, const Operation& op, long max_iters = 2000000) { 66e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool succeeded = false; 67e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool failed = false; 68e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetCurrentTestCategory("weak"); 69e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (long count = 0; !succeeded && !failed && count < max_iters; ++count) { 70e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.BeginLeakDetection(); 71e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { 72e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott Value dup = v; 73e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef EH_NO_EXCEPTIONS 74e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott try { 75e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 76e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetFailureCountdown(count); 77e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott op( dup ); 78e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott succeeded = true; 79e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef EH_NO_EXCEPTIONS 80e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 81e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott catch (...) {} // Just try again. 82e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 83e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.CancelFailureCountdown(); 84e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott CheckInvariant(dup); 85e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 86e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott failed = gTestController.ReportLeaked(); 87e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( !failed ); 88e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 89e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( succeeded ) 90e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.ReportSuccess(count); 91e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 92e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( succeeded || failed ); // Make sure the count hasn't gone over 93e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 94e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 95e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*=================================================================================== 96e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott ConstCheck 97e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 98e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EFFECTS: Similar to WeakCheck (above), but for operations which may not modify 99e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott their arguments. The operation is performed on the value itself, and no 100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott invariant checking is performed. Leak checking still occurs. 101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott====================================================================================*/ 102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class Value, class Operation> 103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid ConstCheck(const Value& v, const Operation& op, long max_iters = 2000000) { 104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool succeeded = false; 105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool failed = false; 106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetCurrentTestCategory("const"); 107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for (long count = 0; !succeeded && !failed && count < max_iters; ++count) { 108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.BeginLeakDetection(); 109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { 110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef EH_NO_EXCEPTIONS 111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott try { 112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetFailureCountdown(count); 114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott op( v ); 115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott succeeded = true; 116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef EH_NO_EXCEPTIONS 117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott catch(...) {} // Just try again. 119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# endif 120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.CancelFailureCountdown(); 121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 122e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott failed = gTestController.ReportLeaked(); 123e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( !failed ); 124e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 125e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( succeeded ) 126e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.ReportSuccess(count); 127e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 128e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( succeeded || failed ); // Make sure the count hasn't gone over 129e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 130e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 131e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*=================================================================================== 132e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott StrongCheck 133e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 134e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EFFECTS: Similar to WeakCheck (above), but additionally checks a component of 135e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott the "strong guarantee": if the operation fails due to an exception, the 136e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott value being operated on must be unchanged, as checked with operator==(). 137e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 138e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott CAVEATS: Note that this does not check everything required for the strong 139e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott guarantee, which says that if an exception is thrown, the operation has no 140e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott effects. Do do that we would have to check that no there were no side-effects 141e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott on objects which are not part of v (e.g. iterator validity must be preserved). 142e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 143e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott====================================================================================*/ 144e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class Value, class Operation> 145e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid StrongCheck(const Value& v, const Operation& op, long max_iters = 2000000) { 146e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool succeeded = false; 147e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool failed = false; 148e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetCurrentTestCategory("strong"); 149e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott for ( long count = 0; !succeeded && !failed && count < max_iters; count++ ) { 150e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.BeginLeakDetection(); 151e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 152e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { 153e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott Value dup = v; 154e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott { 155e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifndef EH_NO_EXCEPTIONS 156e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott try { 157e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 158e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.SetFailureCountdown(count); 159e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott op( dup ); 160e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott succeeded = true; 161e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.CancelFailureCountdown(); 162e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# ifndef EH_NO_EXCEPTIONS 163e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 164e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott catch (...) { 165e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.CancelFailureCountdown(); 166e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool unchanged = (dup == v); 167e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( unchanged ); 168e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 169e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( !unchanged ) { 170e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if 0 171e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott typedef typename Value::value_type value_type; 172e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::ostream_iterator<value_type> o(EH_STD::cerr, " "); 173e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::cerr<<"EH test FAILED:\nStrong guaranee failed !\n"; 174e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::copy(dup.begin(), dup.end(), o); 175e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::cerr<<"\nOriginal is:\n"; 176e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::copy(v.begin(), v.end(), o); 177e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_STD::cerr<<EH_STD::endl; 178e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif 179e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott failed = true; 180e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 181e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } // Just try again. 182e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott# endif 183e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott CheckInvariant(v); 184e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 185e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 186e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 187e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott bool leaked = gTestController.ReportLeaked(); 188e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( !leaked ); 189e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( leaked ) 190e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott failed = true; 191e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 192e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott if ( succeeded ) 193e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott gTestController.ReportSuccess(count); 194e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott } 195e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott EH_ASSERT( succeeded || failed ); // Make sure the count hasn't gone over 196e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott} 197e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott 198e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif // INCLUDED_MOTU_LeakCheck 199