/**
 * Macros useful in running Test Framework tests.
 *
 * @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.
 *
 */
// Revision: 26 1.8.1.4 source/core/testfw/iruntest.hpp, testfw, ioc.v400, 980918 

#ifndef _RUNTEST_
#define _RUNTEST_


#include <stdio.h>
#include <string.h>

#include <itest.hpp>

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

/**
 * runTestImplementationMacro(testClass)
 *
 * Expands to define the entire main routine to create and run a single test.
 *
 * The following macro expands to define the entire main routine to create and
 * run a single test.  It takes the name of the test class for its parameter.
 * The test object is created and the run method is called for the test.
 * Options available are:
 *
 *<PRE>
 *
 *        -t[est] <class>            # Name of the ITest subclass to be "run"
 *
 *        -e[cho] h|g|n|d|D          # Sets detail of diagnostic output: headline, general, normal
 *                                 detail, Debug,; specifies the echo level for printing the
 *                                 diagnostic output from the tests.
 *
 *        -n <numberOfRuns>          # Run test this many times; default is 1.
 *
 *        -o[ptions] <testArgs...>   # Ignores any arguments following -o[ptions] and passes
 *                                 them to the test object.
 *
 *</PRE>
 *
 * If the -t option is not specified, the test class parameter is used for the
 * test class name.  The main routine returns 0 if test succeeded and 1
 * otherwise.
 *
 */
#define runTestImplementationMacro(testClass) \
        main(int argc, const char *const *argv) \
        { \
                runTestApplicationDeclarationsMacro(argc, argv) \
                parseRunTestApplicationArguments(argc, argv, className, \
                        numberOfRuns, testArgs, echoTier, parseError, false, logFileName); \
                if (!parseError && className == NULL) { \
                        className = #testClass; \
                } \
                runTestMacro(testClass) \
                endTestFrameworkMacro() \
                if (runTestResultMacro()) { \
                        return 0; \
                } else { \
                    return 1; \
                } \
        }


/**
 * beginTestFrameworkMacro(argc, argv)
 *
 * This macro expands the code to parse the command line arguments.
 *
 * Takes argc and argv for its parameters and expands the code
 * to parse the command line arguments.
 */
#define beginTestFrameworkMacro(argc, argv) \
        runTestApplicationDeclarationsMacro(argc, argv) \
        parseRunTestApplicationArguments(argc, argv, className, \
                        numberOfRuns, testArgs, echoTier, parseError, true, logFileName);


/**
 * runTestMacro(testClass)
 *
 * This macro expands the code to create and run the test.
 *
 * Takes the name of the test class for its paramenter and expands
 * the code to create and run the test. The test is only created and run if
 * the name of the test class is the same as the class name specified with the
 * -t option on the command line.
 */
#define runTestMacro(testClass) \
                if (!parseError && strcmp(#testClass , className) == 0) { \
                        testClass theTest; \
                        runTestInRunTestApplication(theTest, saveArgc, saveArgv, \
                        numberOfRuns, testArgs, echoTier, isTestRun, logFileName); \
                        testResult = theTest.success(); \
                }


/**
 * endTestFrameworkMacro()
 *
 * This macro expands the code to check if a test was run.
 *
 * This macro expands the code to check if a test was run
 * and print out an error if no test was run.  Takes no parameters.
 */
#define endTestFrameworkMacro()  \
                if (!parseError && !isTestRun) { \
                    printf("# %s - No test was run. Check spelling of test class name.\n", saveArgv[0]); \
                }


/**
 * runTestResultMacro() testResult
 *
 * Returns boolean indicating whether test succeeded.
 */
#define runTestResultMacro()  testResult



/**
 * runTestApplicationDeclarationsMacro(argc, argv)
 *
 * Declares all the external functions and variables used by an application created by the macros.
 *
 * Declares all the external functions and variables used by an application
 * created by the macros.  This should only be called by runTestImplementationMacro
 * and beginTestFrameworkMacro.  The functions parseRunTestApplicationArguments
 * and runTestInRunTestApplication should only be called by the macros.
 */
#define runTestApplicationDeclarationsMacro(argc, argv) \
        extern void parseRunTestApplicationArguments(int, const char *const *, \
                                const char*&, unsigned long&, int&, \
                                                ITieredTextBuffer::ETier&, bool&, bool, const char*&); \
        extern void runTestInRunTestApplication(ITest&, int, \
                        const char *const *, const unsigned long, \
            const int, const ITieredTextBuffer::ETier, bool&, const char*); \
        \
    const char *const *saveArgv = argv; \
    int saveArgc = argc; \
        const char *className; \
    ITieredTextBuffer::ETier echoTier; \
    unsigned long numberOfRuns; \
    int testArgs; \
    const char* logFileName = NULL; \
        bool testResult = false, isTestRun = false, parseError = false;

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

#endif // _RUNTEST_
