学习笔记:解读CppUnit源码7
2009-11-11 10:56
483 查看
前面看过了 Message,SourceLine,Exception类的特征,那么这些类是如何运用在输出上呢?由这个问题带出我们今天要阅读的代码。
Asserter.h
Asserter并不是一个类,是用来编写和和断言有关的宏的。稍后在宏定义的地方,会看到这些的用法。
TestAssert.h
assertEquals里面,用到了对象萃取技术,用到了模板的全特化技术。刚开始看这个全特化的时候还以为会有问题。因为按照常理来说,double数据是不能进行==比较的。但是看看后面,找到了断言CPPUNIT_ASSERT_DOUBLES_EQUAL,所以要符点数的比较用到的应该是这个宏。
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,所以要符点数的比较用到的应该是这个宏。
相关文章推荐
- 学习笔记:解读CppUnit源码3
- 学习笔记:解读CppUnit源码2
- 学习笔记:解读CppUnit源码8
- Spark学习笔记(7)源码解读之JobScheduler内幕实现
- Spark学习笔记(15)Spark Streaming源码解读之No Receivers
- Feign学习笔记2-源码解读
- (一)Netty源码学习笔记之概念解读
- OpenCv学习笔记(一)--OpenCv中Mat类源码的详细解读(1)
- spring学习笔记之DispatcherServlet源码解读
- Spark学习笔记(11)源码解读之Driver中的ReceiverTracker架构
- spring学习笔记之handler mapping源码解读
- jfinal学习笔记02 源码解读JFinalFilter
- Spark学习笔记(12)源码解读之Executor容错安全性
- spring学习笔记之AbstractController源码解读
- Spark学习笔记(6)源码解读之Job动态生成和深度思考
- CAFFE源码学习笔记之一
- zepto.1.1.6.js源码中的each方法学习笔记
- api.js源码阅读学习笔记
- CAFFE源码学习笔记之三-common
- Linux学习笔记(搭建本地源,源码安装)