CppUnitLite will now catch exceptions and tell you the error and the line number of the failing test. This is to avoid having to hunt for crashing tests out of a large battery of tests. Look at the results of the (still failing) wrap/testWrap for an example.

release/4.3a0
Alex Cunningham 2010-07-16 19:30:38 +00:00
parent 3438f89526
commit 7b85dc3ff4
10 changed files with 130 additions and 81 deletions

View File

@ -17,6 +17,16 @@ Failure::Failure (const SimpleString& theTestName,
{ {
} }
Failure::Failure (const SimpleString& theTestName,
const SimpleString& theFileName,
const SimpleString& theCondition)
: message (theCondition),
testName (theTestName),
fileName (theFileName),
lineNumber (-1)
{
}
Failure::Failure (const SimpleString& theTestName, Failure::Failure (const SimpleString& theTestName,
const SimpleString& theFileName, const SimpleString& theFileName,

View File

@ -31,6 +31,11 @@ public:
const SimpleString& expected, const SimpleString& expected,
const SimpleString& actual); const SimpleString& actual);
Failure (const SimpleString& theTestName,
const SimpleString& theFileName,
const SimpleString& theCondition);
SimpleString message; SimpleString message;
SimpleString testName; SimpleString testName;
SimpleString fileName; SimpleString fileName;

View File

@ -9,47 +9,56 @@
static const int DEFAULT_SIZE = 20; static const int DEFAULT_SIZE = 20;
SimpleString::SimpleString () SimpleString::SimpleString ()
: buffer(new char [1]) : buffer_(new char [1])
{ {
buffer [0] = '\0'; buffer_ [0] = '\0';
} }
SimpleString::SimpleString (const char *otherBuffer) SimpleString::SimpleString (const char *otherBuffer)
: buffer (new char [strlen (otherBuffer) + 1]) : buffer_ (new char [strlen (otherBuffer) + 1])
{ {
strcpy (buffer, otherBuffer); strcpy (buffer_, otherBuffer);
} }
SimpleString::SimpleString (const SimpleString& other) SimpleString::SimpleString (const SimpleString& other)
{ {
buffer = new char [other.size() + 1]; buffer_ = new char [other.size() + 1];
strcpy(buffer, other.buffer); strcpy(buffer_, other.buffer_);
} }
SimpleString SimpleString::operator= (const SimpleString& other) SimpleString SimpleString::operator= (const SimpleString& other)
{ {
delete buffer; delete buffer_;
buffer = new char [other.size() + 1]; buffer_ = new char [other.size() + 1];
strcpy(buffer, other.buffer); strcpy(buffer_, other.buffer_);
return *this; return *this;
} }
SimpleString SimpleString::operator+ (const SimpleString& other)
{
SimpleString ret;
delete ret.buffer_;
ret.buffer_ = new char [size() + other.size() - 1];
strcpy(ret.buffer_, buffer_);
strcat(ret.buffer_, other.buffer_);
return ret;
}
char *SimpleString::asCharString () const char *SimpleString::asCharString () const
{ {
return buffer; return buffer_;
} }
int SimpleString::size() const int SimpleString::size() const
{ {
return strlen (buffer); return strlen (buffer_);
} }
SimpleString::~SimpleString () SimpleString::~SimpleString ()
{ {
delete [] buffer; delete [] buffer_;
} }

View File

@ -25,12 +25,13 @@ public:
~SimpleString (); ~SimpleString ();
SimpleString operator= (const SimpleString& other); SimpleString operator= (const SimpleString& other);
SimpleString operator+ (const SimpleString& other);
char *asCharString () const; char *asCharString () const;
int size() const; int size() const;
private: private:
char *buffer; char *buffer_;
}; };

View File

@ -12,6 +12,11 @@ Test::Test (const SimpleString& testName)
TestRegistry::addTest (this); TestRegistry::addTest (this);
} }
Test::Test (const SimpleString& testName, const SimpleString& filename, long lineNumber)
: name_(testName), filename_(filename), lineNumber_(lineNumber)
{
TestRegistry::addTest (this);
}
Test *Test::getNext() const Test *Test::getNext() const

View File

