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.
parent
3438f89526
commit
7b85dc3ff4
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ TEST( matrix, constructor_data )
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
TEST( matrix, constructor_vector )
|
||||
{
|
||||
double data[] = { -5, 3, 0, -5 };
|
||||
|
|
|
@ -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" ));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
Loading…
Reference in New Issue