4#include <QtTest/private/qtestresult_p.h>
5#include <QtCore/qglobal.h>
6#include <QtCore/qmutex.h>
7#include <QtCore/qstringview.h>
9#include <QtTest/private/qtestlog_p.h>
10#include <QtTest/qtest.h>
11#include <QtTest/qtestdata.h>
12#include <QtTest/qtestcase.h>
13#include <QtTest/qtestassert.h>
14#include <QtTest/qtesteventloop.h>
18#include <QtCore/q26numeric.h>
36 static const bool fatalFailure = []() {
37 static const char *
const environmentVar =
"QTEST_FATAL_FAIL";
38 if (!qEnvironmentVariableIsSet(environmentVar))
42 const int fatal = qEnvironmentVariableIntValue(environmentVar, &ok);
46 if (failed && fatalFailure)
85 delete[] std::exchange(dest, src ? qstrdup(src) :
nullptr);
94 const char *objectName = QTestResult::currentTestObjectName();
95 const char *testFunc = QTestResult::currentTestFunction();
96 const char *dataTag = QTestResult::currentDataTag();
97 const char *globalDataTag = QTestResult::currentGlobalDataTag();
99 const QMutexLocker locker(&identifierMutex);
108
109
110
111
113QTestResult::IdentifierLocker::IdentifierLocker()
115 QTest::identifierMutex.lock();
118QTestResult::IdentifierLocker::~IdentifierLocker()
120 QTest::identifierMutex.unlock();
123const char *QTestResult::IdentifierLocker::objectName()
const
125 return QTest::identifierObjectName;
128const char *QTestResult::IdentifierLocker::testFunction()
const
130 return QTest::identifierTestFunc;
133const char *QTestResult::IdentifierLocker::dataTag()
const
135 return QTest::identifierDataTag;
138const char *QTestResult::IdentifierLocker::globalDataTag()
const
140 return QTest::identifierGlobalDataTag;
143void QTestResult::reset()
145 QTest::currentTestData =
nullptr;
146 QTest::currentGlobalTestData =
nullptr;
147 QTest::currentTestFunc =
nullptr;
148 QTest::currentTestObjectName =
nullptr;
149 QTest::updateIdentifier();
150 QTest::resetFailed();
152 QTest::expectFailComment =
nullptr;
153 QTest::expectFailMode = 0;
154 QTest::blacklistCurrentTest =
false;
156 QTestLog::resetCounters();
159void QTestResult::setBlacklistCurrentTest(
bool b)
161 QTest::blacklistCurrentTest = b;
164bool QTestResult::currentTestFailed()
166 return QTest::hasFailed();
169QTestData *QTestResult::currentGlobalTestData()
171 return QTest::currentGlobalTestData;
174QTestData *QTestResult::currentTestData()
176 return QTest::currentTestData;
179void QTestResult::setCurrentGlobalTestData(QTestData *data)
181 QTest::currentGlobalTestData = data;
182 QTest::updateIdentifier();
185void QTestResult::setCurrentTestData(QTestData *data)
187 QTest::currentTestData = data;
188 QTest::updateIdentifier();
189 QTest::resetFailed();
191 QTestLog::enterTestData(data);
194void QTestResult::setCurrentTestFunction(
const char *func)
196 QTest::currentTestFunc = func;
197 QTest::updateIdentifier();
198 QTest::resetFailed();
200 QTestLog::enterTestFunction(func);
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226void QTestResult::finishedCurrentTestData()
228 if (QTest::expectFailMode)
229 addFailure(
"QEXPECT_FAIL was called without any subsequent verification statements");
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249void QTestResult::finishedCurrentTestDataCleanup()
251 if (!QTest::hasFailed() && QTestLog::unhandledIgnoreMessages()) {
252 QTestLog::printUnhandledIgnoreMessages();
253 addFailure(
"Not all expected messages were received");
257 if (!QTest::hasFailed() && !QTest::skipCurrentTest) {
258 if (QTest::blacklistCurrentTest)
259 QTestLog::addBPass(
"");
261 QTestLog::addPass(
"");
264 QTestLog::clearCurrentTestState();
265 QTest::resetFailed();
269
270
271
272
273
274
275
276void QTestResult::finishedCurrentTestFunction()
278 QTestLog::clearCurrentTestState();
279 QTestLog::leaveTestFunction();
281 QTest::currentTestFunc =
nullptr;
282 QTest::resetFailed();
285const char *QTestResult::currentTestFunction()
287 return QTest::currentTestFunc;
290const char *QTestResult::currentDataTag()
292 return QTest::currentTestData ? QTest::currentTestData->dataTag() :
nullptr;
295const char *QTestResult::currentGlobalDataTag()
297 return QTest::currentGlobalTestData ? QTest::currentGlobalTestData->dataTag() :
nullptr;
302 if (!dataIndex || dataIndex[0] ==
'\0')
304 if (!QTest::currentTestData)
306 if (strcmp(dataIndex, QTest::currentTestData->dataTag()) == 0)
311bool QTestResult::expectFail(
const char *dataIndex,
const char *comment,
312 QTest::TestFailMode mode,
const char *file,
int line)
314 QTEST_ASSERT(comment);
315 QTEST_ASSERT(mode > 0);
317 if (!isExpectFailData(dataIndex)) {
322 if (QTest::expectFailMode) {
324 addFailure(
"Already expecting a fail", file, line);
328 QTest::expectFailMode = mode;
329 QTest::expectFailComment = comment;
333static bool checkStatement(
bool statement,
const char *msg,
const char *file,
int line)
337 if (QTest::blacklistCurrentTest)
338 QTestLog::addBXPass(msg, file, line);
340 QTestLog::addXPass(msg, file, line);
344 bool doContinue = (QTest::expectFailMode == QTest::Continue);
352 if (QTest::blacklistCurrentTest)
353 QTestLog::addBXFail(QTest::expectFailComment, file, line);
355 QTestLog::addXFail(QTest::expectFailComment, file, line);
356 bool doContinue = (QTest::expectFailMode == QTest::Continue);
361 QTestResult::addFailure(msg, file, line);
365void QTestResult::fail(
const char *msg,
const char *file,
int line)
367 checkStatement(
false, msg, file, line);
376bool QTestResult::verify(
bool statement,
const char *statementStr,
377 const char *description,
const char *file,
int line)
379 QTEST_ASSERT(statementStr);
381 Q_DECL_UNINITIALIZED
char msg[maxMsgLen];
384 if (QTestLog::verboseLevel() >= 2) {
385 std::snprintf(msg, maxMsgLen,
"QVERIFY(%s)", statementStr);
386 QTestLog::info(msg, file, line);
389 if (statement == !!QTest::expectFailMode) {
390 std::snprintf(msg, maxMsgLen,
391 statement ?
"'%s' returned TRUE unexpectedly. (%s)" :
"'%s' returned FALSE. (%s)",
392 statementStr, description ? description :
"");
395 return checkStatement(statement, msg, file, line);
401 case QTest::ComparisonOperation::CustomCompare:
403 case QTest::ComparisonOperation::ThreeWayCompare:
405 case QTest::ComparisonOperation::Equal:
406 case QTest::ComparisonOperation::NotEqual:
407 case QTest::ComparisonOperation::LessThan:
408 case QTest::ComparisonOperation::LessThanOrEqual:
409 case QTest::ComparisonOperation::GreaterThan:
410 case QTest::ComparisonOperation::GreaterThanOrEqual:
413 Q_UNREACHABLE_RETURN(
"");
419 case QTest::ComparisonOperation::CustomCompare:
421 case QTest::ComparisonOperation::ThreeWayCompare:
423 case QTest::ComparisonOperation::Equal:
424 case QTest::ComparisonOperation::NotEqual:
425 case QTest::ComparisonOperation::LessThan:
426 case QTest::ComparisonOperation::LessThanOrEqual:
427 case QTest::ComparisonOperation::GreaterThan:
428 case QTest::ComparisonOperation::GreaterThanOrEqual:
431 Q_UNREACHABLE_RETURN(
"");
436 std::mbstate_t state = {};
439 auto r = std::mbsrtowcs(
nullptr, &s, INT_MAX, &state);
442 return q26::saturating_cast<
int>(r);
448 const char *failureMsg,
449 const char *val1,
const char *val2,
450 const char *actual,
const char *expected,
451 QTest::ComparisonOperation op)
455 const int written = std::snprintf(msg, maxMsgLen,
"%s\n", failureMsg);
457 maxMsgLen -= written;
459 const auto protect = [](
const char *s) {
return s ? s :
"<null>"; };
462 std::snprintf(msg, maxMsgLen,
" %s(%s)%*s %s\n %s(%s)%*s %s",
463 leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1,
":",
465 rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1,
":",
469 std::snprintf(msg, maxMsgLen,
" %s: %s\n %s: %s",
470 leftArgNameForOp(op), actual, rightArgNameForOp(op), expected);
476 const char *actual,
const char *expected,
477 const char *actualExpr,
const char *expectedExpr)
479 formatFailMessage(msg, maxMsgLen,
"Comparison failed!",
480 actual, expected, actualExpr, expectedExpr,
481 QTest::ComparisonOperation::CustomCompare);
486template <
class Actual,
class Expected>
489 const char *failureMsg,
490 const Actual &val1,
const Expected &val2,
491 const char *actual,
const char *expected,
492 QTest::ComparisonOperation op)
494 const char *val1S = QTest::toString(val1);
495 const char *val2S = QTest::toString(val2);
497 formatFailMessage(msg, maxMsgLen, failureMsg, val1S, val2S, actual, expected, op);
503template <
class Actual,
class Expected>
505 const Actual &val1,
const Expected &val2,
506 const char *actual,
const char *expected,
507 const char *file,
int line,
508 bool hasValues =
true)
510 Q_DECL_UNINITIALIZED
char msg[maxMsgLen];
513 QTEST_ASSERT(expected);
514 QTEST_ASSERT(actual);
516 if (QTestLog::verboseLevel() >= 2) {
517 std::snprintf(msg, maxMsgLen,
"QCOMPARE(%s, %s)", actual, expected);
518 QTestLog::info(msg, file, line);
522 failureMsg =
"Compared values are not the same";
526 std::snprintf(msg, maxMsgLen,
527 "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected);
529 return checkStatement(success, msg, file, line);
534 std::snprintf(msg, maxMsgLen,
"%s", failureMsg);
535 return checkStatement(success, msg, file, line);
538 formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected,
539 QTest::ComparisonOperation::CustomCompare);
541 return checkStatement(success, msg, file, line);
548 const char *actual,
const char *expected,
549 const char *file,
int line)
551 const size_t maxMsgLen = 1024;
552 Q_DECL_UNINITIALIZED
char msg[maxMsgLen];
555 QTEST_ASSERT(expected);
556 QTEST_ASSERT(actual);
558 QTEST_ASSERT(success || failureMsg);
560 if (QTestLog::verboseLevel() >= 2) {
561 std::snprintf(msg, maxMsgLen,
"QCOMPARE(%s, %s)", actual, expected);
562 QTestLog::info(msg, file, line);
567 std::snprintf(msg, maxMsgLen,
"QCOMPARE(%s, %s) returned TRUE unexpectedly.",
570 return checkStatement(success, msg, file, line);
576bool QTestResult::compare(
bool success,
const char *failureMsg,
577 char *val1,
char *val2,
578 const char *actual,
const char *expected,
579 const char *file,
int line)
581 const bool result = compareHelper(success, failureMsg,
582 val1 !=
nullptr ? val1 :
"<null>",
583 val2 !=
nullptr ? val2 :
"<null>",
584 actual, expected, file, line,
585 val1 !=
nullptr && val2 !=
nullptr);
594bool QTestResult::compare(
bool success,
const char *failureMsg,
595 double val1,
double val2,
596 const char *actual,
const char *expected,
597 const char *file,
int line)
599 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
602bool QTestResult::compare(
bool success,
const char *failureMsg,
603 float val1,
float val2,
604 const char *actual,
const char *expected,
605 const char *file,
int line)
607 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
610bool QTestResult::compare(
bool success,
const char *failureMsg,
612 const char *actual,
const char *expected,
613 const char *file,
int line)
615 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
618#if QT_POINTER_SIZE == 8
619bool QTestResult::compare(
bool success,
const char *failureMsg,
620 qsizetype val1, qsizetype val2,
621 const char *actual,
const char *expected,
622 const char *file,
int line)
624 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
628bool QTestResult::compare(
bool success,
const char *failureMsg,
629 unsigned val1,
unsigned val2,
630 const char *actual,
const char *expected,
631 const char *file,
int line)
633 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
636bool QTestResult::compare(
bool success,
const char *failureMsg,
637 QStringView val1, QStringView val2,
638 const char *actual,
const char *expected,
639 const char *file,
int line)
641 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
644bool QTestResult::compare(
bool success,
const char *failureMsg,
645 QStringView val1,
const QLatin1StringView &val2,
646 const char *actual,
const char *expected,
647 const char *file,
int line)
649 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
652bool QTestResult::compare(
bool success,
const char *failureMsg,
653 const QLatin1StringView & val1, QStringView val2,
654 const char *actual,
const char *expected,
655 const char *file,
int line)
657 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
662bool QTestResult::compare(
bool success,
const char *failureMsg,
663 const char *actual,
const char *expeceted,
664 const char *file,
int line)
666 return compareHelper(success, failureMsg, actual, expeceted, file, line);
669void QTestResult::addFailure(
const char *message,
const char *file,
int line)
672 if (qApp && QThread::currentThread() == qApp->thread())
673 QTestEventLoop::instance().exitLoop();
675 if (QTest::blacklistCurrentTest)
676 QTestLog::addBFail(message, file, line);
678 QTestLog::addFail(message, file, line);
679 QTest::setFailed(
true);
682void QTestResult::addSkip(
const char *message,
const char *file,
int line)
686 QTestLog::addSkip(message, file, line);
689void QTestResult::setCurrentTestObject(
const char *name)
691 QTest::currentTestObjectName = name;
692 QTest::updateIdentifier();
695const char *QTestResult::currentTestObjectName()
697 return QTest::currentTestObjectName ? QTest::currentTestObjectName :
"";
700void QTestResult::setSkipCurrentTest(
bool value)
702 QTest::skipCurrentTest = value;
705bool QTestResult::skipCurrentTest()
707 return QTest::skipCurrentTest;
710void QTestResult::setCurrentAppName(
const char *appName)
712 ::currentAppName = appName;
715const char *QTestResult::currentAppName()
717 return ::currentAppName;
722 using namespace QTest;
724 case ComparisonOperation::CustomCompare:
726 case ComparisonOperation::Equal:
727 return "QCOMPARE_EQ";
728 case ComparisonOperation::NotEqual:
729 return "QCOMPARE_NE";
730 case ComparisonOperation::LessThan:
731 return "QCOMPARE_LT";
732 case ComparisonOperation::LessThanOrEqual:
733 return "QCOMPARE_LE";
734 case ComparisonOperation::GreaterThan:
735 return "QCOMPARE_GT";
736 case ComparisonOperation::GreaterThanOrEqual:
737 return "QCOMPARE_GE";
738 case ComparisonOperation::ThreeWayCompare:
739 return "QCOMPARE_3WAY";
741 Q_UNREACHABLE_RETURN(
"");
746 using namespace QTest;
748 case ComparisonOperation::CustomCompare:
749 return "Compared values are not the same";
750 case ComparisonOperation::ThreeWayCompare:
751 return "The result of operator<=>() is not what was expected";
752 case ComparisonOperation::Equal:
753 return "The computed value is expected to be equal to the baseline, but is not";
754 case ComparisonOperation::NotEqual:
755 return "The computed value is expected to be different from the baseline, but is not";
756 case ComparisonOperation::LessThan:
757 return "The computed value is expected to be less than the baseline, but is not";
758 case ComparisonOperation::LessThanOrEqual:
759 return "The computed value is expected to be less than or equal to the baseline, but is not";
760 case ComparisonOperation::GreaterThan:
761 return "The computed value is expected to be greater than the baseline, but is not";
762 case ComparisonOperation::GreaterThanOrEqual:
763 return "The computed value is expected to be greater than or equal to the baseline, but is not";
765 Q_UNREACHABLE_RETURN(
"");
768bool QTestResult::reportResult(
bool success,
const void *lhs,
const void *rhs,
769 const char *(*lhsFormatter)(
const void*),
770 const char *(*rhsFormatter)(
const void*),
771 const char *lhsExpr,
const char *rhsExpr,
772 QTest::ComparisonOperation op,
const char *file,
int line,
773 const char *failureMessage)
775 Q_DECL_UNINITIALIZED
char msg[maxMsgLen];
778 QTEST_ASSERT(lhsExpr);
779 QTEST_ASSERT(rhsExpr);
781 if (QTestLog::verboseLevel() >= 2) {
782 std::snprintf(msg, maxMsgLen,
"%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr);
783 QTestLog::info(msg, file, line);
787 if (QTest::expectFailMode) {
788 std::snprintf(msg, maxMsgLen,
"%s(%s, %s) returned TRUE unexpectedly.",
789 macroNameForOp(op), lhsExpr, rhsExpr);
791 return checkStatement(success, msg, file, line);
794 const std::unique_ptr<
const char[]> lhsPtr{ lhsFormatter(lhs) };
795 const std::unique_ptr<
const char[]> rhsPtr{ rhsFormatter(rhs) };
798 failureMessage = failureMessageForOp(op);
800 formatFailMessage(msg, maxMsgLen, failureMessage, lhsPtr.get(), rhsPtr.get(),
801 lhsExpr, rhsExpr, op);
803 return checkStatement(success, msg, file, line);
806bool QTestResult::report3WayResult(
bool success,
807 const char *failureMessage,
808 const void *lhs,
const void *rhs,
809 const char *(*lhsFormatter)(
const void*),
810 const char *(*rhsFormatter)(
const void*),
811 const char *lhsExpression,
const char *rhsExpression,
812 const char *(*actualOrderFormatter)(
const void *),
813 const char *(*expectedOrderFormatter)(
const void *),
814 const void *actualOrder,
const void *expectedOrder,
815 const char *expectedExpression,
816 const char *file,
int line)
821 QTEST_ASSERT(lhsExpression);
822 QTEST_ASSERT(rhsExpression);
823 QTEST_ASSERT(expectedExpression);
824 const char *macroName = macroNameForOp(QTest::ComparisonOperation::ThreeWayCompare);
825 const std::string actualExpression = std::string(lhsExpression) +
" <=> " + rhsExpression;
827 if (QTestLog::verboseLevel() >= 2) {
828 std::snprintf(msg, maxMsgLen,
"%s(%s, %s, %s)",
829 macroName, lhsExpression, rhsExpression, expectedExpression);
830 QTestLog::info(msg, file, line);
834 if (QTest::expectFailMode) {
835 std::snprintf(msg, maxMsgLen,
"%s(%s, %s, %s) returned TRUE unexpectedly.",
836 macroName, lhsExpression, rhsExpression, expectedExpression);
838 return checkStatement(success, msg, file, line);
840 const std::unique_ptr<
const char[]> lhsStr{lhsFormatter(lhs)};
841 const std::unique_ptr<
const char[]> rhsStr{rhsFormatter(rhs)};
843 const std::unique_ptr<
const char[]> actual{actualOrderFormatter(actualOrder)};
844 const std::unique_ptr<
const char[]> expected{expectedOrderFormatter(expectedOrder)};
847 failureMessage = failureMessageForOp(QTest::ComparisonOperation::ThreeWayCompare);
850 formatFailMessage(msg, maxMsgLen, failureMessage,
851 lhsStr.get(), rhsStr.get(),
852 lhsExpression, rhsExpression,
853 QTest::ComparisonOperation::ThreeWayCompare);
856 formatFailMessage(msg + strlen(msg), maxMsgLen - strlen(msg),
"",
857 actual.get(), expected.get(),
858 actualExpression.c_str(), expectedExpression,
859 QTest::ComparisonOperation::CustomCompare);
861 return checkStatement(success, msg, file, line);
Q_TESTLIB_EXPORT Q_DECL_COLD_FUNCTION const char * formatPropertyTestHelperFailure(char *msg, size_t maxMsgLen, const char *actual, const char *expected, const char *actualExpr, const char *expectedExpr)
static char * identifierTestFunc
static char * identifierDataTag
static char * identifierGlobalDataTag
static void resetFailed()
static const char * expectFailComment
static void storeIdentifierString(char *&dest, const char *src)
static bool skipCurrentTest
static bool blacklistCurrentTest
static const char * currentTestFunc
static void setFailed(bool failed)
static const char * currentTestObjectName
static QTestData * currentTestData
static char * identifierObjectName
static QTestData * currentGlobalTestData
static void updateIdentifier()
static int expectFailMode
static Q_DECL_COLD_FUNCTION void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const Actual &val1, const Expected &val2, const char *actual, const char *expected, QTest::ComparisonOperation op)
static Q_DECL_COLD_FUNCTION void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const char *val1, const char *val2, const char *actual, const char *expected, QTest::ComparisonOperation op)
static bool checkStatement(bool statement, const char *msg, const char *file, int line)
static bool isExpectFailData(const char *dataIndex)
static const char * rightArgNameForOp(QTest::ComparisonOperation op)
static constexpr size_t maxMsgLen
static const char * failureMessageForOp(QTest::ComparisonOperation op)
static int approx_wide_len(const char *s)
static bool compareHelper(bool success, const char *failureMsg, const char *actual, const char *expected, const char *file, int line)
static const char * currentAppName
static bool compareHelper(bool success, const char *failureMsg, const Actual &val1, const Expected &val2, const char *actual, const char *expected, const char *file, int line, bool hasValues=true)
static const char * macroNameForOp(QTest::ComparisonOperation op)
static const char * leftArgNameForOp(QTest::ComparisonOperation op)
static void clearExpectFail()