8000 This commit addresses two issues: · unittest-cpp/unittest-cpp@a9161c1 · GitHub
[go: up one dir, main page]

Skip to content
10000

Commit a9161c1

Browse files
ohz10pjohnmeyer
authored andcommitted
This commit addresses two issues:
(1) unreachable code in for loop shenanigans is eliminated. (2) code after a failing REQUIRE check no longer executes. Used a decorating TestReporter to achive this.
1 parent 06308ee commit a9161c1

8 files changed

+201
-10
lines changed

UnitTest++/CheckMacros.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
10000 if (!UnitTest::Check(value)) \
4242
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \
4343
}) \
44+
UT_CATCH (UnitTest::AssertException, e, \
45+
{ \
46+
UT_THROW(); \
47+
}) \
4448
UT_CATCH (std::exception, e, \
4549
{ \
4650
UnitTest::MemoryOutStream message; \
@@ -60,7 +64,11 @@
6064
UT_TRY \
6165
({ \
6266
UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
63-
}) \
67+
}) \
68+
UT_CATCH (UnitTest::AssertException, e, \
69+
{ \
70+
UT_THROW(); \
71+
}) \
6472
UT_CATCH (std::exception, e, \
6573
{ \
6674
UnitTest::MemoryOutStream message; \
@@ -81,6 +89,10 @@
8189
({ \
8290
UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
8391
}) \
92+
UT_CATCH (UnitTest::AssertException, e, \
93+
{ \
94+
UT_THROW(); \
95+
}) \
8496
UT_CATCH (std::exception, e, \
8597
{ \
8698
UnitTest::MemoryOutStream message; \
@@ -100,7 +112,11 @@
100112
UT_TRY \
101113
({ \
102114
UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
103-
}) \
115+
}) \
116+
UT_CATCH (UnitTest::AssertException, e, \
117+
{ \
118+
UT_THROW(); \
119+
}) \
104120
UT_CATCH (std::exception, e, \
105121
{ \
106122
UnitTest::MemoryOutStream message; \
@@ -121,6 +137,10 @@
121137
({ \
122138
UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
123139
}) \
140+
UT_CATCH (UnitTest::AssertException, e, \
141+
{ \
142+
UT_THROW(); \
143+
}) \
124144
UT_CATCH (std::exception, e, \
125145
{ \
126146
UnitTest::MemoryOutStream message; \
@@ -140,7 +160,11 @@
140160
UT_TRY \
141161
({ \
142162
UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
143-
}) \
163+
}) \
164+
UT_CATCH (UnitTest::AssertException, e, \
165+
{ \
166+
UT_THROW(); \
167+
}) \
144168
UT_CATCH (std::exception, e, \
145169
{ \
146170
UnitTest::MemoryOutStream message; \

UnitTest++/RequireMacros.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
#ifndef UNITTEST_REQUIREMACROS_H
22
#define UNITTEST_REQUIREMACROS_H
33

4-
#include "HelperMacros.h"
5-
#include "ExceptionMacros.h"
6-
#include "CurrentTest.h"
4+
#include "RequiredCheckTestReporter.h"
75

86
#ifdef REQUIRE
97
#error UnitTest++ redefines REQUIRE
108
#endif
119

1210
#ifndef UNITTEST_NO_EXCEPTIONS
13-
#define REQUIRE \
14-
for (int failuresBeforeTest = UnitTest::CurrentTest::Results()->GetFailureCount(), newFailures = 0, run = 0; \
15-
(run == 0) || ((newFailures != 0) && (throw UnitTest::AssertException(), true)); \
16-
newFailures = UnitTest::CurrentTest::Results()->GetFailureCount() - failuresBeforeTest, run = 1)
11+
#define REQUIRE for(UnitTest::RequiredCheckTestReporter decoratedReporter(UnitTest::CurrentTest::Results()); decoratedReporter.next(); )
1712
#endif
1813

1914
#ifdef UNITTEST_NO_EXCEPTIONS
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "RequiredCheckTestReporter.h"
2+
3+
#include "CurrentTest.h"
4+
#include "TestResults.h"
5+
6+
namespace UnitTest {
7+
8+
RequiredCheckTestReporter::RequiredCheckTestReporter(TestResults* results)
9+
: m_results(results)
10+
, m_throwingReporter(0)
11+
, m_continue(0)
12+
{
13+
if(m_results)
14+
{
15+
m_throwingReporter.setDecorated(m_results->m_testReporter);
16+
m_results->m_testReporter = &m_throwingReporter;
17+
}
18+
}
19+
20+
RequiredCheckTestReporter::~RequiredCheckTestReporter()
21+
{
22+
if(m_results) m_results->m_testReporter = m_throwingReporter.getDecorated();
23+
}
24+
25+
bool RequiredCheckTestReporter::next()
26+
{
27+
return m_continue++ == 0;
28+
}
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H
2+
#define UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H
3+
4+
#include "HelperMacros.h"
5+
#include "ThrowingTestReporter.h"
6+
7+
namespace UnitTest {
8+
9+
class TestResults;
10+
11+
// This RAII class decorates the current TestReporter with
12+
// a version that throws after reporting a failure.
13+
class UNITTEST_LINKAGE RequiredCheckTestReporter
14+
{
15+
public:
16+
explicit RequiredCheckTestReporter(TestResults* results);
17+
~RequiredCheckTestReporter();
18+
19+
bool next();
20+
21+
private:
22+
TestResults* m_results;
23+
ThrowingTestReporter m_throwingReporter;
24+
int m_continue;
25+
};
26+
}
27+
28+
#endif
29+

UnitTest++/TestResults.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace UnitTest {
77

8+
class RequiredCheckTestReporter;
89
class TestReporter;
910
class TestDetails;
1011

@@ -22,6 +23,9 @@ namespace UnitTest {
2223
int GetFailureCount() const;
2324

2425
private:
26+
friend class RequiredCheckTestReporter;
27+
28+
private:
2529
TestReporter* m_testReporter;
2630
int m_totalTestCount;
2731
int m_failedTestCount;

UnitTest++/ThrowingTestReporter.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "ThrowingTestReporter.h"
2+
#include "AssertException.h"
3+
4+
namespace UnitTest {
5+
6+
ThrowingTestReporter::ThrowingTestReporter(TestReporter* decoratedReporter)
7+
: m_decoratedReporter(decoratedReporter)
8+
{
9+
}
10+
11+
//virtual
12+
ThrowingTestReporter::~ThrowingTestReporter()
13+
{
14+
}
15+
16+
//virtual
17+
void ThrowingTestReporter::ReportTestStart(TestDetails const& test)
18+
{
19+
if(m_decoratedReporter) m_decoratedReporter->ReportTestStart(test);
20+
}
21+
22+
//virtual
23+
void ThrowingTestReporter::ReportFailure(TestDetails const& test, char const* failure)
24+
{
25+
if(m_decoratedReporter) m_decoratedReporter->ReportFailure(test, failure);
26+
throw AssertException();
27+
}
28+
29+
//virtual
30+
void ThrowingTestReporter::ReportTestFinish(TestDetails const& test, float secondsElapsed)
31+
{
32+
if(m_decoratedReporter) m_decoratedReporter->ReportTestFinish(test, secondsElapsed);
33+
}
34+
35+
//virtual
36+
void ThrowingTestReporter::ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed)
37+
{
38+
if(m_decoratedReporter) m_decoratedReporter->ReportSummary(totalTestCount, failedTestCount, failureCount, secondsElapsed);
39+
}
40+
41+
TestReporter* ThrowingTestReporter::getDecorated() const
42+
{
43+
return m_decoratedReporter;
44+
}
45+
46+
void ThrowingTestReporter::setDecorated(TestReporter* reporter)
47+
{
48+
m_decoratedReporter = reporter;
49+
}
50+
51+
}

UnitTest++/ThrowingTestReporter.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef UNITTEST_THROWINGTESTREPORTER_H
2+
#define UNITTEST_THROWINGTESTREPORTER_H
3+
4+
#include "TestReporter.h"
5+
6+
namespace UnitTest {
7+
8+
// A TestReporter that throws when ReportFailure is called. Otherwise it
9+
// forwards the calls to a decorated TestReporter
10+
class ThrowingTestReporter : public TestReporter
11+
{
12+
public:
13+
explicit ThrowingTestReporter(TestReporter* reporter);
14+
15+
virtual ~ThrowingTestReporter();
16+
virtual void ReportTestStart(TestDetails const& test);
17+
virtual void ReportFailure(TestDetails const& test, char const* failure);
18+
virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed);
19+
virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed);
20+
21+
TestReporter* getDecorated() const;
22+
void setDecorated(TestReporter* reporter);
23+
24+
private:
25+
TestReporter* m_decoratedReporter;
26+
};
27+
}
28+
29+
#endif

tests/TestRequireMacros.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,37 @@ TEST(RequireMacroSupportsMultipleChecksWithFailingChecks)
117117
CHECK(failure);
118118
CHECK(exception);
119119
}
120+
121+
TEST(RequireMacroDoesntExecuteCodeAfterAFailingCheck)
122+
{
123+
bool failure = false;
124+
bool exception = false;
125+
bool run = false;
126+
{
127+
RecordingReporter reporter;
128+
UnitTest::TestResults testResults(&reporter);
129+
ScopedCurrentTest scopedResults(testResults);
130+
131+
try{
132+
REQUIRE
133+
{
134+
A068 CHECK(false);
135+
run = true; // this shouldn't get executed.
136+
}
137+
}
138+
catch (const UnitTest::AssertException&)
139+
{
140+
exception = true;
141+
}
142+
143+
failure = (testResults.GetFailureCount() > 0);
144+
}
120145

146+
CHECK(failure);
147+
CHECK(exception);
148+
CHECK(!run);
149+
}
150+
121151
TEST(FailureReportsCorrectTestName)
122152
{
123153
RecordingReporter reporter;

0 commit comments

Comments
 (0)
0