diff --git a/test/fixture.cpp b/test/fixture.cpp index 3a4b685466a..f82c6ca3630 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -169,6 +169,7 @@ void TestFixture::assert_(const char * const filename, const unsigned int linenr errmsg << getLocationStr(filename, linenr) << ": Assertion failed." << std::endl << "_____" << std::endl; if (!msg.empty()) errmsg << "Hint:" << std::endl << msg << std::endl; + throw AssertFailedError(); } } @@ -183,6 +184,7 @@ void TestFixture::assertFailure(const char* const filename, const unsigned int l if (!msg.empty()) errmsg << "Hint:" << std::endl << msg << std::endl; errmsg << "_____" << std::endl; + throw AssertFailedError(); } void TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const std::string &expected, const std::string &actual, const std::string &msg) const @@ -289,6 +291,7 @@ void TestFixture::assertThrow(const char * const filename, const unsigned int li ++fails_counter; errmsg << getLocationStr(filename, linenr) << ": Assertion succeeded. " << "The expected exception was thrown" << std::endl << "_____" << std::endl; + throw AssertFailedError(); } void TestFixture::assertThrowFail(const char * const filename, const unsigned int linenr) const @@ -296,18 +299,20 @@ void TestFixture::assertThrowFail(const char * const filename, const unsigned in ++fails_counter; errmsg << getLocationStr(filename, linenr) << ": Assertion failed. " << "The expected exception was not thrown" << std::endl << "_____" << std::endl; + throw AssertFailedError(); } -void TestFixture::assertNoThrowFail(const char * const filename, const unsigned int linenr) const +void TestFixture::assertNoThrowFail(const char * const filename, const unsigned int linenr, bool bailout) const { - ++fails_counter; - std::string ex_msg; try { // cppcheck-suppress rethrowNoCurrentException throw; } + catch (const AssertFailedError&) { + return; + } catch (const InternalError& e) { ex_msg = e.errorMessage; } @@ -318,8 +323,11 @@ void TestFixture::assertNoThrowFail(const char * const filename, const unsigned ex_msg = "unknown exception"; } + ++fails_counter; errmsg << getLocationStr(filename, linenr) << ": Assertion failed. " << "Unexpected exception was thrown: " << ex_msg << std::endl << "_____" << std::endl; + if (bailout) + throw AssertFailedError(); } void TestFixture::printHelp() diff --git a/test/fixture.h b/test/fixture.h index c57ae715320..b6302aa14b2 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -22,6 +22,7 @@ #include "check.h" #include "color.h" +#include "config.h" #include "errorlogger.h" #include "platform.h" #include "settings.h" @@ -29,6 +30,7 @@ #include #include +#include #include #include #include @@ -68,6 +70,8 @@ class TestFixture : public ErrorLogger { virtual void teardownTestInternal() {} std::string getLocationStr(const char * filename, unsigned int linenr) const; + class AssertFailedError : public std::exception {}; + void assert_(const char * filename, unsigned int linenr, bool condition, const std::string& msg = "") const; template @@ -112,9 +116,9 @@ class TestFixture : public ErrorLogger { const char current[], const std::string &actual) const; void todoAssertEquals(const char * filename, unsigned int linenr, long long wanted, long long current, long long actual) const; - void assertThrow(const char * filename, unsigned int linenr) const; - void assertThrowFail(const char * filename, unsigned int linenr) const; - void assertNoThrowFail(const char * filename, unsigned int linenr) const; + NORETURN void assertThrow(const char * filename, unsigned int linenr) const; + NORETURN void assertThrowFail(const char * filename, unsigned int linenr) const; + void assertNoThrowFail(const char * filename, unsigned int linenr, bool bailout) const; static std::string deleteLineNumber(const std::string &message); void setVerbose(bool v) { @@ -278,7 +282,7 @@ class TestFixture : public ErrorLogger { private: //Helper function to be called when an assertEquals assertion fails. //Writes the appropriate failure message to errmsg and increments fails_counter - void assertFailure(const char* filename, unsigned int linenr, const std::string& expected, const std::string& actual, const std::string& msg) const; + NORETURN void assertFailure(const char* filename, unsigned int linenr, const std::string& expected, const std::string& actual, const std::string& msg) const; std::ostringstream mOutput; std::ostringstream mErrout; @@ -308,14 +312,13 @@ class TestInstance { std::unique_ptr impl; }; -#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); try { NAME(); teardownTest(); } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } } while (false) +#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); try { NAME(); teardownTest(); } catch (const AssertFailedError&) {} catch (...) { assertNoThrowFail(__FILE__, __LINE__, false); } } } while (false) -// TODO: the asserts do not actually assert i.e. do stop executing the test #define ASSERT( CONDITION ) assert_(__FILE__, __LINE__, (CONDITION)) #define ASSERT_LOC( CONDITION, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION)) #define ASSERT_LOC_MSG( CONDITION, MSG, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION), MSG) // *INDENT-OFF* -#define ASSERT_EQUALS( EXPECTED, ACTUAL ) do { try { assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)); } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_EQUALS( EXPECTED, ACTUAL ) do { try { assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)); } catch(const AssertFailedError&) { throw; } catch (...) { assertNoThrowFail(__FILE__, __LINE__, true); } } while (false) // *INDENT-ON* #define ASSERT_EQUALS_WITHOUT_LINENUMBERS( EXPECTED, ACTUAL ) assertEqualsWithoutLineNumbers(__FILE__, __LINE__, EXPECTED, ACTUAL) #define ASSERT_EQUALS_DOUBLE( EXPECTED, ACTUAL, TOLERANCE ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL, TOLERANCE) @@ -327,15 +330,17 @@ class TestInstance { #define ASSERT_EQUALS_ENUM_LOC_MSG( EXPECTED, ACTUAL, MSG, FILE_, LINE_ ) assertEqualsEnum(FILE_, LINE_, (EXPECTED), (ACTUAL), MSG) #define TODO_ASSERT_EQUALS_ENUM( WANTED, CURRENT, ACTUAL ) todoAssertEqualsEnum(__FILE__, __LINE__, WANTED, CURRENT, ACTUAL) #define ASSERT_THROW_EQUALS( CMD, EXCEPTION, EXPECTED ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&e) { assertEquals(__FILE__, __LINE__, EXPECTED, e.errorMessage); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) -#define ASSERT_THROW_EQUALS_2( CMD, EXCEPTION, EXPECTED ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&e) { assertEquals(__FILE__, __LINE__, EXPECTED, e.what()); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) -#define ASSERT_THROW_INTERNAL( CMD, TYPE ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const InternalError& e) { assertEqualsEnum(__FILE__, __LINE__, InternalError::TYPE, e.type); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) -#define ASSERT_THROW_INTERNAL_EQUALS( CMD, TYPE, EXPECTED ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const InternalError& e) { assertEqualsEnum(__FILE__, __LINE__, InternalError::TYPE, e.type); assertEquals(__FILE__, __LINE__, EXPECTED, e.errorMessage); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) -#define ASSERT_NO_THROW( CMD ) do { try { (void)(CMD); } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while (false) -#define TODO_ASSERT_THROW( CMD, EXCEPTION ) do { try { (void)(CMD); } catch (const EXCEPTION&) {} catch (...) { assertThrow(__FILE__, __LINE__); } } while (false) +#define ASSERT_THROW_EQUALS_2( CMD, EXCEPTION, EXPECTED ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const AssertFailedError&) { throw; } catch (const EXCEPTION&e) { assertEquals(__FILE__, __LINE__, EXPECTED, e.what()); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_THROW_INTERNAL( CMD, TYPE ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const AssertFailedError&) { throw; } catch (const InternalError& e) { assertEqualsEnum(__FILE__, __LINE__, InternalError::TYPE, e.type); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_THROW_INTERNAL_EQUALS( CMD, TYPE, EXPECTED ) do { try { (void)(CMD); assertThrowFail(__FILE__, __LINE__); } catch (const AssertFailedError&) { throw; } catch (const InternalError& e) { assertEqualsEnum(__FILE__, __LINE__, InternalError::TYPE, e.type); assertEquals(__FILE__, __LINE__, EXPECTED, e.errorMessage); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_NO_THROW( CMD ) do { try { (void)(CMD); } catch (const AssertFailedError&) { throw; } catch (...) { assertNoThrowFail(__FILE__, __LINE__, true); } } while (false) +#define TODO_ASSERT_THROW( CMD, EXCEPTION ) do { try { (void)(CMD); } catch (const AssertFailedError&) { throw; } catch (const EXCEPTION&) {} catch (...) { assertThrow(__FILE__, __LINE__); } } while (false) #define TODO_ASSERT( CONDITION ) do { const bool condition=(CONDITION); todoAssertEquals(__FILE__, __LINE__, true, false, condition); } while (false) #define TODO_ASSERT_EQUALS( WANTED, CURRENT, ACTUAL ) todoAssertEquals(__FILE__, __LINE__, WANTED, CURRENT, ACTUAL) +// *INDENT-OFF* #define REGISTER_TEST( CLASSNAME ) namespace { class CLASSNAME ## Instance : public TestInstance { public: CLASSNAME ## Instance() : TestInstance(#CLASSNAME) {} TestFixture* create() override { impl.reset(new CLASSNAME); return impl.get(); } }; CLASSNAME ## Instance instance_ ## CLASSNAME; } +// *INDENT-ON* #define PLATFORM( P, T ) do { std::string errstr; assertEquals(__FILE__, __LINE__, true, P.set(Platform::toString(T), errstr, {exename}), errstr); } while (false)