Blame src/DllPlugInTester/DllPlugInTester.cpp

Packit 8c9aa0
#include <cppunit/BriefTestProgressListener.h>
Packit 8c9aa0
#include <cppunit/CompilerOutputter.h>
Packit 8c9aa0
#include <cppunit/TestPath.h>
Packit 8c9aa0
#include <cppunit/TestResult.h>
Packit 8c9aa0
#include <cppunit/TestResultCollector.h>
Packit 8c9aa0
#include <cppunit/TestRunner.h>
Packit 8c9aa0
#include <cppunit/TextOutputter.h>
Packit 8c9aa0
#include <cppunit/TextTestProgressListener.h>
Packit 8c9aa0
#include <cppunit/XmlOutputter.h>
Packit 8c9aa0
#include <cppunit/extensions/TestFactoryRegistry.h>
Packit 8c9aa0
#include <cppunit/plugin/DynamicLibraryManagerException.h>
Packit 8c9aa0
#include <cppunit/plugin/PlugInParameters.h>
Packit 8c9aa0
#include <cppunit/plugin/PlugInManager.h>
Packit 8c9aa0
#include <cppunit/plugin/TestPlugIn.h>
Packit 8c9aa0
#include <cppunit/portability/Stream.h>
Packit 8c9aa0
#include "CommandLineParser.h"
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
/* Notes:
Packit 8c9aa0
Packit 8c9aa0
  Memory allocated by test plug-in must be freed before unloading the test plug-in.
Packit 8c9aa0
  That is the reason why the XmlOutputter is explicitely destroyed.
Packit 8c9aa0
 */
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
/*! Runs the specified tests located in the root suite.
Packit 8c9aa0
 * \param parser Command line parser.
Packit 8c9aa0
 * \return \c true if the run succeed, \c false if a test failed or if a test
Packit 8c9aa0
 *         path was not resolved.
Packit 8c9aa0
 */
