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