@ -22,6 +22,7 @@ class Test
{ {
public: public:
Test (const SimpleString& testName); Test (const SimpleString& testName);
Test (const SimpleString& testName, const SimpleString& filename, long lineNumber);
virtual ~Test() {}; virtual ~Test() {};
virtual void run (TestResult& result) = 0; virtual void run (TestResult& result) = 0;
@ -29,6 +30,9 @@ public:
void setNext(Test *test); void setNext(Test *test);
Test *getNext () const; Test *getNext () const;
SimpleString getName() const {return name_;}
SimpleString getFilename() const {return filename_;}
long getLineNumber() const {return lineNumber_;}
protected: protected:
@ -37,13 +41,15 @@ protected:
SimpleString name_; SimpleString name_;
Test *next_; Test *next_;
SimpleString filename_;
long lineNumber_; /// This is the line line number of the test, rather than the a single check
}; };
#define TEST(testName, testGroup)\ #define TEST(testName, testGroup)\
class testGroup##testName##Test : public Test \ class testGroup##testName##Test : public Test \
{ public: testGroup##testName##Test () : Test (#testName "Test") {} \ { public: testGroup##testName##Test () : Test (#testName "Test", __FILE__, __LINE__) {} \
void run (TestResult& result_);} \ void run (TestResult& result_);} \
testGroup##testName##Instance; \ testGroup##testName##Instance; \
void testGroup##testName##Test::run (TestResult& result_) void testGroup##testName##Test::run (TestResult& result_)

View File

@ -1,8 +1,12 @@
#include <exception>
#include "Test.h" #include "Test.h"
#include "Failure.h"
#include "TestResult.h" #include "TestResult.h"
#include "TestRegistry.h" #include "TestRegistry.h"
#include "SimpleString.h"
void TestRegistry::addTest (Test *test) void TestRegistry::addTest (Test *test)
@ -13,7 +17,7 @@ void TestRegistry::addTest (Test *test)
int TestRegistry::runAllTests (TestResult& result) int TestRegistry::runAllTests (TestResult& result)
{ {
instance ().run (result); return instance ().run (result);
} }
@ -40,10 +44,22 @@ int TestRegistry::run (TestResult& result)
{ {
result.testsStarted (); result.testsStarted ();
for (Test *test = tests; test != 0; test = test->getNext ()) for (Test *test = tests; test != 0; test = test->getNext ()) {
test->run (result); // TODO: add a try/catch wrapper here
try {
test->run (result);
} catch (std::exception& e) {
result.addFailure(
Failure(test->getName(), test->getFilename(), test->getLineNumber(),
SimpleString("Exception: ") + SimpleString(e.what())));
} catch (...) {
result.addFailure(
Failure(test->getName(), test->getFilename(), test->getLineNumber(),
SimpleString("ExceptionThrown!")));
}
}
result.testsEnded (); result.testsEnded ();
return result.getFailureCount(); return result.getFailureCount();
} }

View File

@ -18,14 +18,21 @@ void TestResult::testsStarted ()
void TestResult::addFailure (const Failure& failure) void TestResult::addFailure (const Failure& failure)
{ {
fprintf (stdout, "%s%s%s%s%ld%s%s\n", if (failure.lineNumber < 0) // allow for no line number
"Failure: \"", fprintf (stdout, "%s%s%s%s%ld%s%s\n",
failure.message.asCharString (), "Failure: \"",
"\" " , failure.message.asCharString (),
"line ", "\" in ",
failure.lineNumber, failure.fileName.asCharString ());
" in ", else
failure.fileName.asCharString ()); fprintf (stdout, "%s%s%s%s%ld%s%s\n",
"Failure: \"",
failure.message.asCharString (),
"\" " ,
"line ",
failure.lineNumber,
" in ",
failure.fileName.asCharString ());
failureCount++; failureCount++;
} }

View File

