summaryrefslogtreecommitdiff
path: root/src/DllPlugInTester
diff options
context:
space:
mode:
authorBaptiste Lepilleur <gaiacrtn@free.fr>2002-04-20 20:54:36 +0000
committerBaptiste Lepilleur <gaiacrtn@free.fr>2002-04-20 20:54:36 +0000
commitf05089dffe81419786776b60bc2dc13d2a421a5c (patch)
tree8451a33146a505c999a28288fe4574e98f268238 /src/DllPlugInTester
parentc4995a9e022ed586cf4e3f166738dfe01bf51c16 (diff)
downloadcppunit-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.cpp316
-rw-r--r--src/DllPlugInTester/CommandLineParser.h121
-rw-r--r--src/DllPlugInTester/DllPlugInTester.cpp93
-rw-r--r--src/DllPlugInTester/DllPlugInTester.dsp12
-rw-r--r--src/DllPlugInTester/Makefile.am5
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 &copy );
+
+ /// Prevents the use of the copy operator.
+ void operator =( const CommandLineParser &copy );
+
+ 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