CPPUnit Source Code Interpretation (4)

zhaozj2021-02-17  58

[Declaration] If you need to copy, spread, please attach this statement, thank you. Original source: http://morningspace.51.net/ ,moyingzz@etang.com

Error handling

[Testfailure]

Related Documents: Testfailure.h, TestFailure.cpp

There are two types of errors in CPPUnit, which are: Failure and Error, respectively. A Failure is expected and can be detected for the assertion; and Error is unpredictable, from an exception indicator, it is not generated by the frame code.

CPPUnit uses TestFailure this class simultaneously represents Failure and Error, see the member variable of TestFailure:

protected:

// Point to the failed test object

TEST * m_failedtest;

// Point to an abnormal object (if any)

EXCEPTION * m_THROWNEXCEPTION;

/ / Distinguish the tag of failure and Error

BOOL M_ISERROR;

Let's see the relevant code: // build a TestFailure based on FailedTest and Thrownexception

Testfailure :: TestFailure (Test * FailedTest,

Exception * thrownexception,

Bool isrror):

M_failedTest (FailedTest),

m_thrownexception (thrownexception),

m_iserror (ISERROR)

{

}

/ / Return m_iserror to determine if Error's function

Bool Testfail :: ISError () Const

{

Return m_iserror;

}

Also, let's take a look at the code about Clone, very simple: testfailure * testfailure :: clone () Const

{

// Create a one-size instance to return to its pointer

Return New Testfailure (m_failedtest, m_thrownexception-> clone (), m_iserror);

}

In addition to M_ISError, TestFail also provides an external access to another two member variables: std :: string testfailure :: failedtestname () Const

{

Return m_failedtest-> getName ();

}

Exception * Testfailure :: thrownexception () const

{

Return M_Thrownexception;

}

Finally, for the test failure, TestFail has recorded its error location, including the source file path and the line number in the file, can be accessed by the following interface: SourceLine Testfail :: SourceLine () Const

{

Return m_thrownexception-> sourceline ();

}

It can be seen that TestFailure calls the Sourceline method for Exception. In order to make the external convenient reference Sourceline, choose to increase its own interface (Sourceline method), and interface implementation is only simple delegate, which is often used in many places. Regarding the specific implementation of Sourceline, it will follow.

[SourceLine] Related Documents: SourceLine.h, SourceLine.cpp

The location of the error related to a failed test, including the source file path and the line number within the file. With it, we can accurately position the reason for the failure of the test. This class will be used in some macros associated with Asserter, which also references this class in Exception.

There are two member variables in Sourceline, respectively correspond to the source file path and the line number in the file:

Private:

Std :: string m_filename;

INT M_LINENUMBER;

In addition to providing the interface to these two member variables, SourceLine also overloads Operator == and Operator! =: Int sourine :: linenumber () Const

{

Return M_LineNumber;

}

Std :: string source :: filename () const

{

Return M_FileName;

}

Bool Source :: Operator == (Const SourceLine & Other) Const

{

Return M_FileName == Other.m_FileName &&

M_LineNumber == Other.m_LineNumber;

}

Bool Source :: Operator! = (Const Sourceline & Other) Const

{

// Call the Operator ==, that is, the correctness of the semantics, and avoid code repeat

// This type of practice is often used in the library design, which can be seen everywhere in the STL source code

Return! (* this == taher);

}

It can be seen that Sourceline is just a simple packaging of the error location. As for the setting of this information, it is necessary to decide the outside world. So how can the location in the next source file, there is a macro in SourceLine, all The secret is here: #define cppUnit_source () :: cppunit :: SourceLine (__file__, __line__)

This macro is called, such as an assertion, a SourceLine object is constructed, M_FileName and M_LineNumber are initialized to the location information of the macro. When talking to Testassert, you will see that these work is not worried, because Framework has arranged everything.

[EXCEPTION]

Related files: exception.h, exception.cpp

This is the abnormality mentioned in the previous mention. It derived from std :: exception, calling its What method to get the description information about this exception, throw an exception when an assertion fails.

There is an INNER Class - Type that identifies an exception type in Exception, which has a public property, with only one constant member variable M_Type, represents the specific type. The only CTOR assigns a value for m_type in the initialization member list, and there is an operator == function:

Class Type