Packit 8c9aa0
bool 
Packit 8c9aa0
runTests( const CommandLineParser &parser )
Packit 8c9aa0
{
Packit 8c9aa0
  bool wasSuccessful = false;
Packit 8c9aa0
  CPPUNIT_NS::PlugInManager plugInManager;
Packit 8c9aa0
Packit 8c9aa0
  // The following scope is used to explicitely free all memory allocated before
Packit 8c9aa0
  // unload the test plug-ins (uppon plugInManager destruction).
Packit 8c9aa0
  {
Packit 8c9aa0
    CPPUNIT_NS::TestResult controller;
Packit 8c9aa0
    CPPUNIT_NS::TestResultCollector result;
Packit 8c9aa0
    controller.addListener( &result );        
Packit 8c9aa0
Packit 8c9aa0
    // Set up outputters
Packit 8c9aa0
    CPPUNIT_NS::OStream *stream = &CPPUNIT_NS::stdCErr();
Packit 8c9aa0
    if ( parser.useCoutStream() )
Packit 8c9aa0
      stream = &CPPUNIT_NS::stdCOut();
Packit 8c9aa0
Packit 8c9aa0
    CPPUNIT_NS::OStream *xmlStream = stream;
Packit 8c9aa0
    if ( !parser.getXmlFileName().empty() )
Packit 8c9aa0
      xmlStream = new CPPUNIT_NS::OFileStream( parser.getXmlFileName().c_str() );
Packit 8c9aa0
Packit 8c9aa0
    CPPUNIT_NS::XmlOutputter xmlOutputter( &result, *xmlStream, parser.getEncoding() );
Packit 8c9aa0
    xmlOutputter.setStyleSheet( parser.getXmlStyleSheet() );
Packit 8c9aa0
    CPPUNIT_NS::TextOutputter textOutputter( &result, *stream );
Packit 8c9aa0
    CPPUNIT_NS::CompilerOutputter compilerOutputter( &result, *stream );
Packit 8c9aa0
Packit 8c9aa0
    // Set up test listeners
Packit 8c9aa0
    CPPUNIT_NS::BriefTestProgressListener briefListener;
Packit 8c9aa0
    CPPUNIT_NS::TextTestProgressListener dotListener;
Packit 8c9aa0
    if ( parser.useBriefTestProgress() )
Packit 8c9aa0
      controller.addListener( &briefListener );
Packit 8c9aa0
    else if ( !parser.noTestProgress() )
Packit 8c9aa0
      controller.addListener( &dotListener );
Packit 8c9aa0
Packit 8c9aa0
    // Set up plug-ins
Packit 8c9aa0
    for ( int index =0; index < parser.getPlugInCount(); ++index )
Packit 8c9aa0
    {
Packit 8c9aa0
      CommandLinePlugInInfo plugIn = parser.getPlugInAt( index );
Packit 8c9aa0
      plugInManager.load( plugIn.m_fileName, plugIn.m_parameters );
Packit 8c9aa0
    }
Packit 8c9aa0
Packit 8c9aa0
    // Registers plug-in specific TestListener (global setUp/tearDown, custom TestListener...)
Packit 8c9aa0
    plugInManager.addListener( &controller );
Packit 8c9aa0
Packit 8c9aa0
    // Adds the default registry suite
Packit 8c9aa0
    CPPUNIT_NS::TestRunner runner;
Packit 8c9aa0
    runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
Packit 8c9aa0
Packit 8c9aa0
    // Runs the specified test
Packit 8c9aa0
    try
Packit 8c9aa0
    {
Packit 8c9aa0
      runner.run( controller, parser.getTestPath() );
Packit 8c9aa0
      wasSuccessful = result.wasSuccessful();
Packit 8c9aa0
    }
Packit 8c9aa0
    catch ( std::invalid_argument & )
Packit 8c9aa0
    {
Packit 8c9aa0
      CPPUNIT_NS::stdCOut()  <<  "Failed to resolve test path: "  
Packit 8c9aa0
                             <<  parser.getTestPath() 
Packit 8c9aa0
                             <<  "\n";
Packit 8c9aa0
    }
Packit 8c9aa0
Packit 8c9aa0
    // Removes plug-in specific TestListener (not really needed but...)
Packit 8c9aa0
    plugInManager.removeListener( &controller );
Packit 8c9aa0
Packit 8c9aa0
    // write using outputters
Packit 8c9aa0
    if ( parser.useCompilerOutputter() )
Packit 8c9aa0
      compilerOutputter.write();
Packit 8c9aa0
Packit 8c9aa0
    if ( parser.useTextOutputter() )
Packit 8c9aa0
      textOutputter.write();
Packit 8c9aa0
Packit 8c9aa0
    if ( parser.useXmlOutputter() )
Packit 8c9aa0
    {
Packit 8c9aa0
      plugInManager.addXmlOutputterHooks( &xmlOutputter );
Packit 8c9aa0
      xmlOutputter.write();
Packit 8c9aa0
      plugInManager.removeXmlOutputterHooks();
Packit 8c9aa0
    }
Packit 8c9aa0
Packit 8c9aa0
    if ( !parser.getXmlFileName().empty() )
Packit 8c9aa0
      delete xmlStream;
Packit 8c9aa0
  }
Packit 8c9aa0
Packit 8c9aa0
  return wasSuccessful;
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
void
Packit 8c9aa0
printShortUsage( const std::string &applicationName )
Packit 8c9aa0
{
Packit 8c9aa0
   CPPUNIT_NS::stdCOut()  << "Usage:\n"
Packit 8c9aa0
             << applicationName  <<  " [-c -b -n -t -o -w] [-x xml-filename]"
Packit 8c9aa0
             "[-s stylesheet] [-e encoding] plug-in[=parameters] [plug-in...] [:testPath]\n\n";
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
void
Packit 8c9aa0
printUsage( const std::string &applicationName )
Packit 8c9aa0
{
Packit 8c9aa0
  printShortUsage( applicationName );
Packit 8c9aa0
  CPPUNIT_NS::stdCOut()  <<
Packit 8c9aa0
"-c --compiler\n"
Packit 8c9aa0
"	Use CompilerOutputter\n"
Packit 8c9aa0
"-x --xml [filename]\n"
Packit 8c9aa0
"	Use XmlOutputter (if filename is omitted, then output to cout or\n"
Packit 8c9aa0
"	cerr.\n"
Packit 8c9aa0
"-s --xsl stylesheet\n"
Packit 8c9aa0
"	XML style sheet for XML Outputter\n"
Packit 8c9aa0
"-e --encoding encoding\n"
Packit 8c9aa0
"	XML file encoding (UTF8, shift_jis, ISO-8859-1...)\n"
Packit 8c9aa0
"-b --brief-progress\n"
Packit 8c9aa0
"	Use BriefTestProgressListener (default is TextTestProgressListener)\n"
Packit 8c9aa0
"-n --no-progress\n"
Packit 8c9aa0
"	Show no test progress (disable default TextTestProgressListener)\n"
Packit 8c9aa0
"-t --text\n"
Packit 8c9aa0
"	Use TextOutputter\n"
Packit 8c9aa0
"-o --cout\n"
Packit 8c9aa0
"	Ouputters output to cout instead of the default cerr.\n"
Packit 8c9aa0
"-w --wait\n"
Packit 8c9aa0
"	Wait for the user to press a return before exit.\n"
Packit 8c9aa0
"filename[=\"options\"]\n"
Packit 8c9aa0
"	Many filenames can be specified. They are the name of the \n"
Packit 8c9aa0
"	test plug-ins to load. Optional plug-ins parameters can be \n"
Packit 8c9aa0
"	specified after the filename by adding '='.\n"
Packit 8c9aa0
"[:testpath]\n"
Packit 8c9aa0
"	Optional. Only one test path can be specified. It must \n"
Packit 8c9aa0
"	be prefixed with ':'. See TestPath constructor for syntax.\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
"'parameters' (test plug-in or XML filename, test path...) may contains \n"
Packit 8c9aa0
"spaces if double quoted. Quote may be escaped with \".\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
"Some examples of command lines:\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
"DllPlugInTesterd_dll.exe -b -x tests.xml -c simple_plugind.dll CppUnitTestPlugInd.dll\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
" Will load 2 tests plug-ins (available in lib/), use the brief test\n"
Packit 8c9aa0
"progress, output the result in XML in file tests.xml and also\n"
Packit 8c9aa0
"output the result using the compiler outputter.\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
"DllPlugInTesterd_dll.exe ClockerPlugInd.dll=\"flat\" -n CppUnitTestPlugInd.dll\n"
Packit 8c9aa0
"\n"
Packit 8c9aa0
" Will load the 2 test plug-ins, and pass the parameter string \"flat\"\n"
Packit 8c9aa0
"to the Clocker plug-in, disable test progress.\n\n";
Packit 8c9aa0
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
/*! Main
Packit 8c9aa0
 * 
Packit 8c9aa0
 * Usage: 
Packit 8c9aa0
 *
Packit 8c9aa0
 * DllPlugInTester.exe dll-filename1 [dll-filename2 [dll-filename3 ...]] [:testpath]
Packit 8c9aa0
 *
Packit 8c9aa0
 * dll-filename must be the name of the DLL. If the DLL use some other DLL, they
Packit 8c9aa0
 * should be in the path or in the same directory as the DLL. The DLL must export
Packit 8c9aa0
 * a function named "GetTestPlugInInterface" with the signature
Packit 8c9aa0
 * GetTestPlugInInterfaceFunction. Both are defined in:
Packit 8c9aa0
 * \code
Packit 8c9aa0
 * #include <msvc6/testrunner/TestPlugInInterface.h>
Packit 8c9aa0
 * \endcode.
Packit 8c9aa0
 *
Packit 8c9aa0
 * If no test path is specified, they all the test of the suite returned by the DLL
Packit 8c9aa0
 * are run. If a test path is specified, then only the specified test is run. The test
Packit 8c9aa0
 * path must be prefixed by ':'.
Packit 8c9aa0
 *
Packit 8c9aa0
 * Test paths are resolved using Test::resolveTestPath() on the suite returned by
Packit 8c9aa0
 * TestFactoryRegistry::getRegistry().makeTest();
Packit 8c9aa0
 *
Packit 8c9aa0
 * If all test succeed and no error happen then the application exit with code 0.
Packit 8c9aa0
 * If any error occurs (failed to load dll, failed to resolve test paths) or a 
Packit 8c9aa0
 * test fail, the application exit with code 1. If the application failed to
Packit 8c9aa0
 * parse the command line, it exits with code 2.
Packit 8c9aa0
 */
Packit 8c9aa0
int 
Packit 8c9aa0
main( int argc, 
Packit 8c9aa0
      const char *argv[] )
Packit 8c9aa0
{
Packit 8c9aa0
  const int successReturnCode = 0;
Packit 8c9aa0
  const int failureReturnCode = 1;
Packit 8c9aa0
  const int badCommadLineReturnCode = 2;
Packit 8c9aa0
Packit 8c9aa0
  // check command line
Packit 8c9aa0
  std::string applicationName( argv[0] );
Packit 8c9aa0
  if ( argc < 2 )
Packit 8c9aa0
  {
Packit 8c9aa0
    printUsage( applicationName );
Packit 8c9aa0
    return badCommadLineReturnCode;
Packit 8c9aa0
  }
Packit 8c9aa0
Packit 8c9aa0
  CommandLineParser parser( argc, argv );
Packit 8c9aa0
  try
Packit 8c9aa0
  {
Packit 8c9aa0
    parser.parse();
Packit 8c9aa0
  }
Packit 8c9aa0
  catch ( CommandLineParserException &e )
Packit 8c9aa0
  {
Packit 8c9aa0
    CPPUNIT_NS::stdCOut()  <<  "Error while parsing command line: "  <<  e.what()  
Packit 8c9aa0
                           << "\n\n";
Packit 8c9aa0
    printShortUsage( applicationName );
Packit 8c9aa0
    return badCommadLineReturnCode;
Packit 8c9aa0
  }
Packit 8c9aa0
Packit 8c9aa0
  bool wasSuccessful = false;
Packit 8c9aa0
  try
Packit 8c9aa0
  {
Packit 8c9aa0
    wasSuccessful = runTests( parser );
Packit 8c9aa0
  }
Packit 8c9aa0
  catch ( CPPUNIT_NS::DynamicLibraryManagerException &e )
Packit 8c9aa0
  {
Packit 8c9aa0
    CPPUNIT_NS::stdCOut()  << "Failed to load test plug-in:\n"
Packit 8c9aa0
                           << e.what() << "\n";
Packit 8c9aa0
  }
Packit 8c9aa0
Packit 8c9aa0
#if !defined( CPPUNIT_NO_STREAM )
Packit 8c9aa0
  if ( parser.waitBeforeExit() )
Packit 8c9aa0
  {
Packit 8c9aa0
    CPPUNIT_NS::stdCOut() << "Please press <RETURN> to exit\n";
Packit 8c9aa0
    CPPUNIT_NS::stdCOut().flush();
Packit 8c9aa0
    std::cin.get();
Packit 8c9aa0
  }
Packit 8c9aa0
#endif
Packit 8c9aa0
Packit 8c9aa0
  return wasSuccessful ? successReturnCode : failureReturnCode;
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0