1e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/***********************************************************************************
2e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  TestController.h
3e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
4e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    SUMMARY: An "faux-singleton" object to encapsulate a hodgepodge of state and
5e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      functionality relating to the test suite. Probably should be broken
6e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      into smaller pieces.
7e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
8e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1997
9e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Mark of the Unicorn, Inc.
10e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
11e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to use, copy, modify, distribute and sell this software
12e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * and its documentation for any purpose is hereby granted without fee,
13e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * provided that the above copyright notice appear in all copies and
14e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * that both that copyright notice and this permission notice appear
15e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * in supporting documentation.  Mark of the Unicorn makes no
16e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * representations about the suitability of this software for any
17e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * purpose.  It is provided "as is" without express or implied warranty.
18e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
19e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott***********************************************************************************/
20e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !INCLUDED_MOTU_nc_alloc
21e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#define INCLUDED_MOTU_nc_alloc 1
22e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
23e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "Prefix.h"
24e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
25e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (EH_NEW_HEADERS)
26e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <utility>
27e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
28e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <pair.h>
29e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
30e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
31e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottextern long alloc_count;
32e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottextern long object_count;
33e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
34e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct TestController {
35e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Report that the current test has succeeded.
36e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void ReportSuccess(int);
37e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
38e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
39e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Leak detection
40e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
41e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
42e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Turn the recording of the addresses of individual allocated
43e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // blocks on or off. If not called, allocations will only be
44e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // counted, but deallocations won't be checked for validity.
45e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void TrackAllocations( bool );
46e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool TrackingEnabled();
47e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
48e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Call this to begin a new leak-detection cycle. Resets all
49e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // allocation counts, etc.
50e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void BeginLeakDetection();
51e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
52e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Returns true iff leak detection is currently in effect
53e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool LeakDetectionEnabled();
54e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
55e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Ends leak detection and reports any resource leaks.
56e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Returns true if any occurred.
57e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool ReportLeaked();
58e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
59e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
60e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Exception-safety
61e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
62e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
63e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Don't test for exception-safety
64e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void TurnOffExceptions();
65e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
66e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Set operator new to fail on the nth invocation
67e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void SetFailureCountdown( long n );
68e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
69e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Set operator new to never fail.
70e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void CancelFailureCountdown();
71e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
72e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Throws an exception if the count has been reached. Call this
73e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // before every operation that might fail in the real world.
74e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void maybe_fail(long);
75e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
76e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
77e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Managing verbose feedback.
78e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
79e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
80e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Call to begin a strong, weak, or const test. If verbose
81e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // reporting is enabled, prints the test category.
82e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void SetCurrentTestCategory( const char* str );
83e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
84e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Call to set the name of the container being tested.
85e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void SetCurrentContainer( const char* str );
86e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
87e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Sets the name of the current test.
88e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void SetCurrentTestName(const char* str);
89e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
90e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Turn verbose reporting on or off.
91e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void SetVerbose(bool val);
92e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
93e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottprivate:
94e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  enum { kNotInExceptionTest = -1 };
95e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
96e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void ClearAllocationSet();
97e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void EndLeakDetection();
98e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void PrintTestName( bool err=false );
99e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static long& Failure_threshold();
101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static long possible_failure_count;
102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const char* current_test;
103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const char* current_test_category;
104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const char* current_container;
105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool  nc_verbose;
106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool  never_fail;
107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool track_allocations;
108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool leak_detection_enabled;
109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottextern TestController gTestController;
112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//
114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// inline implementations
115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//
116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void simulate_possible_failure() {
118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  gTestController.maybe_fail(0);
119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void simulate_constructor() {
122e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  gTestController.maybe_fail(0);
123e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  ++object_count;
124e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
125e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
126e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void simulate_destructor() {
127e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  --object_count;
128e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
129e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
130e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::TrackAllocations(bool track) {
131e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  track_allocations = track;
132e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
133e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
134e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline bool TestController::TrackingEnabled() {
135e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return track_allocations;
136e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
137e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
138e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::SetFailureCountdown(long count) {
139e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  Failure_threshold() = count;
140e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  possible_failure_count = 0;
141e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
142e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
143e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::CancelFailureCountdown() {
144e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  Failure_threshold() = kNotInExceptionTest;
145e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
146e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
147e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::BeginLeakDetection() {
148e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  alloc_count = 0;
149e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  object_count = 0;
150e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  ClearAllocationSet();
151e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  leak_detection_enabled = true;
152e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
153e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
154e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline bool TestController::LeakDetectionEnabled() {
155e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return leak_detection_enabled;
156e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
157e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
158e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::EndLeakDetection() {
159e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  leak_detection_enabled = false;
160e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
161e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
162e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::SetCurrentTestCategory(const char* str) {
163e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  current_test_category = str;
164e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (nc_verbose)
165e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    PrintTestName();
166e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
167e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
168e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::SetCurrentContainer(const char* str) {
169e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  current_container=str;
170e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
171e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
172e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::SetCurrentTestName(const char* str) {
173e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  current_test = str;
174e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
175e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
176e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::SetVerbose(bool val) {
177e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  nc_verbose = val;
178e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
179e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
180e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void TestController::TurnOffExceptions() {
181e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  never_fail = true;
182e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
183e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
184e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif // INCLUDED_MOTU_nc_alloc
185