diff options
| author | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-04-20 20:54:36 +0000 |
|---|---|---|
| committer | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-04-20 20:54:36 +0000 |
| commit | f05089dffe81419786776b60bc2dc13d2a421a5c (patch) | |
| tree | 8451a33146a505c999a28288fe4574e98f268238 /src/DllPlugInTester | |
| parent | c4995a9e022ed586cf4e3f166738dfe01bf51c16 (diff) | |
| download | cppunit-f05089dffe81419786776b60bc2dc13d2a421a5c.tar.gz | |
THANKS: updated
THANKS: updated
* src/cppunit/DynamicLibraryManager.cpp: bugfix: did not pass
library name to exception.
* include/cppunit/TestPath.h:
* src/cppunit/TestPath.cpp: changed into value object.
* src/cppunit/BeosDynamicLibraryManager.cpp: integrated patch from
Shibu Yoshiki for BeOS ('cuppa' project team).
* src/DllPlugInTester/CommandLineParser.h:
* src/DllPlugInTester/CommandLineParser.cpp: added. Command line
parsing.
* src/DllPlugInTester/DllPlugInTester.cpp: full command line support
with parameters for plug-ins.
* src/DllPlugInTester/makefile.am:
* examples/simple/makefile.am:
* examples/cppunittest/makefile.am: integrated Jeffrey Morgan patch,
Unix side should be working again.
* examples/ReadMe.txt: added. Brief description of each example.
* examples/cppunittest/CppUnitTestPlugIn.cpp:
* examples/cppunittest/CppUnitTestPlugIn.dsp: added. New project to
build CppUnit's test suite as a test plug-in.
* examples/cppunittest/CppUnitTestSuite.cpp: updated. Use new
helper macros to create the test suite hierarchy.
* examples/simple/simple_plugin.opt: added. Contains debug tab
settings.
* examples/ClockerPlugIn/ClockerListener.cpp:
* examples/ClockerPlugIn/ClockerListener.h:
* examples/ClockerPlugIn/Timer.cpp:
* examples/ClockerPlugIn/Timer.h:
* examples/ClockerPlugIn/WinNtTimer.cpp:
* examples/ClockerPlugIn/WinNtTimer.h:
* examples/ClockerPlugIn/ClockerPlugIn.cpp:
* examples/ClockerPlugIn/ClockerPlugIn.dsp: added. test listener
plug-in that times tests.
* examples/DumperPlugIn/DumperListener.cpp:
* examples/DumperPlugIn/DumperListener.h:
* examples/DumperPlugIn/DumperPlugIn.cpp:
* examples/DumperPlugIn/DumperPlugIn.dsp: added. test listener
plug-in that dump the test tree.
Diffstat (limited to 'src/DllPlugInTester')
| -rw-r--r-- | src/DllPlugInTester/CommandLineParser.cpp | 316 | ||||
| -rw-r--r-- | src/DllPlugInTester/CommandLineParser.h | 121 | ||||
| -rw-r--r-- | src/DllPlugInTester/DllPlugInTester.cpp | 93 | ||||
| -rw-r--r-- | src/DllPlugInTester/DllPlugInTester.dsp | 12 | ||||
| -rw-r--r-- | src/DllPlugInTester/Makefile.am | 5 |
5 files changed, 519 insertions, 28 deletions
diff --git a/src/DllPlugInTester/CommandLineParser.cpp b/src/DllPlugInTester/CommandLineParser.cpp new file mode 100644 index 0000000..2efff53 --- /dev/null +++ b/src/DllPlugInTester/CommandLineParser.cpp @@ -0,0 +1,316 @@ +#include "CommandLineParser.h" + + +CommandLineParser::CommandLineParser( int argc, + char *argv[] ) + : m_currentIndex( 0 ) + , m_useCompiler( false ) + , m_useXml( false ) + , m_briefProgress( false ) + , m_noProgress( false ) + , m_useText( false ) + , m_useCout( false ) +{ + for ( int index =1; index < argc; ++index ) + { + if ( index > 1 ) + m_line += " "; + m_line += argv[index]; + } +} + + +CommandLineParser::~CommandLineParser() +{ +} + + +void +CommandLineParser::parse() +{ + while ( hasNext() ) + { + getNextOption(); + if ( isOption( "c", "compiler" ) ) + m_useCompiler = true; + else if ( isOption( "x", "xml" ) ) + { + m_useXml = true; + m_xmlFileName = getOptionalParameter(); + } + else if ( isOption( "s", "xsl" ) ) + m_xsl = getParameter(); + else if ( isOption( "e", "encoding" ) ) + m_encoding = getParameter(); + else if ( isOption( "b", "brief-progress" ) ) + m_briefProgress = true; + else if ( isOption( "n", "no-progress" ) ) + m_noProgress = true; + else if ( isOption( "t", "text" ) ) + m_useText = true; + else if ( isOption( "o", "cout" ) ) + m_useCout = true; + else if ( !m_option.empty() ) + fail( "Unknown option" ); + else if ( hasNext() ) + readNonOptionCommands(); + } +} + + +bool +CommandLineParser::isOption( const std::string &shortName, + const std::string &longName ) +{ + return (m_option == "-" + shortName) || + (m_option == "--" + longName); +} + + +bool +CommandLineParser::hasNext() const +{ + return m_currentIndex < m_line.length(); +} + + +std::string +CommandLineParser::getParameter() +{ + if ( startsWith( "\"" ) ) + return getQuotedParameter(); + else + return getUnquotedParameter(); +} + + +std::string +CommandLineParser::getUnquotedParameter() +{ + std::string parameter; + + if ( !hasNext() ) + fail( "missing option parameter" ); + + while ( hasNext() && !isSpace() ) + parameter += next(); + return parameter; +} + + +std::string +CommandLineParser::getQuotedParameter() +{ + std::string parameter; + while ( !startsWith( "\"" ) ) + { + if ( !hasNext() ) + fail( "Unmatched \" in option parameter" ); + + if ( startsWith( "\\" ) ) + { + skipNext(); + if ( !hasNext() ) + fail( "Missing escaped character in option parameter" ); + } + + parameter += next(); + } + return parameter; +} + + +std::string +CommandLineParser::getOptionalParameter() +{ + if ( !hasNext() || startsWith( "-" ) || startsWith( ":" ) ) + return ""; + return getParameter(); +} + + +void +CommandLineParser::getNextOption() +{ + skipSpaces(); + m_option = ""; + if ( startsWith( "-" ) || startsWith( "--" ) ) + { + while ( hasNext() && !isSpace() ) + m_option += next(); + + skipSpaces(); + } +} + + +void +CommandLineParser::readNonOptionCommands() +{ + if ( startsWith( ":" ) ) + { + skipNext(); + m_testPath = getParameter(); + } + else + { + CommandLinePlugInInfo plugIn; + while ( hasNext() && !isSpace() && !startsWith( "=" ) ) + plugIn.m_fileName += next(); + + std::string parameters; + if ( startsWith( "=" ) ) + { + m_option = plugIn.m_fileName; + skipNext(); + parameters = getParameter(); + } + + plugIn.m_parameters.push_back( parameters ); + m_plugIns.push_back( plugIn ); + } +} + + +bool +CommandLineParser::startsWith( const std::string &expected ) const +{ + return m_line.substr( m_currentIndex, expected.length() ) == expected; +} + + +void +CommandLineParser::skipSpaces() +{ + while ( hasNext() && isSpace() ) + skipNext(); +} + + +bool +CommandLineParser::isSpace() const +{ + if ( !hasNext() ) + return true; + + return isSpace( m_line[m_currentIndex] ); +} + + +bool +CommandLineParser::isSpace( unsigned char c ) +{ + return c <= 32; +} + + +char +CommandLineParser::next() +{ + if ( !hasNext() ) + fail( "unexpected error while parsing option" ); + + return m_line[ m_currentIndex++ ]; +} + + +void +CommandLineParser::skipNext( int count ) +{ + m_currentIndex += count; + if ( m_currentIndex > m_line.length() ) + m_currentIndex = m_line.length(); +} + + +void +CommandLineParser::fail( std::string message ) +{ + throw CommandLineParserException( "Error while parsing option: " + m_option+ + "\n" + message ); +} + + + +bool +CommandLineParser::useCompilerOutputter() const +{ + return m_useCompiler; +} + + +bool +CommandLineParser::useXmlOutputter() const +{ + return m_useXml; +} + + +std::string +CommandLineParser::getXmlFileName() const +{ + return m_xmlFileName; +} + + +std::string +CommandLineParser::getXmlStyleSheet() const +{ + return m_xsl; +} + + +std::string +CommandLineParser::getEncoding() const +{ + return m_encoding; +} + + +bool +CommandLineParser::useBriefTestProgress() const +{ + return m_briefProgress; +} + + +bool +CommandLineParser::noTestProgress() const +{ + return m_noProgress; +} + + +bool +CommandLineParser::useTextOutputter() const +{ + return m_useText; +} + + +bool +CommandLineParser::useCoutStream() const +{ + return m_useCout; +} + + +int +CommandLineParser::getPlugInCount() const +{ + return m_plugIns.size(); +} + +CommandLinePlugInInfo +CommandLineParser::getPlugInAt( int index ) const +{ + return m_plugIns.at( index ); +} + + +std::string +CommandLineParser::getTestPath() const +{ + return m_testPath; +} + diff --git a/src/DllPlugInTester/CommandLineParser.h b/src/DllPlugInTester/CommandLineParser.h new file mode 100644 index 0000000..9fd5c5d --- /dev/null +++ b/src/DllPlugInTester/CommandLineParser.h @@ -0,0 +1,121 @@ +#ifndef CPPUNIT_HELPER_COMMANDLINEPARSER_H +#define CPPUNIT_HELPER_COMMANDLINEPARSER_H + +#include <cppunit/Portability.h> +#include <cppunit/plugin/Parameters.h> +#include <string> +#include <stdexcept> +#include <deque> + + +/*! Exception thrown on error while parsing command line. + */ +class CommandLineParserException : public std::runtime_error +{ +public: + CommandLineParserException( std::string message ) + : std::runtime_error( message ) + { + } +}; + + +struct CommandLinePlugInInfo +{ + std::string m_fileName; + CppUnit::Parameters m_parameters; +}; + + +/*! \brief Parses a command line. + +-c --compiler +-x --xml [filename] +-s --xsl stylesheet +-e --encoding encoding +-b --brief-progress +-n --no-progress +-t --text +-o --cout +filename[="options"] +:testpath + + */ +class CommandLineParser +{ +public: + /*! Constructs a CommandLineParser object. + */ + CommandLineParser( int argc, + char *argv[] ); + + /// Destructor. + virtual ~CommandLineParser(); + + /*! Parses the command line. + * \exception CommandLineParserException if an error occurs. + */ + void parse(); + + bool useCompilerOutputter() const; + bool useXmlOutputter() const; + std::string getXmlFileName() const; + std::string getXmlStyleSheet() const; + std::string getEncoding() const; + bool useBriefTestProgress() const; + bool noTestProgress() const; + bool useTextOutputter() const; + bool useCoutStream() const; + std::string getTestPath() const; + int getPlugInCount() const; + CommandLinePlugInInfo getPlugInAt( int index ) const; + +protected: + /// Prevents the use of the copy constructor. + CommandLineParser( const CommandLineParser © ); + + /// Prevents the use of the copy operator. + void operator =( const CommandLineParser © ); + + bool isOption( const std::string &shortName, + const std::string &longName ); + + bool hasNext() const; + bool startsWith( const std::string &expected ) const; + char next(); + void skipNext( int count =1 ); + bool isSpace() const; + + std::string getParameter(); + std::string getQuotedParameter(); + std::string getUnquotedParameter(); + std::string getOptionalParameter(); + void fail( std::string message ); + void getNextOption(); + void skipSpaces(); + static bool isSpace( unsigned char c ); + + void readNonOptionCommands(); + +protected: + std::string m_line; + int m_currentIndex; + std::string m_option; + + bool m_useCompiler; + bool m_useXml; + std::string m_xmlFileName; + std::string m_xsl; + std::string m_encoding; + bool m_briefProgress; + bool m_noProgress; + bool m_useText; + bool m_useCout; + std::string m_testPath; + + typedef std::deque<CommandLinePlugInInfo> PlugIns; + PlugIns m_plugIns; +}; + + +#endif // CPPUNIT_HELPER_COMMANDLINEPARSER_H diff --git a/src/DllPlugInTester/DllPlugInTester.cpp b/src/DllPlugInTester/DllPlugInTester.cpp index d52c552..df55e06 100644 --- a/src/DllPlugInTester/DllPlugInTester.cpp +++ b/src/DllPlugInTester/DllPlugInTester.cpp @@ -4,40 +4,58 @@ #include <cppunit/TestResult.h> #include <cppunit/TestResultCollector.h> #include <cppunit/TestRunner.h> +#include <cppunit/TextOutputter.h> #include <cppunit/TextTestProgressListener.h> +#include <cppunit/XmlOutputter.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/plugin/DynamicLibraryManagerException.h> #include <cppunit/plugin/Parameters.h> #include <cppunit/plugin/PlugInManager.h> #include <cppunit/plugin/TestPlugIn.h> #include <iostream> +#include <fstream> +#include "CommandLineParser.h" /*! Runs the specified tests located in the root suite. - * \param parameters List of string representing the command line arguments. + * \param parser Command line parser. * \return \c true if the run succeed, \c false if a test failed or if a test * path was not resolved. */ bool -runTests( CppUnit::Parameters parameters ) +runTests( const CommandLineParser &parser ) { CppUnit::TestResult controller; CppUnit::TestResultCollector result; controller.addListener( &result ); - CppUnit::TextTestProgressListener progress; -// CppUnit::BriefTestProgressListener progress; - controller.addListener( &progress ); - std::string testPath; + // Set up outputters + std::ostream *stream = &std::cerr; + if ( parser.useCoutStream() ) + stream = &std::cout; + + std::ostream *xmlStream = stream; + if ( !parser.getXmlFileName().empty() ) + xmlStream = new std::ofstream( parser.getXmlFileName().c_str() ); + + CppUnit::XmlOutputter xmlOutputter( &result, *xmlStream, parser.getEncoding() ); + CppUnit::TextOutputter textOutputter( &result, *stream ); + CppUnit::CompilerOutputter compilerOutputter( &result, *stream ); + + // Set up test listeners + CppUnit::BriefTestProgressListener briefListener; + CppUnit::TextTestProgressListener dotListener; + if ( parser.useBriefTestProgress() ) + controller.addListener( &briefListener ); + else if ( !parser.noTestProgress() ) + controller.addListener( &dotListener ); + + // Set up plug-ins CppUnit::PlugInManager plugInManager; - // Loads plug-ins & get test path. - for ( int index =0; index < parameters.size(); ++index ) + for ( int index =0; index < parser.getPlugInCount(); ++index ) { - std::string parameter = parameters[index]; - if ( parameter[0] == ':' ) - testPath = parameter.substr(1); - else - plugInManager.load( parameter ); + CommandLinePlugInInfo plugIn = parser.getPlugInAt( index ); + plugInManager.load( plugIn.m_fileName, plugIn.m_parameters ); } // Registers plug-in specific TestListener (global setUp/tearDown, custom TestListener...) @@ -48,26 +66,36 @@ runTests( CppUnit::Parameters parameters ) runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() ); // Runs the specified test + bool wasSuccessful = false; try { - runner.run( controller ); + runner.run( controller, parser.getTestPath() ); + wasSuccessful = result.wasSuccessful(); } catch ( std::invalid_argument & ) { - std::cerr << "Failed to resolve test path: " << testPath << std::endl; - return false; + std::cerr << "Failed to resolve test path: " + << parser.getTestPath() + << std::endl; } // Removes plug-in specific TestListener (not really needed but...) plugInManager.removeListener( &controller ); - std::cerr << std::endl; + // write using outputters + if ( parser.useCompilerOutputter() ) + compilerOutputter.write(); + + if ( parser.useTextOutputter() ) + textOutputter.write(); + + if ( parser.useXmlOutputter() ) + xmlOutputter.write(); - // Outputs test result - CppUnit::CompilerOutputter outputter( &result, std::cerr ); - outputter.write(); + if ( !parser.getXmlFileName().empty() ) + delete xmlStream; - return result.wasSuccessful(); + return wasSuccessful; } @@ -96,7 +124,8 @@ runTests( CppUnit::Parameters parameters ) * * If all test succeed and no error happen then the application exit with code 0. * If any error occurs (failed to load dll, failed to resolve test paths) or a - * test fail, the application exit with code 1. + * test fail, the application exit with code 1. If the application failed to + * parse the command line, it exits with code 2. */ int main( int argc, @@ -104,6 +133,7 @@ main( int argc, { const int successReturnCode = 0; const int failureReturnCode = 1; + const int badCommadLineReturnCode = 2; // check command line std::string applicationName( argv[0] ); @@ -113,16 +143,25 @@ main( int argc, << applicationName << " dll-filename1 [dll-filename2 ...] [:test-path]..." << std::endl; - return failureReturnCode; + return badCommadLineReturnCode; + } + + CommandLineParser parser( argc, argv ); + try + { + parser.parse(); + } + catch ( CommandLineParserException &e ) + { + std::cerr << "Error while parsing command line: " << e.what() + << std::endl; + return badCommadLineReturnCode; } bool wasSuccessful = false; try { - CppUnit::Parameters parameters; - for ( int index =1; index < argc; ++index ) - parameters.push_back( argv[index] ); - wasSuccessful = runTests( parameters ); + wasSuccessful = runTests( parser ); } catch ( CppUnit::DynamicLibraryManagerException &e ) { diff --git a/src/DllPlugInTester/DllPlugInTester.dsp b/src/DllPlugInTester/DllPlugInTester.dsp index 060a0c9..371681b 100644 --- a/src/DllPlugInTester/DllPlugInTester.dsp +++ b/src/DllPlugInTester/DllPlugInTester.dsp @@ -206,7 +206,19 @@ LINK32=link.exe # Name "DllPlugInTester - Win32 Debug" # Begin Source File +SOURCE=.\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=.\CommandLineParser.h +# End Source File +# Begin Source File + SOURCE=.\DllPlugInTester.cpp # End Source File +# Begin Source File + +SOURCE=.\Makefile.am +# End Source File # End Target # End Project diff --git a/src/DllPlugInTester/Makefile.am b/src/DllPlugInTester/Makefile.am index 1594e11..1359af5 100644 --- a/src/DllPlugInTester/Makefile.am +++ b/src/DllPlugInTester/Makefile.am @@ -4,8 +4,11 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include bin_PROGRAMS=DllPlugInTester -DllPlugInTester_SOURCES= DllPlugInTester.cpp +DllPlugInTester_SOURCES= DllPlugInTester.cpp \ + CommandLineParser.h \ + CommandLineParser.cpp DllPlugInTester_LDADD= \ $(top_builddir)/src/cppunit/libcppunit.la ld.so +DllPlugInTester_LDFLAGS = -ldl |
