summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2006-05-26 14:36:57 +0000
committerMike Buland <eichlan@xagasoft.com>2006-05-26 14:36:57 +0000
commita820665eea71a64b40e74ed24afeaf07a7a99db4 (patch)
tree515af31ac2ed78aa92ce7e90e478bdb452e6e438
parentbd5bb1ca60a6a97b110cbf221b3625e6e6200141 (diff)
downloadlibbu++-a820665eea71a64b40e74ed24afeaf07a7a99db4.tar.gz
libbu++-a820665eea71a64b40e74ed24afeaf07a7a99db4.tar.bz2
libbu++-a820665eea71a64b40e74ed24afeaf07a7a99db4.tar.xz
libbu++-a820665eea71a64b40e74ed24afeaf07a7a99db4.zip
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.
-rw-r--r--Makefile19
-rw-r--r--src/exception.cpp13
-rw-r--r--src/unit/hashtable.cpp107
-rw-r--r--src/unit/xml.cpp43
-rw-r--r--src/xmlexception.cpp27
-rw-r--r--src/xmlexception.h34
-rw-r--r--src/xmlfilereader.cpp5
-rw-r--r--src/xmlreader.cpp38
-rw-r--r--src/xmlreader.h14
-rw-r--r--src/xmlstringreader.cpp3
10 files changed, 251 insertions, 52 deletions
diff --git a/Makefile b/Makefile
index 1add784..d034ffc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,7 @@
1OBJS:=$(patsubst %.cpp,%.o,$(wildcard src/*.cpp)) 1OBJS:=$(patsubst %.cpp,%.o,$(wildcard src/*.cpp))
2USRCS:=$(wildcard src/unit/*.cpp)
3UOBJS:=$(patsubst %.cpp,%.o,$(USRCS))
4UNIT:=$(foreach ut,$(patsubst %.cpp,%,$(wildcard src/unit/*.cpp)),unit/$(notdir $(ut)))
2TOBJS:=$(patsubst %.cpp,%.o,$(wildcard src/test/*.cpp)) 5TOBJS:=$(patsubst %.cpp,%.o,$(wildcard src/test/*.cpp))
3TDIRS:=$(filter-out %.o %.cpp %.h %.d,$(wildcard src/test/*)) 6TDIRS:=$(filter-out %.o %.cpp %.h %.d,$(wildcard src/test/*))
4TESTS:=$(patsubst src/test/%.o,tests/%,$(TOBJS)) $(patsubst src/test/%,tests/%,$(TDIRS)) 7TESTS:=$(patsubst src/test/%.o,tests/%,$(TOBJS)) $(patsubst src/test/%,tests/%,$(TDIRS))
@@ -12,17 +15,17 @@ TXTDEP:="\ dep:\ \ \ "
12TXTARC:="\ \ ar:\ \ \ " 15TXTARC:="\ \ ar:\ \ \ "
13 16
14.PHONY: all clean dist tests depclean cleanapi 17.PHONY: all clean dist tests depclean cleanapi
15.SILENT: clean $(OBJS) $(TOBJS) $(ATOBJS) $(TESTS) $(patsubst %.o,%.d,$(OBJS) $(TOBJS) $(ATOBJS) $(TESTS)) $(LIB) 18.SILENT: clean $(OBJS) $(TOBJS) $(ATOBJS) $(UNIT) $(UOBJS) $(TESTS) $(patsubst %.o,%.d,$(OBJS) $(TOBJS) $(ATOBJS) $(TESTS)) $(LIB)
16 19
17all: libbu++.a tests 20all: libbu++.a tests unit
18 21
19depclean: 22depclean:
20 -rm $(patsubst %.o,%.d,$(OBJS) $(ATOBJS)) 23 -rm $(patsubst %.o,%.d,$(OBJS) $(ATOBJS) $(UOBJS))
21 24
22-include $(patsubst %.o,%.d,$(OBJS) $(ATOBJS)) 25-include $(patsubst %.o,%.d,$(OBJS) $(ATOBJS) $(UOBJS))
23 26
24clean: 27clean:
25 -rm $(OBJS) $(ATOBJS) $(TESTS) $(LIB) 28 -rm $(OBJS) $(ATOBJS) $(UOBJS) $(TESTS) $(LIB)
26 29
27# This bit I cribbed from the docs, seems to work great though! 30# This bit I cribbed from the docs, seems to work great though!
28%.d: %.cpp 31%.d: %.cpp
@@ -41,8 +44,14 @@ $(TESTS): $(ATOBJS) $(LIB)
41 echo "$(TXTLNK)$@" 44 echo "$(TXTLNK)$@"
42 g++ $(LDFLAGS) -ggdb $(filter %$(patsubst tests/%,%,$@).o, $(TOBJS) ) $(patsubst %.cpp,%.o,$(wildcard $(filter %$(patsubst tests/%,%,$@), $(TDIRS))/*.cpp)) -L. -lbu++ -o $@ 45 g++ $(LDFLAGS) -ggdb $(filter %$(patsubst tests/%,%,$@).o, $(TOBJS) ) $(patsubst %.cpp,%.o,$(wildcard $(filter %$(patsubst tests/%,%,$@), $(TDIRS))/*.cpp)) -L. -lbu++ -o $@
43 46
47$(UNIT): $(USRCS) $(LIB)
48 echo "$(TXTLNK)$@"
49 g++ $(LDFLAGS) -ggdb -Isrc -Isrc/unit src/$@.cpp -L. -lbu++ -lcpptest -o $@
50
44tests: $(TESTS) 51tests: $(TESTS)
45 52
53unit: $(UNIT)
54
46dist: clean depclean 55dist: clean depclean
47 mkdir libbu++-$(DATE) 56 mkdir libbu++-$(DATE)
48 cp -a --target-directory=libbu++-$(DATE) Makefile src 57 cp -a --target-directory=libbu++-$(DATE) Makefile 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 @@
2#include <stdarg.h> 2#include <stdarg.h>
3 3
4Exception::Exception( const char *lpFormat, ... ) throw() : 4Exception::Exception( const char *lpFormat, ... ) throw() :
5 nErrorCode( 0 ) 5 nErrorCode( 0 ),
6 sWhat( NULL )
6{ 7{
7 va_list ap; 8 va_list ap;
8 9
@@ -12,7 +13,8 @@ Exception::Exception( const char *lpFormat, ... ) throw() :
12} 13}
13 14
14Exception::Exception( int nCode, const char *lpFormat, ... ) throw() : 15Exception::Exception( int nCode, const char *lpFormat, ... ) throw() :
15 nErrorCode( nCode ) 16 nErrorCode( nCode ),
17 sWhat( NULL )
16{ 18{
17 va_list ap; 19 va_list ap;
18 20
@@ -29,11 +31,16 @@ Exception::Exception( int nCode ) throw() :
29 31
30Exception::~Exception() throw() 32Exception::~Exception() throw()
31{ 33{
32 delete[] sWhat; 34 if( sWhat )
35 {
36 delete[] sWhat;
37 sWhat = NULL;
38 }
33} 39}
34 40
35void Exception::setWhat( const char *lpFormat, va_list &vargs ) 41void Exception::setWhat( const char *lpFormat, va_list &vargs )
36{ 42{
43 if( sWhat ) delete[] sWhat;
37 int nSize; 44 int nSize;
38 45
39 nSize = vsnprintf( NULL, 0, lpFormat, vargs ); 46 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 @@
1#include <cstdlib>
2#include <cstring>
3#include <iostream>
4#include <cpptest.h>
5#include <string.h>
6#include <set>
7#include <map>
8
9#include "hashfunctionstring.h"
10#include "hashfunctioncasestring.h"
11#include "hashfunctionint.h"
12
13class HashFunctionSuite : public Test::Suite
14{
15public:
16 HashFunctionSuite()
17 {
18 TEST_ADD( HashFunctionSuite::functionString )
19 TEST_ADD( HashFunctionSuite::functionCaseString )
20 TEST_ADD( HashFunctionSuite::functionInt )
21 }
22
23private:
24 void functionStringWorker( HashFunction &hf, std::set<unsigned long> &sCodes, char *str, int nLevel, int nMax )
25 {
26 for( char let = 'A'; let <= 'z'; let += 3 )
27 {
28 str[nLevel+1] = '\0';
29 str[nLevel] = let;
30 unsigned long x = hf.hash( str );
31 TEST_ASSERT( sCodes.find( x ) == sCodes.end() );
32 TEST_ASSERT( hf.cmpIDs( str, str ) );
33 sCodes.insert( x );
34
35 if( nLevel < nMax )
36 functionStringWorker( hf, sCodes, str, nLevel+1, nMax );
37 }
38 }
39
40 void functionString()
41 {
42 HashFunctionString hf;
43 char str[10];
44
45 std::set<unsigned long> sCodes;
46
47 functionStringWorker( hf, sCodes, str, 0, 3 );
48 }
49
50 void functionCaseStringWorker( HashFunction &hf, std::map<unsigned long, char *> &sCodes, char *str, int nLevel, int nMax )
51 {
52 for( char let = 'A'; let <= 'z'; let += 3 )
53 {
54 str[nLevel+1] = '\0';
55 str[nLevel] = let;
56 unsigned long x = hf.hash( str );
57 std::map<unsigned long, char *>::iterator i = sCodes.find( x );
58 if( i == sCodes.end() )
59 {
60 sCodes[x] = strdup( str );
61 }
62 else
63 {
64 TEST_ASSERT( strcasecmp( (*i).second, str ) == 0 );
65 TEST_ASSERT( hf.cmpIDs( (*i).second, str ) == true );
66 }
67
68 if( nLevel < nMax )
69 functionCaseStringWorker( hf, sCodes, str, nLevel+1, nMax );
70 }
71 }
72
73 void functionCaseString()
74 {
75 HashFunctionCaseString hf;
76 char str[10];
77
78 std::map<unsigned long, char *> sCodes;
79
80 functionCaseStringWorker( hf, sCodes, str, 0, 3 );
81
82 std::map<unsigned long, char *>::iterator i;
83 for( i = sCodes.begin(); i != sCodes.end(); i++ )
84 {
85 free( (*i).second );
86 }
87 }
88
89 void functionInt()
90 {
91 HashFunctionInt hf;
92
93 for( long i = -100000; i <= 100000; i += 100 )
94 {
95 TEST_ASSERT( ((long)hf.hash( (void *)i )) == i );
96 TEST_ASSERT( ((long)hf.cmpIDs( (void *)i, (void *)i )) );
97 }
98 }
99};
100
101int main( int argc, char *argv[] )
102{
103 Test::TextOutput output( Test::TextOutput::Verbose );
104 HashFunctionSuite ts;
105 return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE;
106}
107
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 @@
1#include <cstdlib>
2#include <cstring>
3#include <iostream>
4#include <cpptest.h>
5#include <string.h>
6
7#include "xmlstringreader.h"
8#include "xmlexception.h"
9
10class XmlCoreTestSuite : public Test::Suite
11{
12public:
13 XmlCoreTestSuite()
14 {
15 TEST_ADD( XmlCoreTestSuite::badXml01 )
16 TEST_ADD( XmlCoreTestSuite::badXml02 )
17 TEST_ADD( XmlCoreTestSuite::badXml03 )
18 }
19
20private:
21 void badXml01()
22 {
23 TEST_THROWS( XmlStringReader r("<hello></bye>"), XmlException & );
24 }
25
26 void badXml02()
27 {
28 TEST_THROWS( XmlStringReader r("<hello>"), XmlException & );
29 }
30
31 void badXml03()
32 {
33 TEST_THROWS( XmlStringReader r("<hello param=\"stuff?"), XmlException & );
34 }
35};
36
37int main( int argc, char *argv[] )
38{
39 Test::TextOutput output( Test::TextOutput::Verbose );
40 XmlCoreTestSuite ts;
41 return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE;
42}
43
diff --git a/src/xmlexception.cpp b/src/xmlexception.cpp
new file mode 100644
index 0000000..7012ee6
--- /dev/null
+++ b/src/xmlexception.cpp
@@ -0,0 +1,27 @@
1#include "xmlexception.h"
2#include <stdarg.h>
3
4XmlException::XmlException( const char *lpFormat, ... ) throw() :
5 Exception( 0 )
6{
7 va_list ap;
8
9 va_start(ap, lpFormat);
10 setWhat( lpFormat, ap );
11 va_end(ap);
12}
13
14XmlException::XmlException( int nCode, const char *lpFormat, ... ) throw() :
15 Exception( nCode )
16{
17 va_list ap;
18
19 va_start(ap, lpFormat);
20 setWhat( lpFormat, ap );
21 va_end(ap);
22}
23
24XmlException::XmlException( int nCode ) throw() :
25 Exception( nCode )
26{
27}
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 @@
1#ifndef XML_EXCEPTION_H
2#define XML_EXCEPTION_H
3
4#include <string>
5#include "exception.h"
6#include <stdarg.h>
7
8/**
9 * A generalized Exception base class. This is nice for making general and
10 * flexible child classes that can create new error code classes.
11 */
12class XmlException : public Exception
13{
14public:
15 /**
16 * Construct an exception with an error code of zero, but with a
17 * description. The use of this is not reccomended most of the time, it's
18 * generally best to include an error code with the exception so your
19 * program can handle the exception in a better way.
20 * @param sFormat The format of the text. See printf for more info.
21 */
22 XmlException( const char *sFormat, ... ) throw();
23
24 /**
25 *
26 * @param nCode
27 * @param sFormat
28 */
29 XmlException( int nCode, const char *sFormat, ... ) throw();
30
31 XmlException( int nCode=0 ) throw();
32};
33
34#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 @@
1#include "xmlfilereader.h" 1#include "xmlfilereader.h"
2#include "xmlexception.h"
2#include <string.h> 3#include <string.h>
3 4
4XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) 5XmlFileReader::XmlFileReader( const char *sFile, bool bStrip )
@@ -8,7 +9,7 @@ XmlFileReader::XmlFileReader( const char *sFile, bool bStrip )
8 9
9 if( fh == NULL ) 10 if( fh == NULL )
10 { 11 {
11 reportError("Couldn't open file."); 12 throw XmlException("Couldn't open file: %s", sFile );
12 //nError = 1; 13 //nError = 1;
13 } 14 }
14 else 15 else
@@ -50,7 +51,7 @@ char XmlFileReader::getChar( int nIndex )
50 } 51 }
51 else 52 else
52 { 53 {
53 return '\0'; 54 throw XmlException("End of XML stream read.");
54 } 55 }
55} 56}
56 57
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 @@
1#include "xmlreader.h" 1#include "xmlreader.h"
2#include "xmlexception.h"
2#include <string.h> 3#include <string.h>
3 4
4XmlReader::XmlReader( bool bStrip ) 5XmlReader::XmlReader( bool bStrip ) :
6 bStrip( bStrip )
5{ 7{
6 nError = 0;
7 this->bStrip = bStrip;
8} 8}
9 9
10XmlReader::~XmlReader() 10XmlReader::~XmlReader()
@@ -68,13 +68,12 @@ bool XmlReader::node()
68 } 68 }
69 else 69 else
70 { 70 {
71 reportError("Close node in singleNode malformed!"); 71 throw XmlException("Close node in singleNode malformed!");
72 return false;
73 } 72 }
74 } 73 }
75 else 74 else
76 { 75 {
77 reportError("Close node expected, but not found."); 76 throw XmlException("Close node expected, but not found.");
78 return false; 77 return false;
79 } 78 }
80 79
@@ -108,8 +107,7 @@ bool XmlReader::startNode()
108 } 107 }
109 else 108 else
110 { 109 {
111 reportError("Got a mismatched node close tag."); 110 throw XmlException("Got a mismatched node close tag.");
112 return false;
113 } 111 }
114 } 112 }
115 else 113 else
@@ -127,8 +125,7 @@ bool XmlReader::startNode()
127 } 125 }
128 else 126 else
129 { 127 {
130 reportError("Got extra junk data instead of node close tag."); 128 throw XmlException("Got extra junk data instead of node close tag.");
131 return false;
132 } 129 }
133 } 130 }
134 else 131 else
@@ -146,8 +143,7 @@ bool XmlReader::startNode()
146 } 143 }
147 else 144 else
148 { 145 {
149 reportError("Expected to find node opening char, '<'.\n"); 146 throw XmlException("Expected to find node opening char, '<'.");
150 return false;
151 } 147 }
152 148
153 return true; 149 return true;
@@ -306,7 +302,7 @@ bool XmlReader::param()
306 } 302 }
307 else 303 else
308 { 304 {
309 reportError("Expected an equals to seperate the params."); 305 throw XmlException("Expected an equals to seperate the params.");
310 return false; 306 return false;
311 } 307 }
312 308
@@ -352,8 +348,7 @@ bool XmlReader::content()
352 } 348 }
353 else 349 else
354 { 350 {
355 reportError("Mismatched close tag found."); 351 throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() );
356 return false;
357 } 352 }
358 } 353 }
359 else 354 else
@@ -370,8 +365,7 @@ bool XmlReader::content()
370 } 365 }
371 else 366 else
372 { 367 {
373 reportError("Malformed close tag."); 368 throw XmlException("Malformed close tag.");
374 return false;
375 } 369 }
376 } 370 }
377 else 371 else
@@ -400,13 +394,3 @@ bool XmlReader::content()
400 } 394 }
401} 395}
402 396
403void XmlReader::reportError( const char *sError )
404{
405 printf("XmlReader error: %s\n", sError );
406}
407
408int XmlReader::getError()
409{
410 return nError;
411}
412
diff --git a/src/xmlreader.h b/src/xmlreader.h
index a8a81f0..19e485a 100644
--- a/src/xmlreader.h
+++ b/src/xmlreader.h
@@ -38,19 +38,6 @@ public:
38 ~XmlReader(); 38 ~XmlReader();
39 39
40 /** 40 /**
41 * Get the error code if an error happened.
42 *@returns The error code (I don't know what they are either)
43 */
44 int getError();
45
46 /**
47 * Report an error to something, this is a really strange mechanism and
48 * should probably just be replaced with the multi-log system.
49 *@param sError The error to report.
50 */
51 void reportError( const char *sError );
52
53 /**
54 * Build a document based on some kind of input. This is called 41 * Build a document based on some kind of input. This is called
55 * automatically by the constructor. 42 * automatically by the constructor.
56 */ 43 */
@@ -127,7 +114,6 @@ private:
127 FlexBuf fbParamName; /**< buffer for the current param's name. */ 114 FlexBuf fbParamName; /**< buffer for the current param's name. */
128 FlexBuf fbParamValue; /**< buffer for the current param's value. */ 115 FlexBuf fbParamValue; /**< buffer for the current param's value. */
129 bool bStrip; /**< Are we stripping whitespace? */ 116 bool bStrip; /**< Are we stripping whitespace? */
130 int nError; /**< Is there an error? */
131}; 117};
132 118
133#endif 119#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 @@
1#include "xmlstringreader.h" 1#include "xmlstringreader.h"
2#include "xmlexception.h"
2#include <string.h> 3#include <string.h>
3 4
4XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) 5XmlStringReader::XmlStringReader( const char *sString, bool bStrip )
@@ -24,7 +25,7 @@ char XmlStringReader::getChar( int nAdd )
24 } 25 }
25 else 26 else
26 { 27 {
27 return '\0'; 28 throw XmlException("End of XML stream read.");
28 } 29 }
29} 30}
30 31