How to prevent qFatal () from abandoning the application?
My Qt application uses Q_ASSERT_X which calls qFatal () which (by default) aborts the application. This works great for an application, but I would like to suppress this behavior when unit testing the application. (I am using Google Test Framework .) I have unit tests in a separate project statically linked to the class under test, the documentation for qFatal () reads:
Calls the message handler using the fatal message msg. If no message handler has been installed, the message is printed to stderr. On Windows, the message is sent to the debugger.
If you are using the default message handler, this function will be interrupted by Unix to create a kernel dump. On Windows, for a debug build, this function will report _CRT_ERROR allowing you to attach a debugger to your application.
...
To suppress output at runtime, install your own message handler using qInstallMsgHandler ().
So here is my main.cpp file:
#include <gtest/gtest.h>
#include <QApplication>
void testMessageOutput(QtMsgType type, const char *msg) {
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s\n", msg);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s\n", msg);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s\n", msg);
break;
case QtFatalMsg:
fprintf(stderr, "My Fatal: %s\n", msg);
break;
}
}
int main(int argc, char **argv)
{
qInstallMsgHandler(testMessageOutput);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
But my application still stops at assert. I can tell my custom handler is being called because the output when running my tests is:
My Fatal: ASSERT error in MyClass :: doSomething: "doSomething ()", file myclass.cpp, line 21 The program terminated unexpectedly.
What can I do to get my tests to keep running even when the assertion fails?
a source to share
At least for Qt-4.6.2 there is nothing you can do.
src/corelib/global/qglobal.cpp
defines void qt_message_output(QtMsgType msgType, const char *buf)
which first checks if the handler is installed. If so, it calls it, otherwise it uses the default handlers. It almost always interrupts (Unix / MingWn) or calls exit (others) right after that.
I haven't been able to find a browser for the current source code on the internet, but the Qt-4.2.2 source code is mostly identical and should give you an idea of what's going on.
a source to share
Q_ASSERT_X does not compile anything when creating an assembly.
So, for unit testing, do a release build and it won't call qFatal.
a source to share
In some cases, you cannot stop qFatal and continue silently, the checked component may be in such a state that the crash will occur after a few lines anyway. One way to avoid this might be to stub qFatal somewhere in your test code;)
void qFatal(const char *msg, ...)
{
QT_THROW(std::some_exception);
}
Then you can have your own assert macro:
#define CUSTOM_QEXPECT_FAIL( method ) { bool failed = false;\
try { \
method ; \
}\
catch(...) { \
failed = true; \
} \
QVERIFY(failed); }
And use it in your code like:
CUSTOM_QEXPECT_FAIL( testedObj->panicAtTheDisco() );
Not to say that this is somehow a good approach, just trying to prove that something can be done for the problem.
Addition, I didn't read carefully enough that you are statically linking to the class under test. In this case, Stubbing doesn't work only if you build it into your test executable.
a source to share