First public contribution.
1 /************************************************************************************************
4 * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
7 * Mark of the Unicorn, Inc.
9 * Permission to use, copy, modify, distribute and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appear in all copies and
12 * that both that copyright notice and this permission notice appear
13 * in supporting documentation. Mark of the Unicorn makes no
14 * representations about the suitability of this software for any
15 * purpose. It is provided "as is" without express or implied warranty.
17 ************************************************************************************************/
22 #if defined (EH_NEW_HEADERS)
32 #if defined (EH_NEW_IOSTREAMS)
35 # include <iostream.h>
39 long object_count = 0;
40 long TestController::possible_failure_count = 0;
41 const char* TestController::current_test = "<unknown>";
42 const char* TestController::current_test_category = "no category";
43 const char* TestController::current_container = 0;
44 bool TestController::nc_verbose = true;
45 bool TestController::never_fail = false;
46 bool TestController::track_allocations = false;
47 bool TestController::leak_detection_enabled = false;
49 TestController gTestController;
51 //************************************************************************************************
52 void TestController::maybe_fail(long) {
53 if (never_fail || Failure_threshold() == kNotInExceptionTest)
56 // throw if allocation would satisfy the threshold
57 if (possible_failure_count++ >= Failure_threshold()) {
58 // what about doing some standard new_handler() behavior here (to test it!) ???
60 // reset and simulate an out-of-memory failure
61 Failure_threshold() = kNotInExceptionTest;
62 #ifndef EH_NO_EXCEPTIONS
63 throw EH_STD::bad_alloc();
68 #if defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
69 # if defined (__SGI_STL)
70 # if defined (EH_NEW_HEADERS)
73 # include <hash_set.h>
75 # elif defined (__MSL__)
78 # error what do I include to get hash_set?
81 # if defined (EH_NEW_HEADERS)
88 #if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
89 typedef EH_STD::set<void*, EH_STD::less<void*> > allocation_set;
92 USING_CSTD_NAME(size_t)
95 size_t operator()(void* x) const { return (size_t)x; }
98 typedef EH_STD::hash_set<void*, ::hash_void, EH_STD::equal_to<void*> > allocation_set;
101 static allocation_set& alloc_set() {
102 static allocation_set s;
106 // Prevents infinite recursion during allocation
107 static bool using_alloc_set = false;
109 #if !defined (NO_FAST_ALLOCATOR)
111 // FastAllocator -- speeds up construction of TestClass objects when
112 // TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations
113 // when the suite is run with the -t option.
115 class FastAllocator {
117 //FastAllocator() : mFree(0), mUsed(0) {}
118 static void *Allocate(size_t s) {
121 if (s <= sizeof(Block)) {
126 else if (mBlocks != 0 && mUsed < kBlockCount) {
127 result = (void*)&mBlocks[mUsed++];
133 static bool Free(void* p) {
134 Block* b = (Block*)p;
135 if (mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount)
146 // Number of fast allocation blocks to create.
149 // You may need to adjust this number for your platform.
150 // A good choice will speed tests. A bad choice will still work.
157 double dummy; // fbp - force alignment
158 char dummy2[kMinBlockSize];
162 static Block* mBlocks;
167 FastAllocator::Block *FastAllocator::mBlocks =
168 (FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount );
169 FastAllocator::Block *FastAllocator::mFree;
170 size_t FastAllocator::mUsed;
173 static FastAllocator gFastAllocator;
176 inline char* AllocateBlock(size_t s) {
177 #if !defined (NO_FAST_ALLOCATOR)
178 char * const p = (char*)gFastAllocator.Allocate( s );
183 return (char*)EH_CSTD::malloc(s);
186 static void* OperatorNew( size_t s ) {
187 if (!using_alloc_set) {
188 simulate_possible_failure();
192 char *p = AllocateBlock(s);
194 if (gTestController.TrackingEnabled() &&
195 gTestController.LeakDetectionEnabled() &&
197 using_alloc_set = true;
198 bool inserted = alloc_set().insert(p).second;
200 using_alloc_set = false;
206 void* _STLP_CALL operator new(size_t s)
207 #ifdef EH_DELETE_HAS_THROW_SPEC
208 throw(EH_STD::bad_alloc)
210 { return OperatorNew( s ); }
212 #ifdef EH_USE_NOTHROW
213 void* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw() {
215 return OperatorNew( size );
223 #if defined (EH_VECTOR_OPERATOR_NEW)
224 void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc) {
225 return OperatorNew( size );
228 # ifdef EH_USE_NOTHROW
229 void* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw() {
231 return OperatorNew(size);
239 void _STLP_CALL operator delete[](void* ptr) throw()
240 { operator delete( ptr ); }
243 #if defined (EH_DELETE_HAS_THROW_SPEC)
244 void _STLP_CALL operator delete(void* s) throw()
246 void _STLP_CALL operator delete(void* s)
250 if ( !using_alloc_set ) {
253 if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() ) {
254 using_alloc_set = true;
255 allocation_set::iterator p = alloc_set().find( (char*)s );
256 EH_ASSERT( p != alloc_set().end() );
257 alloc_set().erase( p );
258 using_alloc_set = false;
261 # if ! defined (NO_FAST_ALLOCATOR)
262 if ( !gFastAllocator.Free( s ) )
270 /*===================================================================================
271 ClearAllocationSet (private helper)
273 EFFECTS: Empty the set of allocated blocks.
274 ====================================================================================*/
275 void TestController::ClearAllocationSet() {
276 if (!using_alloc_set) {
277 using_alloc_set = true;
279 using_alloc_set = false;
284 bool TestController::ReportLeaked() {
288 EH_ASSERT( alloc_count == static_cast<int>(alloc_set().size()) );
290 if (alloc_count != 0 || object_count != 0) {
291 EH_STD::cerr<<"\nEH TEST FAILURE !\n";
294 EH_STD::cerr << "ERROR : " << alloc_count << " outstanding allocations.\n";
296 EH_STD::cerr << "ERROR : " << object_count << " non-destroyed objects.\n";
297 alloc_count = object_count = 0;
305 /*===================================================================================
308 EFFECTS: Prints information about the current test. If err is false, ends with
309 an ellipsis, because the test is ongoing. If err is true an error is being
310 reported, and the output ends with an endl.
311 ====================================================================================*/
313 void TestController::PrintTestName(bool err) {
314 if (current_container)
315 EH_STD::cerr<<"["<<current_container<<"] :";
316 EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";
318 EH_STD::cerr<<EH_STD::endl;
320 EH_STD::cerr<<" ... ";
323 void TestController::ReportSuccess(int count) {
325 EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;
328 long& TestController::Failure_threshold() {
329 static long failure_threshold = kNotInExceptionTest;
330 return failure_threshold;
332 #if 0 // enable non inline functions
333 void TestController::TrackAllocations(bool track) {
334 track_allocations = track;
337 bool TestController::TrackingEnabled() {
338 return track_allocations;
341 void TestController::SetFailureCountdown(long count) {
342 Failure_threshold() = count;
343 possible_failure_count = 0;
346 void TestController::CancelFailureCountdown() {
347 Failure_threshold() = kNotInExceptionTest;
350 void TestController::BeginLeakDetection() {
353 ClearAllocationSet();
354 leak_detection_enabled = true;
357 bool TestController::LeakDetectionEnabled() {
358 return leak_detection_enabled;
361 void TestController::EndLeakDetection() {
362 leak_detection_enabled = false;
365 void TestController::SetCurrentTestCategory(const char* str) {
366 current_test_category = str;
371 void TestController::SetCurrentContainer(const char* str) {
372 current_container=str;
375 void TestController::SetCurrentTestName(const char* str) {
379 void TestController::SetVerbose(bool val) {
383 void TestController::TurnOffExceptions() {