Long live QVERIFY_THROWS_NO_EXCEPTION!

Counter-part to QVERIFY_THROWS_EXCEPTION.

[ChangeLog][QTest] Added QVERIFY_THROWS_NO_EXCEPTION macro.

Change-Id: Ib6a80c8e810d5e2298ff00d608dae04e7a0c3e8f
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Marc Mutz 2021-11-23 09:01:13 +01:00
parent 6a1a936537
commit ed343669f7
9 changed files with 121 additions and 15 deletions

View File

@ -93,6 +93,21 @@ do {\
#ifndef QT_NO_EXCEPTIONS
# define QVERIFY_THROWS_NO_EXCEPTION(...) \
do { \
QT_TRY { \
__VA_ARGS__; \
/* success */ \
} QT_CATCH (const std::exception &e) { \
QTest::qCaught(nullptr, e.what(), __FILE__, __LINE__); \
return; \
} QT_CATCH (...) { \
QTest::qCaught(nullptr, nullptr, __FILE__, __LINE__); \
QT_RETHROW; \
} \
} while (false) \
/* end */
#if QT_DEPRECATED_SINCE(6, 3)
namespace QTest {
QT_DEPRECATED_VERSION_X_6_3("Don't use QVERIFY_EXCEPTION_THROWN(expr, type) anymore, "
@ -126,14 +141,16 @@ inline void useVerifyThrowsException() {}
#else // QT_NO_EXCEPTIONS
/*
* The expression passed to the macro should throw an exception and we can't
* catch it because Qt has been compiled without exception support. We can't
* These macros check whether the expression passed throws exceptions, but we can't
* catch them to check because Qt has been compiled without exception support. We can't
* skip the expression because it may have side effects and must be executed.
* So, users must use Qt with exception support enabled if they use exceptions
* in their code.
*/
# define QVERIFY_THROWS_EXCEPTION(...) \
static_assert(false, "Support of exceptions is disabled")
# define QVERIFY_THROWS_NO_EXCEPTION(...) \
static_assert(false, "Support of exceptions is disabled")
#endif // !QT_NO_EXCEPTIONS

View File

@ -198,6 +198,40 @@
by the test framework.
*/
/*!
\macro QVERIFY_THROWS_NO_EXCEPTION(...)
\since 6.3
\relates QTest
The QVERIFY_THROWS_NO_EXCEPTION macro executes the expression given in its
variadic argument and tries to catch any exception thrown from the expression.
There are several different outcomes:
\list
\li If the expression does not throw an exception, then execution will continue.
\li Otherwise, if an exception derived from \c{std::exception} is caught, a failure
will be recorded in the test log and the macro returns early (implicit return from
enclosing function).
\li If an exception not derived from \c{std::exception} is caught, a failure will be
recorded in the test log and the exception will be re-thrown. This avoids problems
with e.g. pthread cancellation exceptions.
\endlist
The macro uses variadic arguments so the expression can contain commas that the
preprocessor considers argument separators, e.g. as in
\code
QVERIFY_THROWS_NO_EXCEPTION(std::pair<int, long>{42, 42L});
// macro arguments: \---- 1 ----/ \-- 2 -/ \3 /
\endcode
\note This macro can only be used in a test function that is invoked
by the test framework.
*/
/*! \macro QTRY_VERIFY_WITH_TIMEOUT(condition, timeout)
\since 5.0

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<testsuite name="tst_VerifyExceptionThrown" timestamp="@TEST_START_TIME@" hostname="@HOSTNAME@" tests="11" failures="6" errors="0" skipped="0" time="@TEST_DURATION@">
<testsuite name="tst_VerifyExceptionThrown" timestamp="@TEST_START_TIME@" hostname="@HOSTNAME@" tests="13" failures="7" errors="0" skipped="0" time="@TEST_DURATION@">
<properties>
<property name="QTestVersion" value="@INSERT_QT_VERSION_HERE@"/>
<property name="QtVersion" value="@INSERT_QT_VERSION_HERE@"/>
@ -9,6 +9,7 @@
<testcase name="testCorrectStdTypes" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@"/>
<testcase name="testCorrectStdExceptions" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@"/>
<testcase name="testCorrectMyExceptions" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@"/>
<testcase name="testCorrectNoException" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@"/>
<testcase name="testFailInt" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@">
<failure type="fail" message="Expected an exception of type double to be thrown, but caught unknown exception"/>
</testcase>
@ -27,5 +28,8 @@
<testcase name="testFailNoException" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@">
<failure type="fail" message="Expected exception of type std::exception to be thrown but no exception caught"/>
</testcase>
<testcase name="testFailNoException2" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@">
<failure type="fail" message="Expected no exception to be thrown, but caught std::exception with message This line doesn&apos;t throw"/>
</testcase>
<testcase name="cleanupTestCase" classname="tst_VerifyExceptionThrown" time="@TEST_DURATION@"/>
</testsuite>

View File

@ -19,6 +19,10 @@
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testCorrectNoException">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testFailInt">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp" line="0">
<Description><![CDATA[Expected an exception of type double to be thrown, but caught unknown exception]]></Description>
@ -55,6 +59,12 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testFailNoException2">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp" line="0">
<Description><![CDATA[Expected no exception to be thrown, but caught std::exception with message This line doesn't throw]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>

View File

@ -4,50 +4,58 @@ ok 1 - initTestCase()
ok 2 - testCorrectStdTypes()
ok 3 - testCorrectStdExceptions()
ok 4 - testCorrectMyExceptions()
not ok 5 - testFailInt()
ok 5 - testCorrectNoException()
not ok 6 - testFailInt()
---
# Expected an exception of type double to be thrown, but caught unknown exception
at: tst_VerifyExceptionThrown::testFailInt() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
not ok 6 - testFailStdString()
not ok 7 - testFailStdString()
---
# Expected an exception of type char* to be thrown, but caught unknown exception
at: tst_VerifyExceptionThrown::testFailStdString() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
not ok 7 - testFailStdRuntimeError()
not ok 8 - testFailStdRuntimeError()
---
# Expected an exception of type std::runtime_error to be thrown, but caught std::exception with message logic error
at: tst_VerifyExceptionThrown::testFailStdRuntimeError() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
not ok 8 - testFailMyException()
not ok 9 - testFailMyException()
---
# Expected an exception of type MyBaseException to be thrown, but caught std::exception with message logic error
at: tst_VerifyExceptionThrown::testFailMyException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
not ok 9 - testFailMyDerivedException()
not ok 10 - testFailMyDerivedException()
---
# Expected an exception of type std::runtime_error to be thrown, but caught std::exception with message MyDerivedException
at: tst_VerifyExceptionThrown::testFailMyDerivedException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
not ok 10 - testFailNoException()
not ok 11 - testFailNoException()
---
# Expected exception of type std::exception to be thrown but no exception caught
at: tst_VerifyExceptionThrown::testFailNoException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
ok 11 - cleanupTestCase()
1..11
# tests 11
# pass 5
# fail 6
not ok 12 - testFailNoException2()
---
# Expected no exception to be thrown, but caught std::exception with message This line doesn't throw
at: tst_VerifyExceptionThrown::testFailNoException2() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:0)
file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
line: 0
...
ok 13 - cleanupTestCase()
1..13
# tests 13
# pass 6
# fail 7

View File

@ -7,6 +7,8 @@
##teamcity[testFinished name='testCorrectStdExceptions()' flowId='tst_VerifyExceptionThrown']
##teamcity[testStarted name='testCorrectMyExceptions()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='testCorrectMyExceptions()' flowId='tst_VerifyExceptionThrown']
##teamcity[testStarted name='testCorrectNoException()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='testCorrectNoException()' flowId='tst_VerifyExceptionThrown']
##teamcity[testStarted name='testFailInt()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFailed name='testFailInt()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)|]' details='Expected an exception of type double to be thrown, but caught unknown exception' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='testFailInt()' flowId='tst_VerifyExceptionThrown']
@ -25,6 +27,9 @@
##teamcity[testStarted name='testFailNoException()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFailed name='testFailNoException()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)|]' details='Expected exception of type std::exception to be thrown but no exception caught' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='testFailNoException()' flowId='tst_VerifyExceptionThrown']
##teamcity[testStarted name='testFailNoException2()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFailed name='testFailNoException2()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)|]' details='Expected no exception to be thrown, but caught std::exception with message This line doesn|'t throw' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='testFailNoException2()' flowId='tst_VerifyExceptionThrown']
##teamcity[testStarted name='cleanupTestCase()' flowId='tst_VerifyExceptionThrown']
##teamcity[testFinished name='cleanupTestCase()' flowId='tst_VerifyExceptionThrown']
##teamcity[testSuiteFinished name='tst_VerifyExceptionThrown' flowId='tst_VerifyExceptionThrown']

View File

@ -4,6 +4,7 @@ PASS : tst_VerifyExceptionThrown::initTestCase()
PASS : tst_VerifyExceptionThrown::testCorrectStdTypes()
PASS : tst_VerifyExceptionThrown::testCorrectStdExceptions()
PASS : tst_VerifyExceptionThrown::testCorrectMyExceptions()
PASS : tst_VerifyExceptionThrown::testCorrectNoException()
FAIL! : tst_VerifyExceptionThrown::testFailInt() Expected an exception of type double to be thrown, but caught unknown exception
Loc: [qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)]
FAIL! : tst_VerifyExceptionThrown::testFailStdString() Expected an exception of type char* to be thrown, but caught unknown exception
@ -16,6 +17,8 @@ FAIL! : tst_VerifyExceptionThrown::testFailMyDerivedException() Expected an exc
Loc: [qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)]
FAIL! : tst_VerifyExceptionThrown::testFailNoException() Expected exception of type std::exception to be thrown but no exception caught
Loc: [qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)]
FAIL! : tst_VerifyExceptionThrown::testFailNoException2() Expected no exception to be thrown, but caught std::exception with message This line doesn't throw
Loc: [qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp(0)]
PASS : tst_VerifyExceptionThrown::cleanupTestCase()
Totals: 5 passed, 6 failed, 0 skipped, 0 blacklisted, 0ms
Totals: 6 passed, 7 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_VerifyExceptionThrown *********

View File

@ -21,6 +21,10 @@
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testCorrectNoException">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testFailInt">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp" line="0">
<Description><![CDATA[Expected an exception of type double to be thrown, but caught unknown exception]]></Description>
@ -57,6 +61,12 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testFailNoException2">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp" line="0">
<Description><![CDATA[Expected no exception to be thrown, but caught std::exception with message This line doesn't throw]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>

View File

@ -57,6 +57,9 @@ class tst_VerifyExceptionThrown: public QObject
Q_OBJECT
private:
void doSomething() const {}
#ifndef QT_NO_EXCEPTIONS
void throwSomething() const { throw std::logic_error("This line doesn't throw"); }
#endif
private slots:
// Remove all test cases if exceptions are not available
@ -64,6 +67,7 @@ private slots:
void testCorrectStdTypes() const;
void testCorrectStdExceptions() const;
void testCorrectMyExceptions() const;
void testCorrectNoException() const;
void testFailInt() const;
void testFailStdString() const;
@ -72,6 +76,7 @@ private slots:
void testFailMyDerivedException() const;
void testFailNoException() const;
void testFailNoException2() const;
#endif // !QT_NO_EXCEPTIONS
};
@ -148,6 +153,11 @@ void tst_VerifyExceptionThrown::testCorrectMyExceptions() const
#endif
}
void tst_VerifyExceptionThrown::testCorrectNoException() const
{
QVERIFY_THROWS_NO_EXCEPTION(doSomething());
}
void tst_VerifyExceptionThrown::testFailInt() const
{
try {
@ -182,6 +192,11 @@ void tst_VerifyExceptionThrown::testFailNoException() const
QVERIFY_THROWS_EXCEPTION(std::exception, doSomething());
}
void tst_VerifyExceptionThrown::testFailNoException2() const
{
QVERIFY_THROWS_NO_EXCEPTION(throwSomething());
}
#endif // !QT_NO_EXCEPTIONS