您的位置:首页 > 编程语言 > C语言/C++

学习笔记:解读CppUnit源码7

2009-11-11 10:56 483 查看
前面看过了 Message,SourceLine,Exception类的特征,那么这些类是如何运用在输出上呢?由这个问题带出我们今天要阅读的代码。

Asserter.h

struct MyAsserter
{
//抛异常
static void CPPUNIT_API fail( const MyMessage &message,
const MySourceLine &sourceLine = MySourceLine() )
{//抛出一个Exception对象,里面包含了和产生的错误信息
throw MyException( message, sourceLine );
};

//当shouldFail为true时才抛异常
static void CPPUNIT_API failIf( bool shouldFail,
const MyMessage &message,
const MySourceLine &sourceLine = MySourceLine() )
{
if ( shouldFail )
fail( message, sourceLine );
};

//预期值设置
static std::string CPPUNIT_API makeExpected( const std::string &expectedValue )
{
return "Expected: " + expectedValue;
};

//实际值设置
static std::string CPPUNIT_API makeActual( const std::string &actualValue )
{
return "Actual  : " + actualValue;
};

static MyMessage CPPUNIT_API makeNotEqualMessage( const std::string &expectedValue,
const std::string &actualValue,
const MyAdditionalMessage &additionalMessage = MyAdditionalMessage(),
const std::string &shortDescription = "equality assertion failed")
{
MyMessage message( shortDescription,
makeExpected( expectedValue ),
makeActual( actualValue ) );
message.addDetail( additionalMessage );

return message;
};

//表明expected字串和actual字串不相等的情况下,抛出错误
static void failNotEqual( std::string expected,
std::string actual,
const MySourceLine &sourceLine,
const MyAdditionalMessage &additionalMessage,
std::string shortDescription )
{
fail( makeNotEqualMessage( expected,
actual,
additionalMessage,
shortDescription ),
sourceLine );
};
//表明expected字串和actual字串不相等的情况下,根据shouldFail来决定是否输出错误
static void CPPUNIT_API failNotEqualIf( bool shouldFail,
std::string expected,
std::string actual,
const MySourceLine &sourceLine,
const MyAdditionalMessage &additionalMessage = MyAdditionalMessage(),
std::string shortDescription = "equality assertion failed" )
{
if ( shouldFail )
failNotEqual( expected, actual, sourceLine, additionalMessage, shortDescription );
};

};


Asserter并不是一个类,是用来编写和和断言有关的宏的。稍后在宏定义的地方,会看到这些的用法。

TestAssert.h

#include <sstream>
//比较两个数的大小和字符串化某数
CPPUNIT_NS_BEGIN
template <class T>
struct my_assertion_traits
{
static bool equal( const T& x, const T& y )
{
return x == y;
}

static std::string toString( const T& x )
{
std::stringstream ost;
ost << x;
return ost.str();
}
};
//比较两个数的大小和字符串化某数的特化板本
template <>
struct my_assertion_traits<double>
{
static bool equal( double x, double y )
{
return x == y;
//个人觉得这块源代码存在问题浮点数应该不能直接拿来比较的把
//正确的对策方法应该是:
//#define EPSIMON 0.000001
//fabs(a - b)<EPSIMON
}

static std::string toString( double x )
{
const int precision = 15;
char buffer[128];

#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%.*g", precision, x);
#else
sprintf(buffer, "%.*g", precision, x);
#endif
return buffer;
}
};

//若实际值和预期值不相符,则调用Asserter::failNotEqual
template <class T>
void assertEquals( const T& expected,
const T& actual,
MySourceLine sourceLine,
const std::string &message )
{
if ( !my_assertion_traits<T>::equal(expected,actual) ) // lazy toString conversion...
{
MyAsserter::failNotEqual( my_assertion_traits<T>::toString(expected),
my_assertion_traits<T>::toString(actual),
sourceLine,
message );
}
}
//为了浮点数特地准备的方法
void assertDoubleEquals( double expected,
double actual,
double delta,
MySourceLine sourceLine,
const std::string &message )
{
MyAdditionalMessage msg( "Delta   : " +
assertion_traits<double>::toString(delta) );
msg.addDetail( MyAdditionalMessage(message) );

bool equal;
//判断双精度浮点值x 是否有穷。
if ( floatingPointIsFinite(expected)  &&  floatingPointIsFinite(actual) )
equal = fabs( expected - actual ) <= delta;//有穷的情况
else
{
if ( floatingPointIsUnordered(expected)  ||  floatingPointIsUnordered(actual) )
{
equal = false;  // expected or actual is a NaN
}
else // ordered values, +inf or -inf comparison
{
equal = expected == actual;
}
}
//equal就是是否需要输出的标志
MyAsserter::failNotEqualIf( !equal,
assertion_traits<double>::toString(expected),
assertion_traits<double>::toString(actual),
sourceLine,
msg,
"double equality assertion failed" );
};

//为了方便使用,定义了以下的一组宏
//★表达式如果不成立则抛出错误
#define CPPUNIT_ASSERT(condition)                                                 /
( CPPUNIT_NS::MyAsserter::failIf( !(condition),                                   /
CPPUNIT_NS::MyMessage( "assertion failed",         /
"Expression: " #condition), /
CPPUNIT_SOURCELINE() ) )

//断言加上一条特殊的输出
#define CPPUNIT_ASSERT_MESSAGE(message,condition)                          /
( CPPUNIT_NS::MyAsserter::failIf( !(condition),                            /
CPPUNIT_NS::MyMessage( "assertion failed", /
"Expression: "      /
#condition,         /
message ),          /
CPPUNIT_SOURCELINE() ) )

//★断言是否相等
#define CPPUNIT_ASSERT_EQUAL(expected,actual)          /
( CPPUNIT_NS::assertEquals( (expected),              /
(actual),                /
CPPUNIT_SOURCELINE(),    /
"" ) )
//断言是否相等,不成立则输出message
#define CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual)      /
( CPPUNIT_NS::assertEquals( (expected),              /
(actual),                /
CPPUNIT_SOURCELINE(),    /
(message) ) )

//★断言是否相等:比较的是两个符点数
#define CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta)        /
( CPPUNIT_NS::assertDoubleEquals( (expected),            /
(actual),              /
(delta),               /
CPPUNIT_SOURCELINE(),  /
"" ) )
CPPUNIT_NS_END


assertEquals里面,用到了对象萃取技术,用到了模板的全特化技术。刚开始看这个全特化的时候还以为会有问题。因为按照常理来说,double数据是不能进行==比较的。但是看看后面,找到了断言CPPUNIT_ASSERT_DOUBLES_EQUAL,所以要符点数的比较用到的应该是这个宏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: