// Revision: 02 1.10.1.4 source/core/testfw/icmptest.hpp, testfw, ioc.v400, 980918 
#ifndef _ICMPTEST_
#define _ICMPTEST_
/**
 * Class IComparisonTestOf: Comparison protocol tests.
 *
 * IComparisonTestOf tests the constructor, copy constructor and assignment
 * operator of the target class.  This is a good way to leverage testing effort since
 * it allows you to test classes if those classes are expected to adhere to some
 * protocol.  This protocol test is implemented using a template class.
 *
 * IComparisonTestOf tests the following operations of its target class:
 *
 *<PRE>
 *     - copy constructed stack object
 *     - operator= assigned stack object
 *     - operator= self-assigned stack object
 *     - copy constructed heap object
 *     - operator= assigned heap object
 *     - operator= self-assigned heap object
 *     - Separately constructed unequal object of the unequal target is given
 *</PRE>
 *
 * @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

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

/**
 * IComparisonTestOf template class tests for adherence to specific protocols.
 *
 * IComparisonTestOf tests the constructor, copy constructor and assignment
 * operator of the target class.  This is a good way to leverage testing effort since
 * it allows you to test classes if those classes are expected to adhere to some
 * protocol.  This protocol test is implemented using a template class.
 *
 * Clients can either create a subclass or directly use this class.
 *
 * IComparisonTestOf tests the following operations of its target class:
 *
 *<PRE>
 *     - copy constructed stack object
 *     - operator= assigned stack object
 *     - operator= self-assigned stack object
 *     - copy constructed heap object
 *     - operator= assigned heap object
 *     - operator= self-assigned heap object
 *     - Separately constructed unequal object of the unequal target is given
 *</PRE>
 *
 * Target class must have operator== defined.
 *
 * The best was to use the IComparisonTest framework is to use the protocol
 * macros ComparisonTestMacro and ComparisonTestEqualOnlyMacro.
 *
 * These macros do everything you need in one line.  They write the entire
 * header and the entire implementation, including construtors and
 * destructors.  Just supply the names of the test class, target class,
 * comparator, the parameter list for the constructor that creates the target,
 * and (optionally) the unequal target.  The parameter list may be left blank
 * to indicate that the empty constructor is to be used to create the target or
 * unequal target.  If the test is only testing equal targets, then use the
 * "EqualOnly" macros.
 *
 *<PRE>
 * Usage:
 *
 *    Example:  ISample is the target class which we want to test.  ISample
 *              has a constructor, a copy constructor, an operator=, and
 *              an operator== defined:
 *
 *              comparisonTestMacro(ISampleTest, ISample, (1), (2));
 *
 *    Example:  Example for a class which creates the target object using the
 *              empty constructor:
 *
 *              comparisonTestMacro(ISampleTest, ISample, , (2));
 *
 *    Now you can run ISampleTest with the following command:
 *
 *              runTestImplementationMacro(ISampleTest);
 *
 *    If you do not want to test your target against an unequal object of the
 *    same type, do the following:
 *
 *              comparisonTestEqualOnlyMacro(ISampleTest, ISample, (1));
 *
 *    Or you can use this global function which creates and returns an instance
 *    of IComparisonTestOf:
 *
 *              createComparisonTest(new ISample(1), new ISample(2));
 *
 *    which can be used with the adoptTest method (see the ITestCollection class).
 *
 *</PRE>
 *
 */
template <class AType>
class IComparisonTestOf: public ITest
{
public:
//-------------------------------------------------------------------------
/** @group Constructors and Destructor */

/**
 * Constructor
 *
 * @param target        Target object to perform tests on
 * @param unequalTarget Unequal object to use for comparison
 */
IComparisonTestOf(AType* target, AType* unequalTarget = 0);


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


/**
 * Copy Constructor
 *
 * @param that    Object to copy
 */
IComparisonTestOf(const IComparisonTestOf<AType>& that);


/**
 * Standard assignment operator.
 *
 *@param that     Object used in assignment.
 */
IComparisonTestOf<AType>&  operator=(const IComparisonTestOf<AType>& that);


/**
 * ITest's copyInfo method.
 *
 * Within copyInfo, IComparisonTestOf 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.
 *
 * @override sometimes
 * @callup yes
 */
virtual void copyInfo();

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

//-------------------------------------------------------------------------
// Protected ITest Overrides
//-------------------------------------------------------------------------

/**
 * Tests the constructor, copy constructor, and assignment operator of the target class.
 *
 * Note:  Do NOT override the method.  Do NOT call this method directly.
 * The best was to use the IComparisonTest
 * framework is to use the protocol macros: ComparisonTestMacro and
 * ComparisonTestEqualOnlyMacro.
 */
virtual void test(); // Do not call this directly.  Called by ITest::run.

//-------------------------------------------------------------------------
//  Subclass should override these methods
//-------------------------------------------------------------------------

/**
 * Returns the name of the target class.  By default, it returns NULL.
 * You must override this method if you want the target class name
 * reported in the test output.
 *
 * @return      The name of the target class
 * @override    sometimes
 */
virtual const char* targetClassNameAsString() const;


//--------------------------------------------------------------------------
private:
virtual void        compare(AType* obj, AType* target, bool same);

AType*  fTarget;
AType*  fUnequalTarget;
};

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

//-----------------------------------------------------------------------------
// IComparisonTestOf Rice-A-Roni Macros
//
// These macros do everything you need in one line.  They write the entire
// header and the entire implementation, including construtors and
// destructors.  Just supply the names of the test class, target class,
// comparator, the parameter list for the constructor that creates the target,
// and (optionally) the unequal target.  The parameter list may be left blank
// to indicate that the empty constructor is to be used to create the target or
// unequal target.  If the test is only testing equal targets, then use the
// "EqualOnly" macros.
//-----------------------------------------------------------------------------

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


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


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

template<class AType>
IComparisonTestOf<AType>* createComparisonTest(AType* target, AType* unequalTarget);

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

#include <icmptest.c>

#endif  // _ICMPTEST_