@ -34,7 +34,6 @@ TEST( matrix, constructor_data )
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( matrix, constructor_vector ) TEST( matrix, constructor_vector )
{ {
double data[] = { -5, 3, 0, -5 }; double data[] = { -5, 3, 0, -5 };

View File

@ -28,72 +28,63 @@ TEST( wrap, ArgumentList ) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST( wrap, parse ) { TEST( wrap, parse ) {
try { Module module(".", "geometry",verbose);
Module module(".", "geometry",verbose); CHECK(module.classes.size()==3);
CHECK(module.classes.size()==3);
// check second class, Point3 // check second class, Point3
Class cls = *(++module.classes.begin()); Class cls = *(++module.classes.begin());
CHECK(cls.name=="Point3"); CHECK(cls.name=="Point3");
CHECK(cls.constructors.size()==1); CHECK(cls.constructors.size()==1);
CHECK(cls.methods.size()==1); CHECK(cls.methods.size()==1);
// first constructor takes 3 doubles // first constructor takes 3 doubles
Constructor c1 = cls.constructors.front(); Constructor c1 = cls.constructors.front();
CHECK(c1.args.size()==3); CHECK(c1.args.size()==3);
// check first double argument // check first double argument
Argument a1 = c1.args.front(); Argument a1 = c1.args.front();
CHECK(!a1.is_const); CHECK(!a1.is_const);
CHECK(a1.type=="double"); CHECK(a1.type=="double");
CHECK(!a1.is_ref); CHECK(!a1.is_ref);
CHECK(a1.name=="x"); CHECK(a1.name=="x");
// check method // check method
Method m1 = cls.methods.front(); Method m1 = cls.methods.front();
CHECK(m1.returns=="double"); CHECK(m1.returns=="double");
CHECK(m1.name=="norm"); CHECK(m1.name=="norm");
CHECK(m1.args.size()==0); CHECK(m1.args.size()==0);
CHECK(m1.is_const); CHECK(m1.is_const);
} catch (exception& e) {
FAIL(e.what());
}
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( wrap, matlab_code ) { TEST( wrap, matlab_code ) {
// Parse into class object // Parse into class object
try { Module module(".","geometry",verbose);
Module module(".","geometry",verbose);
// emit MATLAB code // emit MATLAB code
// make_geometry will not compile, use make testwrap to generate real make // make_geometry will not compile, use make testwrap to generate real make
module.matlab_code("actual", "", "-O5"); module.matlab_code("actual", "", "-O5");
CHECK(files_equal("expected/@Point2/Point2.m" , "actual/@Point2/Point2.m" )); CHECK(files_equal("expected/@Point2/Point2.m" , "actual/@Point2/Point2.m" ));
CHECK(files_equal("expected/@Point2/x.cpp" , "actual/@Point2/x.cpp" )); CHECK(files_equal("expected/@Point2/x.cpp" , "actual/@Point2/x.cpp" ));
CHECK(files_equal("expected/@Point3/Point3.m" , "actual/@Point3/Point3.m" )); CHECK(files_equal("expected/@Point3/Point3.m" , "actual/@Point3/Point3.m" ));
CHECK(files_equal("expected/new_Point3_ddd.m" , "actual/new_Point3_ddd.m" )); CHECK(files_equal("expected/new_Point3_ddd.m" , "actual/new_Point3_ddd.m" ));
CHECK(files_equal("expected/new_Point3_ddd.cpp", "actual/new_Point3_ddd.cpp")); CHECK(files_equal("expected/new_Point3_ddd.cpp", "actual/new_Point3_ddd.cpp"));
CHECK(files_equal("expected/@Point3/norm.m" , "actual/@Point3/norm.m" )); CHECK(files_equal("expected/@Point3/norm.m" , "actual/@Point3/norm.m" ));
CHECK(files_equal("expected/@Point3/norm.cpp" , "actual/@Point3/norm.cpp" )); CHECK(files_equal("expected/@Point3/norm.cpp" , "actual/@Point3/norm.cpp" ));
CHECK(files_equal("expected/new_Test_.cpp" , "actual/new_Test_.cpp" )); CHECK(files_equal("expected/new_Test_.cpp" , "actual/new_Test_.cpp" ));
CHECK(files_equal("expected/@Test/Test.m" , "actual/@Test/Test.m" )); CHECK(files_equal("expected/@Test/Test.m" , "actual/@Test/Test.m" ));
CHECK(files_equal("expected/@Test/return_string.cpp" , "actual/@Test/return_string.cpp" )); CHECK(files_equal("expected/@Test/return_string.cpp" , "actual/@Test/return_string.cpp" ));
CHECK(files_equal("expected/@Test/return_pair.cpp" , "actual/@Test/return_pair.cpp" )); CHECK(files_equal("expected/@Test/return_pair.cpp" , "actual/@Test/return_pair.cpp" ));
CHECK(files_equal("expected/@Test/return_field.cpp" , "actual/@Test/return_field.cpp" )); CHECK(files_equal("expected/@Test/return_field.cpp" , "actual/@Test/return_field.cpp" ));
CHECK(files_equal("expected/@Test/return_TestPtr.cpp", "actual/@Test/return_TestPtr.cpp")); CHECK(files_equal("expected/@Test/return_TestPtr.cpp", "actual/@Test/return_TestPtr.cpp"));
CHECK(files_equal("expected/@Test/return_ptrs.cpp" , "actual/@Test/return_ptrs.cpp" )); CHECK(files_equal("expected/@Test/return_ptrs.cpp" , "actual/@Test/return_ptrs.cpp" ));
CHECK(files_equal("expected/@Test/print.m" , "actual/@Test/print.m" )); CHECK(files_equal("expected/@Test/print.m" , "actual/@Test/print.m" ));
CHECK(files_equal("expected/@Test/print.cpp" , "actual/@Test/print.cpp" )); CHECK(files_equal("expected/@Test/print.cpp" , "actual/@Test/print.cpp" ));
CHECK(files_equal("expected/make_geometry.m" , "actual/make_geometry.m" )); CHECK(files_equal("expected/make_geometry.m" , "actual/make_geometry.m" ));
} catch (exception& e) {
FAIL(e.what()); // fails if file is in wrong place
}
} }
/* ************************************************************************* */ /* ************************************************************************* */