From 7a68264b0fe7a8da3569a31b8815b4a78b710155 Mon Sep 17 00:00:00 2001 From: Austin Gilbert Date: Mon, 8 Feb 2016 19:11:05 -0600 Subject: [PATCH 1/3] Renaming tests/TestRequireMacros.cpp -> tests/TestRequireMacrosWithExceptionsOn.cpp, testing REQUIRE with exceptions turned off will require a significantly different approach. --- ...estRequireMacros.cpp => TestRequireMacrosWithExceptionsOn.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{TestRequireMacros.cpp => TestRequireMacrosWithExceptionsOn.cpp} (100%) diff --git a/tests/TestRequireMacros.cpp b/tests/TestRequireMacrosWithExceptionsOn.cpp similarity index 100% rename from tests/TestRequireMacros.cpp rename to tests/TestRequireMacrosWithExceptionsOn.cpp From 4b0ac3f34a598fbd6ad7e0158e9663f0481ab965 Mon Sep 17 00:00:00 2001 From: Austin Gilbert Date: Mon, 8 Feb 2016 21:36:05 -0600 Subject: [PATCH 2/3] UT_RETHROW needed to take an argument when UNITTEST_NO_EXCEPTIONS=1. --- UnitTest++/ExceptionMacros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UnitTest++/ExceptionMacros.h b/UnitTest++/ExceptionMacros.h index 027a5da..c3b1e30 100644 --- a/UnitTest++/ExceptionMacros.h +++ b/UnitTest++/ExceptionMacros.h @@ -12,7 +12,7 @@ #else #define UT_TRY(x) x #define UT_THROW(x) - #define UT_RETHROW() + #define UT_RETHROW(ExceptionType) #define UT_CATCH(ExceptionType, ExceptionName, CatchBody) #define UT_CATCH_ALL(CatchBody) #endif From 2e53a17d7e85d11efeef3ca88d852d2c80b2e5b1 Mon Sep 17 00:00:00 2001 From: Austin Gilbert Date: Mon, 8 Feb 2016 21:38:56 -0600 Subject: [PATCH 3/3] With code proposed in Pull Request #95, when UNITTEST_NO_EXCEPTIONS is defined, the definition for REQUIRE macro is empty. This commit adds functionality for stopping unit tests early when UNITTEST_NO_EXCEPTIONS is defined via std::longjmp. --- UnitTest++/RequireMacros.h | 8 +- UnitTest++/ThrowingTestReporter.cpp | 12 +- tests/TestRequireMacrosWithExceptionsOff.cpp | 738 +++++++++++++++++++ 3 files changed, 750 insertions(+), 8 deletions(-) create mode 100644 tests/TestRequireMacrosWithExceptionsOff.cpp diff --git a/UnitTest++/RequireMacros.h b/UnitTest++/RequireMacros.h index ea1f6b9..0830e99 100644 --- a/UnitTest++/RequireMacros.h +++ b/UnitTest++/RequireMacros.h @@ -7,12 +7,6 @@ #error UnitTest++ redefines REQUIRE #endif -#ifndef UNITTEST_NO_EXCEPTIONS - #define REQUIRE for(UnitTest::RequiredCheckTestReporter decoratedReporter(*UnitTest::CurrentTest::Results()); decoratedReporter.Next(); ) -#endif +#define REQUIRE for(UnitTest::RequiredCheckTestReporter decoratedReporter(*UnitTest::CurrentTest::Results()); decoratedReporter.Next(); ) -#ifdef UNITTEST_NO_EXCEPTIONS - #define REQUIRE #endif - -#endif \ No newline at end of file diff --git a/UnitTest++/ThrowingTestReporter.cpp b/UnitTest++/ThrowingTestReporter.cpp index 672f042..4e56149 100644 --- a/UnitTest++/ThrowingTestReporter.cpp +++ b/UnitTest++/ThrowingTestReporter.cpp @@ -1,6 +1,10 @@ #include "ThrowingTestReporter.h" #include "RequiredCheckException.h" +#ifdef UNITTEST_NO_EXCEPTIONS +#include "ReportAssertImpl.h" +#endif + namespace UnitTest { ThrowingTestReporter::ThrowingTestReporter(TestReporter* decoratedReporter) @@ -27,7 +31,13 @@ namespace UnitTest { { m_decoratedReporter->ReportFailure(test, failure); } - throw RequiredCheckException(); + + #ifndef UNITTEST_NO_EXCEPTIONS + throw RequiredCheckException(); + #else + static const int stopTest = 1; + UNITTEST_LONGJMP(*UnitTest::Detail::GetAssertJmpBuf(), stopTest); + #endif } //virtual diff --git a/tests/TestRequireMacrosWithExceptionsOff.cpp b/tests/TestRequireMacrosWithExceptionsOff.cpp new file mode 100644 index 0000000..d43fbc1 --- /dev/null +++ b/tests/TestRequireMacrosWithExceptionsOff.cpp @@ -0,0 +1,738 @@ +#include "UnitTest++/UnitTestPP.h" +#include "UnitTest++/CurrentTest.h" +#include "RecordingReporter.h" +#include "ScopedCurrentTest.h" + +#include + +using namespace std; + +#ifdef UNITTEST_NO_EXCEPTIONS + +// NOTE: unit tests here use a work around for std::longjmp +// taking us out of the current running unit test. We use a +// follow on test to check the previous test exhibited correct +// behavior. + +namespace { + + static RecordingReporter reporter; + static std::string testName; + static bool next = false; + static int line = 0; + + // Use destructor to reset our globals + struct DoValidationOn + { + ~DoValidationOn() + { + testName = ""; + next = false; + line = 0; + + reporter.lastFailedLine = 0; + memset(reporter.lastFailedTest, 0, sizeof(reporter.lastFailedTest)); + memset(reporter.lastFailedSuite, 0, sizeof(reporter.lastFailedSuite)); + memset(reporter.lastFailedFile, 0, sizeof(reporter.lastFailedFile)); + } + }; + + TEST(RequireCheckSucceedsOnTrue) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK(true); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireCheckSucceedsOnTrue_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckFailsOnFalse) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK(false); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckFailsOnFalse_FollowOn) + { + CHECK(!next); + } + + TEST(RequireMacroSupportsMultipleChecks) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,1); + } + + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroSupportsMultipleChecks_FollowOn) + { + CHECK(next); + } + + TEST(RequireMacroSupportsMultipleChecksWithFailingChecks) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,2); + } + + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroSupportsMultipleChecksWithFailingChecks_FollowOn) + { + CHECK(!next); + } + + TEST(RequireMacroDoesntExecuteCodeAfterAFailingCheck) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(false); + next = true; + } + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroDoesntExecuteCodeAfterAFailingCheck_FollowOn) + { + CHECK(!next); + } + + TEST(FailureReportsCorrectTestName) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + testName = m_details.testName; + REQUIRE CHECK(false); + } + } + + TEST_FIXTURE(DoValidationOn, FailureReportsCorrectTestName_FollowOn) + { + CHECK_EQUAL(testName, reporter.lastFailedTest); + } + + TEST(RequiredCheckFailureIncludesCheckContents) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + testName = m_details.testName; + const bool yaddayadda = false; + + REQUIRE CHECK(yaddayadda); + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckFailureIncludesCheckContents_FollowOn) + { + CHECK(strstr(reporter.lastFailedMessage, "yaddayadda")); + } + + TEST(RequiredCheckEqualSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1,1); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckEqualFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1, 2); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualFailsOnNotEqual_FollowOn) + { +// TODO: check reporter last test name + CHECK(!next); + } + + TEST(RequiredCheckEqualFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails const testDetails("testName", "suiteName", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + line = __LINE__; REQUIRE CHECK_EQUAL(1, 123); + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualFailureContainsCorrectDetails_FollowOn) + { + CHECK_EQUAL("testName", reporter.lastFailedTest); + CHECK_EQUAL("suiteName", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + int g_sideEffect = 0; + int FunctionWithSideEffects() + { + ++g_sideEffect; + return 1; + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1, FunctionWithSideEffects()); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(2, FunctionWithSideEffects()); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE(1.0f, 1.001f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE (1.0f, 1.1f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("test", "suite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + line = __LINE__; REQUIRE CHECK_CLOSE(1.0f, 1.1f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK_EQUAL("test", reporter.lastFailedTest); + CHECK_EQUAL("suite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + + CHECK(!next); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE (1, FunctionWithSideEffects(), 0.1f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE(2, FunctionWithSideEffects(), 0.1f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseDoesNotHaveSideEffectsWhenFailingOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckArrayCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + const float data[4] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, data, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArrayCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckArrayCloseFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE(data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("arrayCloseTest", "arrayCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + line = __LINE__; REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArrayCloseFailureIncludesTolerance) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[4] = { 0, 1, 2, 3 }; + float const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureIncludesTolerance_FollowOn) + { + CHECK(!next); + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + TEST(RequiredCheckArrayEqualSuceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[4] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data, data, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualSuceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArrayEqualFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailsOnNotEqual) + { + CHECK(!next); + } + + TEST(RequiredCheckArrayEqualFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayEqualFailureContainsCorrectInfo) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + line = __LINE__; REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailureContainsCorrectInfo_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("RequiredCheckArrayEqualFailureContainsCorrectInfo", reporter.lastFailedTest); + CHECK_EQUAL(__FILE__, reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + float const* FunctionWithSideEffects2() + { + ++g_sideEffect; + static float const data[] = { 0, 1, 2, 3}; + return data; + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckArray2DCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE(data, data, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArray2DCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ [ 0 1 ] [ 2 3 ] ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ [ 0 1 ] [ 3 3 ] ]")); + } + + TEST(RequiredCheckArray2DCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("array2DCloseTest", "array2DCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + line = __LINE__; REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesTolerance) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[2][2] = { {0, 1}, {2, 3} }; + float const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureIncludesTolerance_FollowOn) + { + CHECK(!next); + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + float const* const* FunctionWithSideEffects3() + { + ++g_sideEffect; + static float const data1[] = {0,1}; + static float const data2[] = {2,3}; + static const float* const data[] = {data1, data2}; + return data; + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK(next); + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK(!next); + CHECK_EQUAL(1, g_sideEffect); + } +} + +#endif