From a820665eea71a64b40e74ed24afeaf07a7a99db4 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 26 May 2006 14:36:57 +0000 Subject: Added the first of many unit tests. For now the unit tests are just built with everything else in the all target of the makefile, which is fine, but relies on CppTest, which can be found at http://cpptest.sf.net Also fixed some things I've been meaning to get to for a while in the xml system, including a few bugs that will make coping with malformed data not hang other programs, and do the error reporting in a nice way. --- src/exception.cpp | 13 ++++-- src/unit/hashtable.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ src/unit/xml.cpp | 43 +++++++++++++++++++ src/xmlexception.cpp | 27 ++++++++++++ src/xmlexception.h | 34 +++++++++++++++ src/xmlfilereader.cpp | 5 ++- src/xmlreader.cpp | 38 +++++------------ src/xmlreader.h | 14 ------- src/xmlstringreader.cpp | 3 +- 9 files changed, 237 insertions(+), 47 deletions(-) create mode 100644 src/unit/hashtable.cpp create mode 100644 src/unit/xml.cpp create mode 100644 src/xmlexception.cpp create mode 100644 src/xmlexception.h (limited to 'src') diff --git a/src/exception.cpp b/src/exception.cpp index 291a198..3cde134 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -2,7 +2,8 @@ #include Exception::Exception( const char *lpFormat, ... ) throw() : - nErrorCode( 0 ) + nErrorCode( 0 ), + sWhat( NULL ) { va_list ap; @@ -12,7 +13,8 @@ Exception::Exception( const char *lpFormat, ... ) throw() : } Exception::Exception( int nCode, const char *lpFormat, ... ) throw() : - nErrorCode( nCode ) + nErrorCode( nCode ), + sWhat( NULL ) { va_list ap; @@ -29,11 +31,16 @@ Exception::Exception( int nCode ) throw() : Exception::~Exception() throw() { - delete[] sWhat; + if( sWhat ) + { + delete[] sWhat; + sWhat = NULL; + } } void Exception::setWhat( const char *lpFormat, va_list &vargs ) { + if( sWhat ) delete[] sWhat; int nSize; nSize = vsnprintf( NULL, 0, lpFormat, vargs ); diff --git a/src/unit/hashtable.cpp b/src/unit/hashtable.cpp new file mode 100644 index 0000000..b2e1cf5 --- /dev/null +++ b/src/unit/hashtable.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "hashfunctionstring.h" +#include "hashfunctioncasestring.h" +#include "hashfunctionint.h" + +class HashFunctionSuite : public Test::Suite +{ +public: + HashFunctionSuite() + { + TEST_ADD( HashFunctionSuite::functionString ) + TEST_ADD( HashFunctionSuite::functionCaseString ) + TEST_ADD( HashFunctionSuite::functionInt ) + } + +private: + void functionStringWorker( HashFunction &hf, std::set &sCodes, char *str, int nLevel, int nMax ) + { + for( char let = 'A'; let <= 'z'; let += 3 ) + { + str[nLevel+1] = '\0'; + str[nLevel] = let; + unsigned long x = hf.hash( str ); + TEST_ASSERT( sCodes.find( x ) == sCodes.end() ); + TEST_ASSERT( hf.cmpIDs( str, str ) ); + sCodes.insert( x ); + + if( nLevel < nMax ) + functionStringWorker( hf, sCodes, str, nLevel+1, nMax ); + } + } + + void functionString() + { + HashFunctionString hf; + char str[10]; + + std::set sCodes; + + functionStringWorker( hf, sCodes, str, 0, 3 ); + } + + void functionCaseStringWorker( HashFunction &hf, std::map &sCodes, char *str, int nLevel, int nMax ) + { + for( char let = 'A'; let <= 'z'; let += 3 ) + { + str[nLevel+1] = '\0'; + str[nLevel] = let; + unsigned long x = hf.hash( str ); + std::map::iterator i = sCodes.find( x ); + if( i == sCodes.end() ) + { + sCodes[x] = strdup( str ); + } + else + { + TEST_ASSERT( strcasecmp( (*i).second, str ) == 0 ); + TEST_ASSERT( hf.cmpIDs( (*i).second, str ) == true ); + } + + if( nLevel < nMax ) + functionCaseStringWorker( hf, sCodes, str, nLevel+1, nMax ); + } + } + + void functionCaseString() + { + HashFunctionCaseString hf; + char str[10]; + + std::map sCodes; + + functionCaseStringWorker( hf, sCodes, str, 0, 3 ); + + std::map::iterator i; + for( i = sCodes.begin(); i != sCodes.end(); i++ ) + { + free( (*i).second ); + } + } + + void functionInt() + { + HashFunctionInt hf; + + for( long i = -100000; i <= 100000; i += 100 ) + { + TEST_ASSERT( ((long)hf.hash( (void *)i )) == i ); + TEST_ASSERT( ((long)hf.cmpIDs( (void *)i, (void *)i )) ); + } + } +}; + +int main( int argc, char *argv[] ) +{ + Test::TextOutput output( Test::TextOutput::Verbose ); + HashFunctionSuite ts; + return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/src/unit/xml.cpp b/src/unit/xml.cpp new file mode 100644 index 0000000..559b2f4 --- /dev/null +++ b/src/unit/xml.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +#include "xmlstringreader.h" +#include "xmlexception.h" + +class XmlCoreTestSuite : public Test::Suite +{ +public: + XmlCoreTestSuite() + { + TEST_ADD( XmlCoreTestSuite::badXml01 ) + TEST_ADD( XmlCoreTestSuite::badXml02 ) + TEST_ADD( XmlCoreTestSuite::badXml03 ) + } + +private: + void badXml01() + { + TEST_THROWS( XmlStringReader r(""), XmlException & ); + } + + void badXml02() + { + TEST_THROWS( XmlStringReader r(""), XmlException & ); + } + + void badXml03() + { + TEST_THROWS( XmlStringReader r(" + +XmlException::XmlException( const char *lpFormat, ... ) throw() : + Exception( 0 ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +XmlException::XmlException( int nCode, const char *lpFormat, ... ) throw() : + Exception( nCode ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +XmlException::XmlException( int nCode ) throw() : + Exception( nCode ) +{ +} diff --git a/src/xmlexception.h b/src/xmlexception.h new file mode 100644 index 0000000..9437ba3 --- /dev/null +++ b/src/xmlexception.h @@ -0,0 +1,34 @@ +#ifndef XML_EXCEPTION_H +#define XML_EXCEPTION_H + +#include +#include "exception.h" +#include + +/** + * A generalized Exception base class. This is nice for making general and + * flexible child classes that can create new error code classes. + */ +class XmlException : public Exception +{ +public: + /** + * Construct an exception with an error code of zero, but with a + * description. The use of this is not reccomended most of the time, it's + * generally best to include an error code with the exception so your + * program can handle the exception in a better way. + * @param sFormat The format of the text. See printf for more info. + */ + XmlException( const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @param sFormat + */ + XmlException( int nCode, const char *sFormat, ... ) throw(); + + XmlException( int nCode=0 ) throw(); +}; + +#endif diff --git a/src/xmlfilereader.cpp b/src/xmlfilereader.cpp index 216c08a..dd4bc82 100644 --- a/src/xmlfilereader.cpp +++ b/src/xmlfilereader.cpp @@ -1,4 +1,5 @@ #include "xmlfilereader.h" +#include "xmlexception.h" #include XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) @@ -8,7 +9,7 @@ XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) if( fh == NULL ) { - reportError("Couldn't open file."); + throw XmlException("Couldn't open file: %s", sFile ); //nError = 1; } else @@ -50,7 +51,7 @@ char XmlFileReader::getChar( int nIndex ) } else { - return '\0'; + throw XmlException("End of XML stream read."); } } diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp index bb24157..76c6258 100644 --- a/src/xmlreader.cpp +++ b/src/xmlreader.cpp @@ -1,10 +1,10 @@ #include "xmlreader.h" +#include "xmlexception.h" #include -XmlReader::XmlReader( bool bStrip ) +XmlReader::XmlReader( bool bStrip ) : + bStrip( bStrip ) { - nError = 0; - this->bStrip = bStrip; } XmlReader::~XmlReader() @@ -68,13 +68,12 @@ bool XmlReader::node() } else { - reportError("Close node in singleNode malformed!"); - return false; + throw XmlException("Close node in singleNode malformed!"); } } else { - reportError("Close node expected, but not found."); + throw XmlException("Close node expected, but not found."); return false; } @@ -108,8 +107,7 @@ bool XmlReader::startNode() } else { - reportError("Got a mismatched node close tag."); - return false; + throw XmlException("Got a mismatched node close tag."); } } else @@ -127,8 +125,7 @@ bool XmlReader::startNode() } else { - reportError("Got extra junk data instead of node close tag."); - return false; + throw XmlException("Got extra junk data instead of node close tag."); } } else @@ -146,8 +143,7 @@ bool XmlReader::startNode() } else { - reportError("Expected to find node opening char, '<'.\n"); - return false; + throw XmlException("Expected to find node opening char, '<'."); } return true; @@ -306,7 +302,7 @@ bool XmlReader::param() } else { - reportError("Expected an equals to seperate the params."); + throw XmlException("Expected an equals to seperate the params."); return false; } @@ -352,8 +348,7 @@ bool XmlReader::content() } else { - reportError("Mismatched close tag found."); - return false; + throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); } } else @@ -370,8 +365,7 @@ bool XmlReader::content() } else { - reportError("Malformed close tag."); - return false; + throw XmlException("Malformed close tag."); } } else @@ -400,13 +394,3 @@ bool XmlReader::content() } } -void XmlReader::reportError( const char *sError ) -{ - printf("XmlReader error: %s\n", sError ); -} - -int XmlReader::getError() -{ - return nError; -} - diff --git a/src/xmlreader.h b/src/xmlreader.h index a8a81f0..19e485a 100644 --- a/src/xmlreader.h +++ b/src/xmlreader.h @@ -37,19 +37,6 @@ public: */ ~XmlReader(); - /** - * Get the error code if an error happened. - *@returns The error code (I don't know what they are either) - */ - int getError(); - - /** - * Report an error to something, this is a really strange mechanism and - * should probably just be replaced with the multi-log system. - *@param sError The error to report. - */ - void reportError( const char *sError ); - /** * Build a document based on some kind of input. This is called * automatically by the constructor. @@ -127,7 +114,6 @@ private: FlexBuf fbParamName; /**< buffer for the current param's name. */ FlexBuf fbParamValue; /**< buffer for the current param's value. */ bool bStrip; /**< Are we stripping whitespace? */ - int nError; /**< Is there an error? */ }; #endif diff --git a/src/xmlstringreader.cpp b/src/xmlstringreader.cpp index aa7174f..82caacd 100644 --- a/src/xmlstringreader.cpp +++ b/src/xmlstringreader.cpp @@ -1,4 +1,5 @@ #include "xmlstringreader.h" +#include "xmlexception.h" #include XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) @@ -24,7 +25,7 @@ char XmlStringReader::getChar( int nAdd ) } else { - return '\0'; + throw XmlException("End of XML stream read."); } } -- cgit v1.2.3