gtsam/CppUnitLite/Test.h

170 lines
6.4 KiB
C++

/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////
//
// TEST.H
//
// This file contains the Test class along with the macros which make effective
// in the harness.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef TEST_H
#define TEST_H
#include <cmath>
#include <boost/lexical_cast.hpp>
class TestResult;
class Test
{
public:
Test (const std::string& testName);
Test (const std::string& testName, const std::string& filename, long lineNumber, bool safeCheck);
virtual ~Test() {};
virtual void run (TestResult& result) = 0;
void setNext(Test *test);
Test *getNext () const;
std::string getName() const {return name_;}
std::string getFilename() const {return filename_;}
long getLineNumber() const {return lineNumber_;}
bool safe() const {return safeCheck_;}
protected:
bool check (long expected, long actual, TestResult& result, const std::string& fileName, long lineNumber);
bool check (const std::string& expected, const std::string& actual, TestResult& result, const std::string& fileName, long lineNumber);
std::string name_;
Test *next_;
std::string filename_;
long lineNumber_; /// This is the line line number of the test, rather than the a single check
bool safeCheck_;
};
/**
* Normal test will wrap execution in a try/catch block to catch exceptions more effectively
*/
#define TEST(testGroup, testName)\
class testGroup##testName##Test : public Test \
{ public: testGroup##testName##Test () : Test (#testName "Test", __FILE__, __LINE__, true) {} \
virtual ~testGroup##testName##Test () {};\
void run (TestResult& result_);} \
testGroup##testName##Instance; \
void testGroup##testName##Test::run (TestResult& result_)
/**
* For debugging only: use TEST_UNSAFE to allow debuggers to have access to exceptions, as this
* will not wrap execution with a try/catch block
*/
#define TEST_UNSAFE(testGroup, testName)\
class testGroup##testName##Test : public Test \
{ public: testGroup##testName##Test () : Test (#testName "Test", __FILE__, __LINE__, false) {} \
virtual ~testGroup##testName##Test () {};\
void run (TestResult& result_);} \
testGroup##testName##Instance; \
void testGroup##testName##Test::run (TestResult& result_)
/**
* Use this to disable unwanted tests without commenting them out.
*/
#define TEST_DISABLED(testGroup, testName)\
void testGroup##testName##Test(TestResult& result_, const std::string& name_)
/*
* Convention for tests:
* - "EXPECT" is a test that will not end execution of the series of tests
* - Otherwise, upon a failure, the test will end
*
* Usage:
* EXPECT is useful when checking several different parts of an condition so
* that a failure of one check won't hide another failure.
*
* Note: Exception tests are not available in a EXPECT form, as exceptions rarely
* fit the criteria of an assertion that does not need to be true to continue
*/
/* True ASSERTs: tests end at first failure */
#define CHECK(condition)\
{ if (!(condition)) \
{ result_.addFailure (Failure (name_, __FILE__,__LINE__, #condition)); return; } }
#define THROWS_EXCEPTION(condition)\
{ try { condition; \
result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Didn't throw: ") + boost::lexical_cast<std::string>(#condition))); \
return; } \
catch (...) {} }
#define CHECK_EXCEPTION(condition, exception_name)\
{ try { condition; \
result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Didn't throw: ") + boost::lexical_cast<std::string>(#condition))); \
return; } \
catch (exception_name&) {} \
catch (...) { \
result_.addFailure (Failure (name_, __FILE__,__LINE__, std::string("Wrong exception: ") + boost::lexical_cast<std::string>(#condition) + boost::lexical_cast<std::string>(", expected: ") + boost::lexical_cast<std::string>(#exception_name))); \
return; } }
#define EQUALITY(expected,actual)\
{ if (!assert_equal(expected,actual)) \
result_.addFailure(Failure(name_, __FILE__, __LINE__, #expected, #actual)); }
#define CHECK_EQUAL(expected,actual)\
{ if ((expected) == (actual)) return; result_.addFailure(Failure(name_, __FILE__, __LINE__, boost::lexical_cast<std::string>(expected), boost::lexical_cast<std::string>(actual))); }
#define LONGS_EQUAL(expected,actual)\
{ long actualTemp = actual; \
long expectedTemp = expected; \
if ((expectedTemp) != (actualTemp)) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__, boost::lexical_cast<std::string>(expectedTemp), \
boost::lexical_cast<std::string>(actualTemp))); return; } }
#define DOUBLES_EQUAL(expected,actual,threshold)\
{ double actualTemp = actual; \
double expectedTemp = expected; \
if (!std::isfinite(actualTemp) || !std::isfinite(expectedTemp) || fabs ((expectedTemp)-(actualTemp)) > threshold) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__, \
boost::lexical_cast<std::string>((double)expectedTemp), boost::lexical_cast<std::string>((double)actualTemp))); return; } }
/* EXPECTs: tests will continue running after a failure */
#define EXPECT(condition)\
{ if (!(condition)) \
{ result_.addFailure (Failure (name_, __FILE__,__LINE__, #condition)); } }
#define EXPECT_LONGS_EQUAL(expected,actual)\
{ long actualTemp = actual; \
long expectedTemp = expected; \
if ((expectedTemp) != (actualTemp)) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__, boost::lexical_cast<std::string>(expectedTemp), \
boost::lexical_cast<std::string>(actualTemp))); } }
#define EXPECT_DOUBLES_EQUAL(expected,actual,threshold)\
{ double actualTemp = actual; \
double expectedTemp = expected; \
if (!std::isfinite(actualTemp) || !std::isfinite(expectedTemp) || fabs ((expectedTemp)-(actualTemp)) > threshold) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__, \
boost::lexical_cast<std::string>((double)expectedTemp), boost::lexical_cast<std::string>((double)actualTemp))); } }
#define FAIL(text) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__,(text))); return; }
#endif