#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