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,
const SimpleString& theFileName,

View File

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

View File

@ -9,47 +9,56 @@
static const int DEFAULT_SIZE = 20;
SimpleString::SimpleString ()
: buffer(new char [1])
: buffer_(new char [1])
{
buffer [0] = '\0';
buffer_ [0] = '\0';
}
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)
{
buffer = new char [other.size() + 1];
strcpy(buffer, other.buffer);
buffer_ = new char [other.size() + 1];
strcpy(buffer_, other.buffer_);
}
SimpleString SimpleString::operator= (const SimpleString& other)
{
delete buffer;
buffer = new char [other.size() + 1];
strcpy(buffer, other.buffer);
delete buffer_;
buffer_ = new char [other.size() + 1];
strcpy(buffer_, other.buffer_);
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
{
return buffer;
return buffer_;
}
int SimpleString::size() const
{
return strlen (buffer);
return strlen (buffer_);
}
SimpleString::~SimpleString ()
{
delete [] buffer;
delete [] buffer_;
}

View File

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

View File

@ -12,6 +12,11 @@ Test::Test (const SimpleString& testName)
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

View File

@ -22,6 +22,7 @@ class Test
{
public:
Test (const SimpleString& testName);
Test (const SimpleString& testName, const SimpleString& filename, long lineNumber);
virtual ~Test() {};
virtual void run (TestResult& result) = 0;
@ -29,6 +30,9 @@ public:
void setNext(Test *test);
Test *getNext () const;
SimpleString getName() const {return name_;}
SimpleString getFilename() const {return filename_;}
long getLineNumber() const {return lineNumber_;}
protected:
@ -37,13 +41,15 @@ protected:
SimpleString name_;
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)\
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_);} \
testGroup##testName##Instance; \
void testGroup##testName##Test::run (TestResult& result_)

View File

@ -1,8 +1,12 @@
#include <exception>
#include "Test.h"
#include "Failure.h"
#include "TestResult.h"
#include "TestRegistry.h"
#include "SimpleString.h"
void TestRegistry::addTest (Test *test)
@ -13,7 +17,7 @@ void TestRegistry::addTest (Test *test)
int TestRegistry::runAllTests (TestResult& result)
{
instance ().run (result);
return instance ().run (result);
}
@ -30,7 +34,7 @@ void TestRegistry::add (Test *test)
tests = test;
return;
}
test->setNext (tests);
tests = test;
}
@ -40,10 +44,22 @@ int TestRegistry::run (TestResult& result)
{
result.testsStarted ();
for (Test *test = tests; test != 0; test = test->getNext ())
test->run (result);
for (Test *test = tests; test != 0; test = test->getNext ()) {
// 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 ();
return result.getFailureCount();
return result.getFailureCount();
}

View File

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

View File

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

View File

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