Listing 1: A class for counting tests passed, tests failed, number of exception points, and which exception point to fail on

#ifndef COUNTER_H
#define COUNTER_H

#include <exception>
#include <iostream>
#include <typeinfo>
#include <strstream>

class TestException : public std::exception
{
    virtual const char* what() const throw() {
        return "TestException";
    }
};

class Counter {
private:
    // This variable indicates the number of the exception point
    // that we are up to executing in the code.
    static int sExceptionPointCount;
    // The number of the exception point which should throw.
    static int sThrowCount;
    static bool sDontThrow;

    // This counts the number of times new has successfully returned
    // a non-null result, minus the number of times a non-null ptr
    // has been passed to delete.
    static int sNewCount;

    static int sPassCount;
    static int sFailCount;

    static std::ostream* mOs;

public:
    // This function should be called wherever an
    // exception could be generated in the real code.
    static void CouldThrow() throw ( TestException );

    // Functions for the test harness to use.
    static void SetThrowCount( int inCount ) throw();
     // Prevents throwing until next call to SetThrowCount()
    static void DontThrow() throw();
    static bool HasThrown() throw();

    // Return the number of currently allocated blocks.
    static int GetAllocationCount() throw();

    // Managing tests.
    static void Pass( const char* testName ) throw();
    static void Fail( const char* testName ) throw();
    static void Test( bool result, const char* testName ) throw();
    static void PrintTestSummary();

    // Managing where the output is sent. The default is cout.
    static void SetOutputStream( std::ostream* os );
    static std::ostream& GetOut(){ return *mOs; }

    // For use by our definitions of new and delete.
    static void* MemAllocated( void* rawMem );
    static void DoDeallocate( void* userMem );
};

/************************************************
    TestDriver
    This method does the test. It will cause all 
    exception paths to be executed. 
    
    For example usage, see below.
*************************************************/

template<class TestFunction>
void TestDriver()
{
    int i = 0;
    int start_count, leaks;
    bool thrown;
    Counter::GetOut() << "Doing test " 
                      << typeid( TestFunction ).name() 
                      << std::endl;

    do {
        start_count = Counter::GetAllocationCount();

        Counter::SetThrowCount( ++i );
        //Counter::GetOut() << std::endl 
        //    << "        Exception count: " << i << std::endl;
        try {
            TestFunction::DoTest();
        }
        catch( const TestException& e ) {
        }
        catch( const std::bad_alloc& e ) {
        }
        catch( ... ) {
        }

        thrown = Counter::HasThrown();
        // Should set not to throw exceptions for the stuff below.
        Counter::DontThrow();
        
        // Check for resource leaks here. 
        // ...

    } while( thrown );
    // Loop terminates when we make it all the way
    // through a test without triggering the exception counter.
    Counter::GetOut() << "            " << i 
                      << " execution paths were tested." 
                      << std::endl;
}

/*******************
To use this TestDriver function, supply a class like this:

class TestPath1
{
public:
    static void DoTest() {
        // Test some aspect of your class or function here,
        // by calling it with known inputs and checking the results.
        // For example:
        
        // This tests the conversion constructor of a 
        // String class (assuming that operator== works OK).
        String s1(""), s2("Hello");
        Counter::Test( s1 == "", "Correct string value" );    
        Counter::Test( s2 == "Hello", "Correct string value" );    
    }
};

Then, supply a main like this

int main()
{
    TestDriver<TestPath1>();
    TestDriver<TestPath2>();
    // and so on...
    
    Counter::PrintTestSummary();
    return 0;
}

********************/

#endif // COUNTER_H
— End of Listing —