QVERIFY_EXCEPTION_THROWN: re-throw unknown exceptions

Swallowing unknown exceptions is dangerous business, as the exception
might be a pthread cancellation token, the swallowing of which would
terminate the program.

Instead of returning from the catch-all-clause, therefore, re-throw
the unknown exception.

Fix tst_verifyexceptionthrown failure cases that use
non-std::exception-derived true negative exceptions to not let the
exception escape from the test function.

As a drive-by, pretty up the macro's docs.

[ChangeLog][QtTest][QVERIFY_EXCEPTION_THROWN] Now re-throws unknown
exceptions (= not derived from std::exception) (was: swallowed them
and returned from the test function), in order to play nice with
pthread cancellation.

Pick-to: 6.2 5.15
Change-Id: Ic036d4a9ed4b7683fa67e27af8bcbae0eefdd0da
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Marc Mutz 2021-08-27 16:53:35 +02:00 committed by Marc Mutz
parent 8761208aef
commit f4e89d58da
3 changed files with 26 additions and 12 deletions

View File

@ -102,6 +102,7 @@ do {\
" but no exception caught", __FILE__, __LINE__);\
return;\
} QT_CATCH (const exceptiontype &) {\
/* success */\
}\
} QT_CATCH (const std::exception &e) {\
QByteArray msg = QByteArray() + "Expected exception of type " #exceptiontype \
@ -111,7 +112,7 @@ do {\
} QT_CATCH (...) {\
QTest::qFail("Expected exception of type " #exceptiontype " to be thrown" \
" but unknown exception caught", __FILE__, __LINE__);\
return;\
QT_RETHROW;\
}\
} while (false)

View File

@ -159,15 +159,24 @@
\relates QTest
The QVERIFY_EXCEPTION_THROWN macro executes an \a expression and tries
to catch an exception thrown from the \a expression. If the \a expression
throws an exception and its type is the same as \a exceptiontype
or \a exceptiontype is substitutable with the type of thrown exception
(i.e. usually the type of thrown exception is publicly derived
from \a exceptiontype) then execution will be continued. If not-substitutable
type of exception is thrown or the \a expression doesn't throw an exception
at all, then a failure will be recorded in the test log and
the test won't be executed further.
The QVERIFY_EXCEPTION_THROWN macro executes \a expression
and tries to catch an exception thrown from \a expression.
There are several possible outcomes:
\list
\li If \a expression throws an exception that is either the same as
\a exceptiontype or derived from \a exceptiontype, then execution will continue.
\li Otherwise, if \a expression throws no exception, or the
exception thrown derives from \c{std::exception}, then a failure
will be recorded in the test log and the macro returns early
(from enclosing function).
\li If the thrown exception derives neither from \c{std::exception} nor from
\a exceptiontype, a failure will be recorded in the test log, and the exception is
re-thrown. This avoids problems with e.g. pthread cancellation exceptions.
\endlist
\note This macro can only be used in a test function that is invoked
by the test framework.

View File

@ -112,12 +112,16 @@ void tst_VerifyExceptionThrown::testCorrectMyExceptions() const
void tst_VerifyExceptionThrown::testFailInt() const
{
QVERIFY_EXCEPTION_THROWN(throw int(5), double);
try {
QVERIFY_EXCEPTION_THROWN(throw int(5), double);
} catch (int) {}
}
void tst_VerifyExceptionThrown::testFailStdString() const
{
QVERIFY_EXCEPTION_THROWN(throw std::string("some string"), char*);
try {
QVERIFY_EXCEPTION_THROWN(throw std::string("some string"), char*);
} catch (const std::string &) {}
}
void tst_VerifyExceptionThrown::testFailStdRuntimeError() const