{

PUBLIC:

TYPE (std :: string type): m_type (type) {}

Bool Operator == (const type & other) Const

{

Return M_Type == Other.m_type;}

Private:

Const std :: string m_type;

}

Package the type information is packaged. It should be a typical OO style, which is called "Replace Type Code with Class" technique in the Refactoring book, and the reader can also find other related content in the book: Replace Conditional With Polymorphism, Replace Type Code with Subclasses, Replace Type Code with State / Strategy, Replace Data Value with object. Two functions related to Type are type and isinstanceOf: // Return to Exception Type

Exception :: Type Exception :: Type ()

{

Return Type ("CPPUnit :: Exception");

}

/ / Judgment whether the ExceptionType is "cppunit :: exception"

Bool Exception :: IsinstanceOf (const type & exceptiontype) Const

{

Return EXCEPTIONTYPE == TYPE ();

}

IsinstanceOf implements a simple period of time period check, similar to iskindof in the MFC. It will also be seen in Exception's derived class. Exception has two private member variables: private:

Std :: string m_message; / / / / with this unusual description information

SourceLine m_sourceLine; // Abnormal location

View exception's CTOR found two different versions: Exception (std :: string message = ",

Sourceline SourceLine = SourceLine ());

#ifdef cppUnit_enable_sourceline_deprecated

Exception (std :: string message, long lineenumber, std :: string filename);

#ENDIF

About this CPPUNIT_ENABLE_SOURCELINE_DEPRECated origin, has "record" in the Changelog attached to CPPUnit. In the earlier version of CPPUnit, Exception did not quote the SourceLine class (that is, there is no first CTOR, Sourceline has not "born", but in the middle of the two member variables of FileName and Linenumber, this from the first It can also be seen in the declaration of the two CTORs. In the subsequent reactoring process, these two poor guys were eliminated by "Introduce Parameter Object", so Sourceline is replaced. However, as a released Framework, it is necessary to take into account compatible issues, so the previous interface must be retained, so the second CTOR still exists, but its internal implementation has stolen column: Exception :: Exception (std :: string message, long) LINENUMBER, std :: string filename:

M_Message (Message),

M_SourceLine (filename, linenumber) // is still transferred to SourceLine {}

Since it is "deprecated", then such an interface is of course not recommended, there are many clusters in the Exception source code, and there is not much to say it here. In short, the default case cppUnit_enable_sourceline_DepRecated is not defined, so the code surrounded by #ifdef cppUnit_enable_sourceline_deprecated ... # Endif is worthless. However, like this "historical legacy" issue, it will be encountered in many library design. There are several functions, the code is as follows: const char * exception :: what () const throw ()

{

Return m_message.c_str ();

}

Exception * Exception :: Clone () const

{

Return New Exception (* this);

}

Exception :: Operator = (const exception&)

{

IF (& other! = this)

{

m_message = other.m_message;

m_sourceline = other.m_sourceline;

}

Return * this;

}

[Notequalexception]

Related files: Notequalexception.h, Notequalexception.cpp

Derive from Exception, which will throw this exception when it is determined to fail. Compared with the base class, there are more three private member variables:

Private:

Std :: string m_expected; // expected value

Std :: string m_actual; // actual value, is it only supporting a string comparison, then explain it later?

Std :: string m_additionalMessage; // Additional information

Notequalexception also covers the class of Type, isInstanceOf, Clone, Operator = these functions: // Return Notequalexception Type

Exception :: Type Notequalexception :: type ()

{

Return Type ("CPPUnit :: Notequalexception");

}

// Call the ISInsTanceOf of the base class, so if the incoming value is an Exception's TYPE,

// Return to True, this is consistent with the timing

Bool Notequalexception :: IsinstanceOf (const type & exceptiontype) Const

{

Return EXCEPTIONTYPE == Type () ||

EXCETION :: isinstanceOf (ExceptionType);

}

Exception * Notequalexception :: Clone () Const

{

Return New Notequalexception (* this);

}

Notequalexception &

Notequalexception :: Operator = (const notequalexception&>)

{

Exception :: Operator = (帖子); / / Do not forget to call the base class Operator =

IF (& other! = this) {

m_expected = other.m_expected;

m_Actual = other.m_actual;

m_additionalmessage = other.m_additionalmessage;

}

RETURN * THIS;

}

转载请注明原文地址:https://www.9cbs.com/read-29138.html

New Post(0)