testinfo.h
Go to the documentation of this file.00001 #ifndef CPPUT_TESTINFO_H_INCLUDED
00002 # define CPPUT_TESTINFO_H_INCLUDED
00003
00004 # include <cpput/forwards.h>
00005 # include <cpput/message.h>
00006 # include <cpptl/intrusiveptr.h>
00007 # include <json/value.h>
00008 # include <stdexcept>
00009
00010 namespace CppUT {
00011
00012
00017 class CPPUT_API AbortingAssertionException : public std::runtime_error
00018 {
00019 public:
00020 AbortingAssertionException( const std::string &message )
00021 : std::runtime_error( "AbortingAssertionException:\n" + message )
00022 {
00023 }
00024
00025 virtual ~AbortingAssertionException() throw()
00026 {
00027 }
00028 };
00029
00030
00035 class CPPUT_API SkipTestException : public std::runtime_error
00036 {
00037 public:
00038 SkipTestException()
00039 : std::runtime_error( "SkipTestException" )
00040 {
00041 }
00042
00043 virtual ~SkipTestException() throw()
00044 {
00045 }
00046 };
00047
00048
00053 class CPPUT_API UndeclaredResourceException : public std::runtime_error
00054 {
00055 public:
00056 UndeclaredResourceException( const std::string &resourceName )
00057 : std::runtime_error( "UndeclaredResourceException: " + resourceName )
00058 {
00059 }
00060
00061 virtual ~UndeclaredResourceException() throw()
00062 {
00063 }
00064 };
00065
00068 class SourceLocation
00069 {
00070 public:
00071 SourceLocation( const char *file = 0,
00072 unsigned int line =0 )
00073 : file_( file )
00074 , line_( line )
00075 {
00076 }
00077
00078 void clear()
00079 {
00080 file_ = 0;
00081 line_ = 0;
00082 }
00083
00084 bool isValid() const
00085 {
00086 return file_ != 0;
00087 }
00088
00089 const char *file_;
00090 unsigned int line_;
00091 };
00092
00096 class CPPUT_API Assertion
00097 {
00098 public:
00099 enum Kind
00100 {
00101 fault = 1,
00102 assertion = 2
00103 };
00104
00105 Assertion( Kind kind = assertion,
00106 const SourceLocation &sourceLocation = SourceLocation() );
00107
00108 void setLocation( const SourceLocation &location );
00109 const SourceLocation &location() const;
00110
00111 void setKind( Kind kind_ );
00112 Kind kind() const;
00113
00114 void setIgnoredFailure();
00115 bool isIgnoredFailure() const;
00116
00117 void setMessages( const Message &messages );
00118 const Message &messages() const;
00119
00120 void setTestDataType( const std::string &type );
00121 std::string testDataType() const;
00122
00123 void setTestData( const std::string &name,
00124 const Json::Value &value,
00125 const std::string &type = "basic" );
00126
00127 const Json::Value &testData() const;
00128
00129 std::string toString() const;
00130
00131 private:
00132 Message messages_;
00133 Json::Value testData_;
00134 CppTL::ConstString testDataType_;
00135 SourceLocation location_;
00136 Kind kind_;
00137 bool isIgnoredFailure_;
00138 };
00139
00140
00144 class CPPUT_API TestStatus
00145 {
00146 public:
00147 enum Status
00148 {
00149 passed = 1,
00150 skipped,
00151 failed
00152 };
00153
00154 TestStatus( Status status = passed );
00155
00156 void setStatus( Status status );
00157
00158 Status status() const;
00159
00160 bool hasFailed() const;
00161 bool hasPassed() const;
00162 bool wasSkipped() const;
00163
00164 void setStatistics( const std::string &name,
00165 const Json::Value &value );
00166
00167
00168 void addSpecific( const std::string &type,
00169 const Json::Value &value );
00170
00171 int assertionCount() const;
00172 int failedAssertionCount() const;
00173 int ignoredFailureCount() const;
00174
00175 void increaseAssertionCount( int delta = 1 );
00176 void increaseFailedAssertionCount( int delta = 1 );
00177 void increaseIgnoredFailureCount( int delta = 1 );
00178 private:
00179 Json::Value statistics_;
00180 Json::Value specifics_;
00181 Status status_;
00182 unsigned int assertionCount_;
00183 unsigned int failedAssertionCount_;
00184 unsigned int ignoredFailureCount_;
00185 };
00186
00187
00189 class CheckerResult
00190 {
00191 public:
00192 CheckerResult()
00193 : status_( TestStatus::passed )
00194 , message_( "" )
00195 {
00196 }
00197
00198 void setFailed()
00199 {
00200 status_ = TestStatus::failed;
00201 }
00202
00208 void compose( const CheckerResult &other )
00209 {
00210 switch ( status_ )
00211 {
00212 case TestStatus::failed:
00213 case TestStatus::passed:
00214 if ( other.status_ != TestStatus::passed )
00215 status_ = other.status_;
00216 break;
00217 case TestStatus::skipped:
00218 break;
00219 default:
00220 CPPTL_DEBUG_ASSERT_UNREACHABLE;
00221 }
00222 message_.extend( other.message_ );
00223 }
00224
00225 TestStatus::Status status_;
00226 Message message_;
00227 };
00228
00229 namespace Impl {
00230
00232 class CheckerLineLocation
00233 {
00234 public:
00235 const CheckerResult *result_;
00236 unsigned long line_;
00237 };
00238
00239 struct FileLocationMarker {};
00240
00241
00243 class CheckerFileLocation
00244 {
00245 public:
00246 const CheckerLineLocation *lineData_;
00247 const char *file_;
00248 };
00249
00251 class AssertionTrigger
00252 {
00253 public:
00254 static AssertionTrigger aborting;
00255 static AssertionTrigger checking;
00256
00257 AssertionTrigger &operator +=( const CheckerFileLocation &fileLocation );
00258 };
00259
00260 }
00261
00262
00317 # define CPPUT_BEGIN_ASSERTION_MACRO() \
00318 CppUT::Impl::AssertionTrigger::aborting += (const CppUT::Impl::FileLocationMarker *)__FILE__ + __LINE__ /
00319
00324 # define CPPUT_BEGIN_CHECKING_MACRO() \
00325 CppUT::Impl::AssertionTrigger::checking += (const CppUT::Impl::FileLocationMarker *)__FILE__ + __LINE__ /
00326
00327
00328
00331 class CPPUT_API TestResultUpdater : public CppTL::IntrusiveCount
00332 {
00333 public:
00334 virtual ~TestResultUpdater()
00335 {
00336 }
00337
00338 virtual void addResultLog( const Json::Value &log ) = 0;
00339
00340 virtual void addResultAssertion( const Assertion &assertion ) = 0;
00341 };
00342
00346 enum AssertionType
00347 {
00348 abortingAssertion = 1,
00349 checkingAssertion
00350 };
00351
00355 enum AbortingAssertionMode
00356 {
00357 fastAbortingAssertion = 1,
00358 richAbortingAssertion
00359 };
00360
00365 class TestInfo : public CppTL::IntrusiveCount
00366
00367 {
00368 public:
00369 class CPPUT_API ScopedContextOverride
00370 {
00371 public:
00372 ScopedContextOverride();
00373
00374 ~ScopedContextOverride();
00375
00376 protected:
00377 TestInfoPtr context_;
00378 };
00379
00380 class CPPUT_API IgnoreFailureScopedContextOverride : public ScopedContextOverride
00381 , private TestResultUpdater
00382 {
00383 public:
00384 IgnoreFailureScopedContextOverride( bool &assertionFailed );
00385
00386 ~IgnoreFailureScopedContextOverride();
00387
00388 private:
00389 virtual void addResultLog( const Json::Value &log );
00390
00391 virtual void addResultAssertion( const Assertion &assertion );
00392
00393 private:
00394 Assertion *assertion_;
00395 bool &assertionFailed_;
00396 };
00397
00398 friend class IgnoreFailureScopedContextOverride;
00399
00400
00405 static TestInfo &threadInstance();
00406
00407 TestInfo();
00408
00409 void setTestResultUpdater( TestResultUpdater &updater );
00410 void removeTestResultUpdater();
00411
00415 void startNewTest();
00416
00420 void addResource( const AcquiredResourceHandlePtr &resource );
00421
00425 void discardTestResources();
00426
00433 Resource &getResource( const ResourceName &name );
00434
00435 TestStatus &testStatus();
00436
00437 void handleAssertion( const char *file,
00438 unsigned int line,
00439 const CheckerResult &result,
00440 bool isAbortingAssertion );
00441
00442 void handleUnexpectedException( const Assertion &fault );
00443
00444 void setAbortingAssertionMode( AbortingAssertionMode mode );
00445
00446 void log( const Json::Value &log );
00447
00448 private:
00449 typedef std::map<ResourceName,AcquiredResourceHandlePtr> Resources;
00450 Resources resources_;
00451 TestStatus testStatus_;
00452 Assertion currentAssertion_;
00453 AssertionType assertionType_;
00454 AbortingAssertionMode abortingAssertionMode_;
00455 TestResultUpdater *updater_;
00456 };
00457
00465 Resource &CPPUT_API getResource( const ResourceName &name );
00466
00470 void CPPUT_API log( const Json::Value &log );
00471
00475 void CPPUT_API log( const std::string &log );
00476
00480 void CPPUT_API log( const char *log );
00481
00485 void CPPUT_API log( const CppTL::ConstString &log );
00486
00487 }
00488
00489
00490 inline CppUT::Impl::CheckerLineLocation operator /( unsigned long line, const CppUT::CheckerResult &result )
00491 {
00492 CppUT::Impl::CheckerLineLocation lineData;
00493 lineData.result_ = &result;
00494 lineData.line_ = line;
00495 return lineData;
00496 }
00497
00498
00499 inline CppUT::Impl::CheckerFileLocation operator +( const CppUT::Impl::FileLocationMarker *file, const CppUT::Impl::CheckerLineLocation &lineData )
00500 {
00501 CppUT::Impl::CheckerFileLocation fileData;
00502 fileData.file_ = (const char *)file;
00503 fileData.lineData_ = &lineData;
00504 return fileData;
00505 }
00506
00507
00508
00509 #endif // CPPUT_TESTINFO_H_INCLUDED