// Revision: 07 1.13.1.5 source/core/testfw/istrmtst.hpp, testfw, ioc.v400, 001006 
#ifndef _ISTRMTST_
#define _ISTRMTST_
/**
 * Class IStreamTestOf: Tests the streaming of the target class.
 *
 * Tests the streaming of the target object using operator<<= and operator>>=
 *
 * This test is a good way to leverage testing effort since it allows one to test
 * classes if those classes are expected to adhere to some protocol.  This protocol
 * test is implemented using a template class.  Target classes must have operator=
 * defined to be tested by IStreamTestOf.  One macro and one global function are
 * provided to help easy use of this class.
 *
 * @package Test Framework
 * @category Testing
 *
 * @author Alan Liu
 * @task Initial Test Framework
 * @author Esther Tong
 * @task TestFrameworkLite
 * @author David McCusker, Christoper Miller, Carol Widra, and Kwansook Nam
 * @task Many of the other Contributors to TestFramework
 *
 * @copyright
 *      IBM Open Class Library
 *      (C) Copyright International Business Machines Corporation 1997
 *      Licensed Material - Program-Property of IBM - All Rights Reserved.
 *
 */

#include <itest.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class IDataStream;

#pragma enum(4)
#pragma pack(push,4)

//--------------------------------------------------------------------------
/**
 * Class IStreamTestOf: Tests the streaming of the target class.
 *
 * Tests the streaming of the target object using operator<<= and operator>>=
 *
 * IStreamTestOf is a subclass of ITest which tests the streaming of the target.
 * Clients should create a subclass of IStreamTestOf or use streamTestMacro
 * (see below).
 *
 * This test is a good way to leverage testing effort since it allows one to test
 * classes if those classes are expected to adhere to some protocol.  This protocol
 * test is implemented using a template class.  Target classes MUST have operator=
 * defined to be tested by IStreamTestOf.  One macro and one global function are
 * provided for easy use of this class.
 *
 * The macro streamTestMacro does everything you need in one line.  It writes the
 * entire header and the entire implementation.  Just supply the name of the test
 * class, target class and the parameter list for the constructor that creates the target.
 * The parameter list may be left blank to indicate that the empty constructor is
 * to be used to create the target.
 *
 *<PRE>
 *
 * Usage:
 *
 *   Example:  ISample is the target class that we want to test streaming.
 *             ISample has operator<<=, operator>>=, and operator== defined.
 *
 *       streamTestMacro(ISampleTest,ISample,(1));
 *
 *   Example of a class which creates the target object using the empty constructor:
 *
 *       streamTestMacro(ISampleTest,ISample,);
 *
 *   Now you can run ISampleTest with runTestImplementationMacro:
 *
 *       runTestImplementationMacro(ISampleTest);
 *
 *   Or you can use this global function which creates and returns an instance
 *   of IStreamTestOf:
 *
 *              createStreamTest(new ISample(2));
 *
 *    which can be used with the adoptTest method (see the ITestCollection class).
 *
 *</PRE>
 *
 */
template<class AType>
class IStreamTestOf : public ITest {
public:
//------------------------------------------------------------------------
// Canonical methods
/** @group Construction, Destruction, and Assignment */


/**
 * Constructor
 *
 * @param target
 */
IStreamTestOf(AType* target);


/**
 * Copy Constructor
 *
 * @param
 */
IStreamTestOf(const IStreamTestOf<AType>&);


/**
 * Assignment operator
 */
IStreamTestOf<AType>& operator=(const IStreamTestOf<AType>&);


/**
 * Destructor
 */
virtual ~IStreamTestOf();


//------------------------------------------------------------------------
/** @group Override Methods */


/**
 * ITest's copyInfo method.
 *
 * Within copyInfo, ISteamTestOf calls the inherited implementation
 * (e.g., IDerived::copyInfo should call IBase::copyInfo).  Then
 * copyInfo should add key/value pairs to infoMap by calling the
 * addInfo() method.
 */
virtual void  copyInfo();

//-------------------------------------------------------------------------
protected:

/**
 * Streams the target object out to and in from the memory stream
 * and compares the streamed-in object with the original.
 *
 * test also verifies that the stream position is consistent after stream-out and
 * stream-in.
 *
 * Note: Do NOT override this method.  The best way to use the IStreamTestOf
 * framework is to use the protocol StreamTestMacro.
 *
 * ITest overrides; these methods are called by the framework ITest::run()
 */
virtual void test();


/**
 * Client may override this method if the target class name is to be
 * reported in the test output.
 *
 * @return char*    The name of the target class.  Be default, it returns NULL.
 */
virtual const char* targetClassNameAsString() const;


//-------------------------------------------------------------------------
private:
    AType*       fTarget;
    IDataStream* fStream;
};

#pragma pack(pop)
#pragma enum(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

/**
 *--------------------------------------------------------------------------
 * IStreamTestOf Rice-A-Roni macro
 *
 *  This macro does everything you need in one line.  It writes the entire header and
 *  the entire implementation.  Just supply the name of the test class, target class
 *  and the parameter list for the constructor that creates the target.
 *  The parameter list may be left blank to indicate that the empty constructor is
 *  to be used to create the target.
 *--------------------------------------------------------------------------
 */

#define streamTestMacro(testClass, targetClass, parameterList) \
                \
                class testClass : public IStreamTestOf<targetClass> { \
                public: \
                                testClass(); \
                                virtual ~testClass(); \
                                virtual const char* targetClassNameAsString() const; \
                }; \
        \
                testClass::testClass() \
                :IStreamTestOf<targetClass>(new targetClass parameterList) {} \
                testClass::~testClass() {} \
                const char* testClass::targetClassNameAsString() const { return #targetClass; }


/**
 *
 * Global function which creates an instance of IStreamTestOf<AType>
 */

template<class AType>
IStreamTestOf<AType> *createStreamTest(AType* target);

#if ! defined(__TEMPINC__)
#include <istrmtst.c>
#endif

#endif // _ISTRMTST_
