5#include <QtTest/qtestcase.h>
6#include <QtTest/private/qtestcase_p.h>
7#include <QtTest/qtestassert.h>
9#include <QtCore/qbytearray.h>
10#include <QtCore/qcoreapplication.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qdir.h>
13#include <QtCore/qdirlisting.h>
15#include <QtCore/qexception.h>
17#include <QtCore/qfile.h>
18#include <QtCore/qfileinfo.h>
19#include <QtCore/qfloat16.h>
20#include <QtCore/qlibraryinfo.h>
21#include <QtCore/qlist.h>
22#include <QtCore/qmetaobject.h>
23#include <QtCore/qobject.h>
24#include <QtCore/qstringlist.h>
25#include <QtCore/qtemporarydir.h>
26#include <QtCore/qthread.h>
27#include <QtCore/qvarlengtharray.h>
28#include <QtCore/private/qlocking_p.h>
29#include <QtCore/private/qtools_p.h>
30#include <QtCore/private/qwaitcondition_p.h>
32#include <QtCore/qtestsupport_core.h>
34#include <QtTest/private/qtestlog_p.h>
35#include <QtTest/private/qtesttable_p.h>
36#include <QtTest/qtestdata.h>
37#include <QtTest/private/qtestresult_p.h>
38#include <QtTest/private/qsignaldumper_p.h>
39#include <QtTest/private/qbenchmark_p.h>
40#if QT_CONFIG(batch_test_support)
41#include <QtTest/private/qtestregistry_p.h>
43#include <QtTest/private/cycle_include_p.h>
44#include <QtTest/private/qtestblacklist_p.h>
45#include <QtTest/private/qtestcrashhandler_p.h>
46#if defined(HAVE_XCTEST)
47#include <QtTest/private/qxctestlogger_p.h>
50#include <QtTest/private/qtestutil_macos_p.h>
53#if defined(Q_OS_DARWIN)
54#include <QtTest/private/qappletestlogger_p.h>
59#if !defined(Q_OS_INTEGRITY) || __GHS_VERSION_NUMBER > 202014
63# undef __cpp_lib_to_chars
77#if defined(Q_OS_LINUX)
84# if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR))
87#include <qt_windows.h>
90#include <QtCore/private/qcore_unix_p.h>
93#if __has_include(<paths.h>)
101# if !defined(Q_OS_INTEGRITY)
102# include <sys/resource.h>
106#if defined(Q_OS_MACOS)
107#include <IOKit/pwr_mgt/IOPMLib.h>
108#include <mach/task.h>
109#include <mach/mach_init.h>
110#include <CoreFoundation/CFPreferences.h>
113#if defined(Q_OS_WASM)
114#include <emscripten.h>
118#include <QtCore/QStandardPaths>
125using namespace Qt::StringLiterals;
127using QtMiscUtils::toHexUpper;
128using QtMiscUtils::fromHex;
132#if defined(__COVERAGESCANNER__) && !QT_CONFIG(testlib_selfcover)
133 if (!qEnvironmentVariableIsEmpty(
"QT_TESTCOCOON_ACTIVE"))
137 qputenv(
"QT_TESTCOCOON_ACTIVE",
"1");
140 __coveragescanner_install(appname);
141 __coveragescanner_testname(testname);
142 __coveragescanner_clear();
153 if (sl.access() != QMetaMethod::Private || sl.parameterCount() != 0
154 || sl.returnType() != QMetaType::Void || sl.methodType() != QMetaMethod::Slot)
156 const QByteArray name = sl.name();
157 return !(name.isEmpty() || name.endsWith(
"_data")
158 || name ==
"initTestCase" || name ==
"cleanupTestCase"
159 || name ==
"init" || name ==
"cleanup");
169#if !QT_CONFIG(future)
170using QException = std::exception;
173class TestFailedException :
public QException
176 TestFailedException() =
default;
177 ~TestFailedException() override =
default;
179 const char *what()
const noexcept override {
return "QtTest: test failed"; }
182 TestFailedException *clone()
const override {
return new TestFailedException(); }
183 void raise()
const override {
throw TestFailedException(); }
187class TestSkippedException :
public QException
190 TestSkippedException() =
default;
191 ~TestSkippedException() override =
default;
193 const char *what()
const noexcept override {
return "QtTest: test was skipped"; }
196 TestSkippedException *clone()
const override {
return new TestSkippedException(); }
197 void raise()
const override {
throw TestSkippedException(); }
225
226
227
228
229
230
231
232
233
234
237
238
239
240
241
242
243
244
245
248
249
250
251
252
253
254
255
256
259
260
261
262
263
264
266
267
268
269
271
272
273
274
277
278
279
280
281
282
284
285
286
287
289
290
291
292
295
296
297
298
299
300
302
303
304
305
307
308
309
310
313
314
315
316
317
318
320
321
322
323
325
326
327
328
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
351 g_throwOnFail.fetchAndAddRelaxed(enable ? 1 : -1);
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
375 g_throwOnSkip.fetchAndAddRelaxed(enable ? 1 : -1);
382 return "QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) "
383 "was too short, %3 ms would have been sufficient this time."_L1
395#if defined(Q_OS_MACOS)
413 void invokeTest(
int index, QLatin1StringView tag,
std::optional<
WatchDog> &watchDog)
const;
414 void invokeTestOnData(
int index)
const;
416 QMetaMethod m_initTestCaseMethod;
417 QMetaMethod m_initTestCaseDataMethod;
418 QMetaMethod m_cleanupTestCaseMethod;
419 QMetaMethod m_initMethod;
420 QMetaMethod m_cleanupMethod;
422 MetaMethods m_methods;
433 if (m_methods.empty()) {
434 const QMetaObject *metaObject = o->metaObject();
435 const int count = metaObject->methodCount();
436 m_methods.reserve(count);
437 for (
int i = 0; i < count; ++i) {
438 const QMetaMethod me = metaObject->method(i);
440 m_methods.push_back(me);
445QMetaMethod
TestMethods::findMethod(
const QObject *obj,
const char *signature)
447 const QMetaObject *metaObject = obj->metaObject();
448 const int funcIndex = metaObject->indexOfMethod(signature);
449 return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
470 try { ok = m.invoke(obj, Qt ::DirectConnection); }
471 catch (
const TestFailedException &) {}
472 catch (
const TestSkippedException &) {}
479 const QMetaObject *metaObject = obj->metaObject();
480 int funcIndex = metaObject->indexOfMethod(methodName);
482 invokeTestMethodIfValid(metaObject->method(funcIndex), obj);
488 const QByteArray env = qgetenv(
"QTEST_EVENT_DELAY");
538static bool qPrintTestSlots(FILE *stream,
const char *filter =
nullptr,
const char *preamble =
"")
540 const auto matches = [filter](
const QByteArray &s) {
541 return !filter || QLatin1StringView(s).contains(QLatin1StringView(filter),
542 Qt::CaseInsensitive);
544 bool matched =
false;
546 QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
547 if (isValidSlot(sl)) {
548 const QByteArray signature = sl.methodSignature();
549 if (matches(signature)) {
550 std::fprintf(stream,
"%s%s\n", preamble, signature.constData());
562 QTestLog::setPrintAvailableTagsMode();
565 QTestTable::globalTestTable();
567 const QTestTable *gTable = QTestTable::globalTestTable();
569 const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject();
572 for (
int i = 0; i < currTestMetaObj->methodCount(); ++i) {
573 QMetaMethod tf = currTestMetaObj->method(i);
575 if (isValidSlot(tf)) {
578 QStringList localTags;
580 const QByteArray slot = tf.methodSignature().chopped(2);
581 const QByteArray member = slot +
"_data()";
582 invokeTestMethodIfExists(member.constData());
583 const int dataCount = table.dataCount();
584 localTags.reserve(dataCount);
585 for (
int j = 0; j < dataCount; ++j)
586 localTags << QLatin1StringView(table.testData(j)->dataTag());
589 if (gTable->dataCount() == 0) {
590 if (localTags.size() == 0) {
592 std::fprintf(stream,
"%s %s\n", currTestMetaObj->className(), slot.data());
595 for (
int k = 0; k < localTags.size(); ++k)
596 std::fprintf(stream,
"%s %s %s\n",
597 currTestMetaObj->className(),
599 localTags.at(k).toLatin1().data());
602 for (
int j = 0; j < gTable->dataCount(); ++j) {
603 if (localTags.size() == 0) {
605 std::fprintf(stream,
"%s %s __global__ %s\n",
606 currTestMetaObj->className(),
608 gTable->testData(j)->dataTag());
612 for (
int k = 0; k < localTags.size(); ++k)
613 std::fprintf(stream,
"%s %s %s __global__ %s\n",
614 currTestMetaObj->className(),
616 localTags.at(k).toLatin1().data(),
617 gTable->testData(j)->dataTag());
628 int l =
static_cast<
int>(strtol(str, &pEnd, 10));
630 std::fprintf(stderr,
"Invalid numeric parameter: '%s'\n", str);
639 const char *logFilename =
nullptr;
643 QTest::testFunctions.clear();
644 QTest::testTags.clear();
646#if defined(Q_OS_DARWIN) && defined(HAVE_XCTEST)
647 if (QXcodeTestLogger::canLogTestProgress())
648 logFormat = QTestLog::XCTest;
651 const char *testOptions =
652 " New-style logging options:\n"
653 " -o filename,format : Output results to file in the specified format\n"
654 " Use - to output to stdout\n"
655 " Valid formats are:\n"
656 " txt : Plain text\n"
657 " csv : CSV format (suitable for benchmarks)\n"
658 " junitxml : XML JUnit document\n"
659 " xml : XML document\n"
660 " lightxml : A stream of XML tags\n"
661 " teamcity : TeamCity format\n"
662 " tap : Test Anything Protocol\n"
664 " *** Multiple loggers can be specified, but at most one can log to stdout.\n"
666 " Old-style logging options:\n"
667 " -o filename : Write the output into file\n"
668 " -txt : Output results in Plain Text\n"
669 " -csv : Output results in a CSV format (suitable for benchmarks)\n"
670 " -junitxml : Output results as XML JUnit document\n"
671 " -xml : Output results as XML document\n"
672 " -lightxml : Output results as stream of XML tags\n"
673 " -teamcity : Output results in TeamCity format\n"
674 " -tap : Output results in Test Anything Protocol format\n"
676 " *** If no output file is specified, stdout is assumed.\n"
677 " *** If no output format is specified, -txt is assumed.\n"
679 " Test log detail options:\n"
680 " -silent : Log failures and fatal errors only\n"
681 " -v1 : Log the start of each testfunction\n"
682 " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n"
683 " -vs : Log every signal emission and resulting slot invocations\n"
685 " *** The -silent and -v1 options only affect plain text output.\n"
687 " Testing options:\n"
688 " -functions : Returns a list of current testfunctions\n"
689 " -datatags : Returns a list of current data tags.\n"
690 " A global data tag is preceded by ' __global__ '.\n"
691 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
692 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
693 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
694 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
695 " 0 means unlimited, default: 2000\n"
696 " -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
697 " -repeat n : Run the testsuite n times or until the test fails.\n"
698 " Useful for finding flaky tests. If negative, the tests are\n"
699 " repeated forever. This is intended as a developer tool, and\n"
700 " is only supported with the plain text logger.\n"
701 " -skipblacklisted : Skip blacklisted tests. Useful for measuring test coverage.\n"
703 " Benchmarking options:\n"
704#if QT_CONFIG(valgrind)
705 " -callgrind : Use callgrind to time benchmarks\n"
707#ifdef QTESTLIB_USE_PERF_EVENTS
708 " -perf : Use Linux perf events to time benchmarks\n"
709 " -perfcounter name : Use the counter named 'name'\n"
710 " -perfcounterlist : Lists the counters available\n"
712#ifdef HAVE_TICK_COUNTER
713 " -tickcounter : Use CPU tick counters to time benchmarks\n"
715 " -eventcounter : Counts events received during benchmarks\n"
716 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
717 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
718 " -iterations n : Sets the number of accumulation iterations.\n"
719 " -median n : Sets the number of median iterations.\n"
720 " -vb : Print out verbose benchmarking information.\n";
722 for (
int i = 1; i < argc; ++i) {
723 if (strcmp(argv[i],
"-help") == 0 || strcmp(argv[i],
"--help") == 0
724 || strcmp(argv[i],
"/?") == 0) {
725 std::printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
726 " By default, all testfunctions will be run.\n\n"
727 "%s", argv[0], testOptions);
731 " QmlTest options:\n"
732 " -import dir : Specify an import directory.\n"
733 " -plugins dir : Specify a directory where to search for plugins.\n"
734 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
735 " -translation file : Specify the translation file.\n"
736 " -file-selector dir : Specify a file selector for the QML engine.\n");
740 " -help : This help\n");
742 }
else if (strcmp(argv[i],
"-functions") == 0) {
749 }
else if (strcmp(argv[i],
"-datatags") == 0) {
754 }
else if (strcmp(argv[i],
"-txt") == 0) {
755 logFormat = QTestLog::Plain;
756 }
else if (strcmp(argv[i],
"-csv") == 0) {
757 logFormat = QTestLog::CSV;
758 }
else if (strcmp(argv[i],
"-junitxml") == 0) {
759 logFormat = QTestLog::JUnitXML;
760 }
else if (strcmp(argv[i],
"-xunitxml") == 0) {
761 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
762 logFormat = QTestLog::JUnitXML;
763 }
else if (strcmp(argv[i],
"-xml") == 0) {
764 logFormat = QTestLog::XML;
765 }
else if (strcmp(argv[i],
"-lightxml") == 0) {
766 logFormat = QTestLog::LightXML;
767 }
else if (strcmp(argv[i],
"-teamcity") == 0) {
768 logFormat = QTestLog::TeamCity;
769 }
else if (strcmp(argv[i],
"-tap") == 0) {
770 logFormat = QTestLog::TAP;
771 }
else if (strcmp(argv[i],
"-silent") == 0) {
772 QTestLog::setVerboseLevel(-1);
773 }
else if (strcmp(argv[i],
"-v1") == 0) {
774 QTestLog::setVerboseLevel(1);
775 }
else if (strcmp(argv[i],
"-v2") == 0) {
776 QTestLog::setVerboseLevel(2);
777 }
else if (strcmp(argv[i],
"-vs") == 0) {
778 QSignalDumper::setEnabled(
true);
779 }
else if (strcmp(argv[i],
"-o") == 0) {
781 std::fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
786 char *filename =
new char[strlen(argv[i])+1];
787 char *format =
new char[strlen(argv[i])+1];
788 if (
std::sscanf(argv[i],
"%[^,],%s", filename, format) == 1) {
790 logFilename = argv[i];
793 if (strcmp(format,
"txt") == 0)
794 logFormat = QTestLog::Plain;
795 else if (strcmp(format,
"csv") == 0)
796 logFormat = QTestLog::CSV;
797 else if (strcmp(format,
"lightxml") == 0)
798 logFormat = QTestLog::LightXML;
799 else if (strcmp(format,
"xml") == 0)
800 logFormat = QTestLog::XML;
801 else if (strcmp(format,
"junitxml") == 0)
802 logFormat = QTestLog::JUnitXML;
803 else if (strcmp(format,
"xunitxml") == 0) {
804 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
805 logFormat = QTestLog::JUnitXML;
806 }
else if (strcmp(format,
"teamcity") == 0)
807 logFormat = QTestLog::TeamCity;
808 else if (strcmp(format,
"tap") == 0)
809 logFormat = QTestLog::TAP;
811 std::fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
814 if (strcmp(filename,
"-") == 0 && QTestLog::loggerUsingStdout()) {
815 std::fprintf(stderr,
"only one logger can log to stdout\n");
818 QTestLog::addLogger(QTestLog::LogMode(logFormat), filename);
822 }
else if (strcmp(argv[i],
"-eventdelay") == 0) {
824 std::fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
829 }
else if (strcmp(argv[i],
"-keydelay") == 0) {
831 std::fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
836 }
else if (strcmp(argv[i],
"-mousedelay") == 0) {
838 std::fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
843 }
else if (strcmp(argv[i],
"-maxwarnings") == 0) {
845 std::fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
848 QTestLog::setMaxWarnings(qToInt(argv[++i]));
850 }
else if (strcmp(argv[i],
"-repeat") == 0) {
852 std::fprintf(stderr,
"-repeat needs an extra parameter for the number of repetitions\n");
857 }
else if (strcmp(argv[i],
"-nocrashhandler") == 0) {
859 }
else if (strcmp(argv[i],
"-skipblacklisted") == 0) {
861#if QT_CONFIG(valgrind)
862 }
else if (strcmp(argv[i],
"-callgrind") == 0) {
863 if (!QBenchmarkValgrindUtils::haveValgrind()) {
865 "WARNING: Valgrind not found or too old. "
866 "Make sure it is installed and in your path. "
867 "Using the walltime measurer.\n");
868 }
else if (QFileInfo(QDir::currentPath()).isWritable()) {
869 QBenchmarkGlobalData::current->setMode(
870 QBenchmarkGlobalData::CallgrindParentProcess);
873 "WARNING: Current directory not writable. "
874 "Using the walltime measurer.\n");
876 }
else if (strcmp(argv[i],
"-callgrindchild") == 0) {
877 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
878 QBenchmarkGlobalData::current->callgrindOutFileBase =
879 QBenchmarkValgrindUtils::outFileBase();
881#ifdef QTESTLIB_USE_PERF_EVENTS
882 }
else if (strcmp(argv[i],
"-perf") == 0) {
883 if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
885 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
887 std::fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
889 }
else if (strcmp(argv[i],
"-perfcounter") == 0) {
891 std::fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
894 QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
896 }
else if (strcmp(argv[i],
"-perfcounterlist") == 0) {
897 QBenchmarkPerfEventsMeasurer::listCounters();
900#ifdef HAVE_TICK_COUNTER
901 }
else if (strcmp(argv[i],
"-tickcounter") == 0) {
902 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
904 }
else if (strcmp(argv[i],
"-eventcounter") == 0) {
905 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
906 }
else if (strcmp(argv[i],
"-minimumvalue") == 0) {
908 std::fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
911 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
913 }
else if (strcmp(argv[i],
"-minimumtotal") == 0) {
915 std::fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
918 QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
920 }
else if (strcmp(argv[i],
"-iterations") == 0) {
922 std::fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
925 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
927 }
else if (strcmp(argv[i],
"-median") == 0) {
929 std::fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
932 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
935 }
else if (strcmp(argv[i],
"-vb") == 0) {
936 QBenchmarkGlobalData::current->verboseOutput =
true;
937#if defined(Q_OS_DARWIN)
938 }
else if (strncmp(argv[i],
"-Apple", 6) == 0) {
941# if defined(HAVE_XCTEST)
942 }
else if (
int skip = QXcodeTestLogger::parseCommandLineArgument(argv[i])) {
947 }
else if (argv[i][0] ==
'-') {
948 std::fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[i], testOptions);
950 std::fprintf(stderr,
"\nqmltest related options:\n"
951 " -import : Specify an import directory.\n"
952 " -plugins : Specify a directory where to search for plugins.\n"
953 " -input : Specify the root directory for test cases.\n");
956 std::fprintf(stderr,
"\n"
957 " -help : This help\n");
964 for (offset = 0; argv[i][offset]; ++offset) {
965 if (argv[i][offset] ==
':') {
966 if (argv[i][offset + 1] ==
':') {
977 QTest::testFunctions += QString::fromLatin1(argv[i]);
978 QTest::testTags += QString();
980 QTest::testFunctions +=
981 QString::fromLatin1(argv[i], colon);
983 QString::fromLatin1(argv[i] + colon + 1);
988 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
989 QTestLog::setInstalledTestCoverage(installedTestCoverage);
993 const bool explicitLoggerRequested = logFormat != -1;
994 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
995 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
997 bool addFallbackLogger = !explicitLoggerRequested;
999#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
1001 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
1002 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1003 QTestLog::addLogger(QTestLog::Apple,
nullptr);
1004 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
1005 addFallbackLogger =
false;
1009 if (addFallbackLogger)
1010 QTestLog::addLogger(QTestLog::Plain, logFilename);
1012 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
1013 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
1020 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
1025 const int count = container.size();
1030 return container.front();
1032 QList<QList<QBenchmarkResult>> containerCopy = container;
1033 std::sort(containerCopy.begin(), containerCopy.end(),
1034 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
1035 return a.first() < b.first();
1038 const int middle = count / 2;
1041 return containerCopy.at(middle);
1048 QTestResult::setCurrentTestData(data);
1052 QTestResult::setCurrentTestData(
nullptr);
1056void TestMethods::invokeTestOnData(
int index)
const
1060 bool isBenchmark =
false;
1061 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1063 QList<QList<QBenchmarkResult>> resultsList;
1064 bool minimumTotalReached =
false;
1066 QBenchmarkTestMethodData::current->beginDataRun();
1068 QBenchmarkTestMethodData::current->iterationCount = 1;
1074 invokeTestMethodIfValid(m_initMethod);
1076 const bool initQuit =
1077 QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
1079 QBenchmarkTestMethodData::current->results.clear();
1080 QBenchmarkTestMethodData::current->resultAccepted =
false;
1081 QBenchmarkTestMethodData::current->valid =
false;
1083 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1084 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1086 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1088 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1090 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1096 QTestResult::finishedCurrentTestData();
1099 invokeTestMethodIfValid(m_cleanupMethod);
1103 if (QCoreApplication::instance())
1104 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1109 QTestResult::finishedCurrentTestDataCleanup();
1115 }
while (invokeOk && isBenchmark
1116 && QBenchmarkTestMethodData::current->resultsAccepted() ==
false
1117 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1119 QBenchmarkTestMethodData::current->endDataRun();
1120 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1122 resultsList.append(QBenchmarkTestMethodData::current->results);
1124 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1125 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1127 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1128 QString pattern = i < 0 ?
"warmup stage result : %1"_L1
1129 :
"accumulation stage result: %1"_L1;
1130 QTestLog::info(qPrintable(pattern.arg(first.measurement.value)),
nullptr, 0);
1136 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1137 minimumTotalReached =
true;
1139 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1141 current += r.first().measurement.value;
1144 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1145 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1147 }
while (isBenchmark
1148 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1149 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1153 bool testPassed = !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed();
1154 QTestResult::finishedCurrentTestDataCleanup();
1156 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1157 QTestLog::addBenchmarkResults(qMedian(resultsList));
1161#if QT_CONFIG(thread)
1258 qFatal(
"Test function timed out");
1281template <
typename Functor>
1285 watchDog->beginTest();
1290 watchDog->testFinished();
1294 const QTestTable &lTable,
const QTestTable &gTable)
1296 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1297 const int localDataCount = lTable.dataCount();
1298 if (localDataCount) {
1299 std::fputs(
"Available test-specific data tags:\n", stderr);
1300 for (
int i = 0; i < localDataCount; ++i)
1301 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1303 const int globalDataCount = gTable.dataCount();
1304 if (globalDataCount) {
1305 std::fputs(
"Available global data tags:\n", stderr);
1306 for (
int i = 0; i < globalDataCount; ++i)
1307 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1309 if (localDataCount == 0 && globalDataCount == 0)
1310 std::fputs(
"Function has no data tags\n", stderr);
1314
1315
1316
1317
1318
1321 QBenchmarkTestMethodData benchmarkData;
1322 QBenchmarkTestMethodData::current = &benchmarkData;
1324 const QByteArray &name = m_methods[index].name();
1325 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1330 QTestResult::setCurrentTestFunction(name.constData());
1332 const QTestTable *gTable = QTestTable::globalTestTable();
1333 const int globalDataCount = gTable->dataCount();
1334 int curGlobalDataIndex = 0;
1335 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1336 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1339 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1340 QLatin1StringView global) {
1343 if (tag == local || tag == global)
1346 return tag.startsWith(global) && tag.endsWith(local) &&
1347 tag.size() == global.size() + 1 + local.size() &&
1348 tag[global.size()] ==
':';
1350 bool foundFunction =
false;
1351 bool blacklisted =
false;
1355 if (!gTable->isEmpty())
1356 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1358 if (curGlobalDataIndex == 0) {
1359 std::snprintf(member, 512,
"%s_data()", name.constData());
1360 runWithWatchdog(watchDog, [&member] {
1363 if (QTestResult::skipCurrentTest())
1367 int curDataIndex = 0;
1368 const int dataCount = table.dataCount();
1369 const auto dataTag = [&table, dataCount](
int index) {
1370 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1375 QTestResult::setSkipCurrentTest(
false);
1376 QTestResult::setBlacklistCurrentTest(
false);
1377 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1378 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1379 foundFunction =
true;
1380 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1381 globalDataTag(curGlobalDataIndex));
1383 QTestResult::setBlacklistCurrentTest(
true);
1386 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1388 QTestResult::finishedCurrentTestData();
1389 QTestResult::finishedCurrentTestDataCleanup();
1392 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1394 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1400 runWithWatchdog(watchDog, [
this, index] {
1401 invokeTestOnData(index);
1405 if (!tag.isEmpty() && !globalDataCount)
1409 }
while (curDataIndex < dataCount);
1411 QTestResult::setCurrentGlobalTestData(
nullptr);
1412 ++curGlobalDataIndex;
1413 }
while (curGlobalDataIndex < globalDataCount);
1415 if (!tag.isEmpty() && !foundFunction) {
1416 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1417 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1419 QTestResult::finishedCurrentTestFunction();
1420 QTestResult::setSkipCurrentTest(
false);
1421 QTestResult::setBlacklistCurrentTest(
false);
1424void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1426 QTEST_ASSERT(typeId);
1427 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1428 QTEST_ASSERT(data->parent());
1430 int idx = data->parent()->indexOf(tagName);
1432 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1433 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1437 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1438 qFatal(
"Requested type '%s' does not match available type '%s'.",
1439 QMetaType(typeId).name(),
1440 QMetaType(data->parent()->elementTypeId(idx)).name());
1443 return data->data(idx);
1447
1448
1449char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1452 va_start(ap, numArguments);
1454 QByteArray arguments;
1455 arguments += prefix;
1457 if (numArguments > 0) {
1458 arguments += va_arg(ap,
const char *);
1460 for (size_t i = 1; i < numArguments; ++i) {
1462 arguments += va_arg(ap,
const char *);
1467 arguments += suffix;
1468 return qstrdup(arguments.constData());
1472
1473
1474
1475
1476
1477
1478
1479
1480
1487
1488
1489
1490
1491
1492
1493 const qsizetype maxLen = 50;
1494 const qsizetype len = qMin(maxLen, length);
1495 char *result =
nullptr;
1497 if (length > maxLen) {
1498 const qsizetype size = len * 3 + 4;
1499 result =
new char[size];
1501 char *
const forElipsis = result + size - 5;
1502 forElipsis[0] =
' ';
1503 forElipsis[1] =
'.';
1504 forElipsis[2] =
'.';
1505 forElipsis[3] =
'.';
1506 result[size - 1] =
'\0';
1509 const qsizetype size = len * 3;
1510 result =
new char[size];
1511 result[size - 1] =
'\0';
1518 const char at = ba[i];
1520 result[o] = toHexUpper(at >> 4);
1522 result[o] = toHexUpper(at);
1536
1537
1538
1539
1542 bool trimmed =
false;
1543 auto buffer =
std::make_unique<
char[]>(256);
1544 const char *end = p + length;
1545 char *dst = buffer.get();
1547 bool lastWasHexEscape =
false;
1549 for ( ; p != end; ++p) {
1555 if (dst - buffer.get() > 246) {
1562 if (Q_UNLIKELY(lastWasHexEscape)) {
1563 if (fromHex(*p) != -1) {
1568 lastWasHexEscape =
false;
1571 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1602 *dst++ = toHexUpper(uchar(*p) >> 4);
1603 *dst++ = toHexUpper(uchar(*p));
1604 lastWasHexEscape =
true;
1616 return buffer.release();
1620
1621
1622
1623
1624
1625
1626
1635 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1636 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1665 *dst++ = toHexUpper(ch >> 12);
1666 *dst++ = toHexUpper(ch >> 8);
1667 *dst++ = toHexUpper(ch >> 4);
1668 *dst++ = toHexUpper(ch);
1676 auto p = string.utf16();
1677 auto length = string.size();
1679 bool trimmed =
false;
1680 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1681 const auto end = p + length;
1682 char *dst = buffer.get();
1685 for ( ; p != end; ++p) {
1686 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1690 dst = writePrettyUnicodeChar(*p, dst);
1700 return buffer.release();
1705 const QMetaObject *metaObject = testObject->metaObject();
1706 QTEST_ASSERT(metaObject);
1709 if (!CrashHandler::alreadyDebugging()
1710#if QT_CONFIG(valgrind)
1711 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1717 QTestResult::setCurrentTestFunction(
"initTestCase");
1718 runWithWatchdog(watchDog, [
this, testObject] {
1719 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1722 QSignalDumper::startDump();
1724 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1726 runWithWatchdog(watchDog, [
this, testObject] {
1727 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1731 const bool previousFailed = QTestResult::currentTestFailed();
1732 QTestResult::finishedCurrentTestData();
1733 QTestResult::finishedCurrentTestDataCleanup();
1734 QTestResult::finishedCurrentTestFunction();
1736 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1737 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1738 const char *data =
nullptr;
1739 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1740 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1741 invokeTest(i, QLatin1StringView(data), watchDog);
1746 const bool wasSkipped = QTestResult::skipCurrentTest();
1747 QTestResult::setSkipCurrentTest(
false);
1748 QTestResult::setBlacklistCurrentTest(
false);
1749 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1750 runWithWatchdog(watchDog, [
this, testObject] {
1751 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1754 QTestResult::finishedCurrentTestData();
1756 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1757 QTestResult::finishedCurrentTestDataCleanup();
1759 QTestResult::finishedCurrentTestFunction();
1760 QTestResult::setCurrentTestFunction(
nullptr);
1762 QSignalDumper::endDump();
1765#if QT_DEPRECATED_SINCE(6
, 8
)
1784 const char *(*lhsFormatter)(
const void*),
1785 const char *(*rhsFormatter)(
const void*),
1786 const char *lhsExpr,
const char *rhsExpr,
1787 ComparisonOperation op,
const char *file,
int line)
1789 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1790 lhsExpr, rhsExpr, op, file, line);
1796 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1800static QFile androidExitCodeFile()
1802 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1803 return QFile(testHome +
"/qtest_last_exit_code"_L1);
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1845int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1851 qInit(testObject, argc, argv);
1855#if defined(Q_OS_WASM)
1857 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1858 Module.notifyTestFinished($0);
1866
1867void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1870 CrashHandler::maybeDisableCoreDump();
1871 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1873#if defined(Q_OS_MACOS)
1875 QTestPrivate::disableWindowRestore();
1878 if (!appNapDisabler)
1879 appNapDisabler.emplace();
1881 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1882 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1883 &macPowerSavingDisabled);
1886 QTestPrivate::parseBlackList();
1887 QTestResult::reset();
1889 QTEST_ASSERT(testObject);
1890 QTEST_ASSERT(!currentTestObject);
1893 const QMetaObject *metaObject = testObject->metaObject();
1894 QTEST_ASSERT(metaObject);
1896 QTestResult::setCurrentTestObject(metaObject->className());
1898 QTestResult::setCurrentAppName(argv[0]);
1902#if QT_CONFIG(valgrind)
1903 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1905 QTestLog::startLogging();
1908 androidExitCodeFile().remove();
1913
1916 QTEST_ASSERT(currentTestObject);
1918#if QT_CONFIG(valgrind)
1919 int callgrindChildExitCode = 0;
1922#ifndef QT_NO_EXCEPTIONS
1926#if QT_CONFIG(valgrind)
1927 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1928 if (Q_UNLIKELY(!qApp))
1929 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1931 const QStringList origAppArgs(QCoreApplication::arguments());
1932 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1935 QBenchmarkValgrindUtils::cleanup();
1940 std::optional<CrashHandler::FatalSignalHandler> handler;
1941 CrashHandler::prepareStackTrace();
1945 bool seenBad =
false;
1946 TestMethods::MetaMethods commandLineMethods;
1947 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1948 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1949 const QByteArray tfB = tf.toLatin1();
1950 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1951 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1952 if (m.isValid() && isValidSlot(m)) {
1953 commandLineMethods.push_back(m);
1955 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1956 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1957 std::fputc(
'\n', stderr);
1958 QTestResult::setCurrentTestFunction(tfB.constData());
1959 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1960 QTestResult::finishedCurrentTestFunction();
1962 QTest::testTags.remove(commandLineMethods.size());
1968 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1969 QTestResult::currentAppName());
1970 if (commandLineMethods.empty())
1977 while (QTestLog::failCount() == 0 && (repeatForever || remainingRepetitions-- > 0)) {
1978 QTestTable::globalTestTable();
1979 test.invokeTests(currentTestObject);
1980 QTestTable::clearGlobalTestTable();
1984#ifndef QT_NO_EXCEPTIONS
1986 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
1987 if (QTestResult::currentTestFunction()) {
1988 QTestResult::finishedCurrentTestFunction();
1989 QTestResult::setCurrentTestFunction(
nullptr);
2000#if QT_CONFIG(valgrind)
2001 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2002 return callgrindChildExitCode;
2006 const int exitCode = qMin(QTestLog::failCount(), 127);
2009 QFile exitCodeFile = androidExitCodeFile();
2010 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2011 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2013 qWarning(
"Failed to open %s for writing test exit code: %s",
2014 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2022
2027#if QT_CONFIG(valgrind)
2028 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2030 QTestLog::stopLogging();
2032 delete QBenchmarkGlobalData::current;
2033 QBenchmarkGlobalData::current =
nullptr;
2035#if defined(Q_OS_MACOS)
2036 IOPMAssertionRelease(macPowerSavingDisabled);
2037 appNapDisabler = std::nullopt;
2041#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2054 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2057QList<QString> QTest::qGetTestCaseNames()
2059 return QTest::TestRegistry::instance()->getAllTestNames();
2062QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2064 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2070
2071
2072
2073
2074
2075
2076int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2078 const int argc = arguments.size();
2079 QVarLengthArray<
char *> argv(argc);
2081 QList<QByteArray> args;
2084 for (
int i = 0; i < argc; ++i)
2086 args.append(arguments.at(i).toLocal8Bit().constData());
2087 argv[i] = args.last().data();
2090 return qExec(testObject, argc, argv.data());
2094
2095void QTest::
qFail(
const char *message,
const char *file,
int line)
2097 QTestResult::fail(message, file, line);
2101
2102bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2103 const char *file,
int line)
2105 return QTestResult::verify(statement, statementStr, description, file, line);
2109
2110
2111void QTest::
qSkip(
const char *message,
const char *file,
int line)
2113 QTestResult::addSkip(message, file, line);
2114 QTestResult::setSkipCurrentTest(
true);
2118
2119
2121 QTest::TestFailMode mode,
const char *file,
int line)
2123 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2144 auto message = [&] {
2145 const auto exType = what ?
"std::" :
"unknown ";
2146 const auto ofType = expected ?
" of type " :
"";
2147 const auto no = expected ?
"an" :
"no";
2148 const auto withMsg = what ?
" with message " :
"";
2149 const auto protect = [](
const char *s) {
return s ? s :
""; };
2151 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2152 "but caught %sexception%s%s",
2153 no, ofType, protect(expected),
2154 exType, withMsg, protect(what));
2156 qFail(message().toUtf8().constData(), file, line);
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2182 std::rethrow_exception(
std::current_exception());
2183 }
catch (
const std::exception &e) {
2184 qCaught(expected, e.what(), file, line);
2186 qCaught(expected,
nullptr, file, line);
2193#if QT_DEPRECATED_SINCE(6
, 3
)
2195
2196
2197
2198void QTest::qWarn(
const char *message,
const char *file,
int line)
2200 QTestLog::warn(message, file, line);
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2224 QTestLog::ignoreMessage(type, message);
2227#if QT_CONFIG(regularexpression)
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2245 QTestLog::ignoreMessage(type, messagePattern);
2250
2251
2253
2254
2255
2256
2259 return QTestLog::failOnWarning();
2263
2264
2266
2267
2268
2269
2272 return QTestLog::failOnWarning(message);
2275#if QT_CONFIG(regularexpression)
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2330 QTestLog::failOnWarning(messagePattern);
2335
2338static inline bool isWindowsBuildDirectory(
const QString &dirName)
2340 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2341 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2345#if QT_CONFIG(temporaryfile)
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2358 QSharedPointer<QTemporaryDir> result;
2360 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2362 tempDir->setAutoRemove(
true);
2364 if (!tempDir->isValid())
2367 const QString dataPath = tempDir->path();
2368 const QString resourcePath = u':' + dirName;
2369 const QFileInfo fileInfo(resourcePath);
2371 if (!fileInfo.isDir()) {
2372 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2376 bool isResourceDirEmpty =
true;
2377 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2378 isResourceDirEmpty =
false;
2379 if (!dirEntry.isDir()) {
2380 const QString &filePath = dirEntry.filePath();
2381 const QString destination =
2382 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2383 QFileInfo destinationFileInfo(destination);
2384 QDir().mkpath(destinationFileInfo.path());
2385 QFile file(filePath);
2386 if (!file.copy(destination)) {
2387 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2388 qUtf16Printable(file.errorString()));
2392 file.setFileName(destination);
2393 if (!file.setPermissions(QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2394 qWarning(
"Failed to set permissions on '%ls': %ls.", qUtf16Printable(destination),
2395 qUtf16Printable(file.errorString()));
2401 if (isResourceDirEmpty) {
2402 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2406 result = std::move(tempDir);
2413
2415QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2416 const char *sourcedir)
2424 QDir binDirectory(QCoreApplication::applicationDirPath());
2425 if (binDirectory.exists(base)) {
2426 found = binDirectory.absoluteFilePath(base);
2431 else if (isWindowsBuildDirectory(binDirectory.dirName())
2432 && binDirectory.cdUp() && binDirectory.exists(base)) {
2433 found = binDirectory.absoluteFilePath(base);
2436 else if (QTestLog::verboseLevel() >= 2) {
2437 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2438 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2439 "checking next location"_L1.arg(base, candidate)),
2445 if (found.isEmpty()) {
2446 const char *testObjectName = QTestResult::currentTestObjectName();
2447 if (testObjectName) {
2448 const QString testsPath = QLibraryInfo::path(QLibraryInfo::TestsPath);
2449 const QString candidate =
"%1/%2/%3"_L1
2450 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2451 if (QFileInfo::exists(candidate)) {
2453 }
else if (QTestLog::verboseLevel() >= 2) {
2454 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2455 "checking next location"_L1
2456 .arg(base, QDir::toNativeSeparators(candidate))),
2463 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2465 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2469 if (!srcdir.isAbsolute() && builddir)
2470 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2472 const QString canonicalPath = srcdir.canonicalFilePath();
2473 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2474 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2476 }
else if (QTestLog::verboseLevel() >= 2) {
2477 QTestLog::info(qPrintable(
2478 "testdata %1 not found relative to source path [%2]"_L1
2479 .arg(base, QDir::toNativeSeparators(candidate))),
2485 if (found.isEmpty()) {
2486 const QString candidate =
":/%1"_L1.arg(base);
2487 if (QFileInfo::exists(candidate)) {
2489 }
else if (QTestLog::verboseLevel() >= 2) {
2490 QTestLog::info(qPrintable(
2491 "testdata %1 not found in resources [%2]"_L1
2492 .arg(base, QDir::toNativeSeparators(candidate))),
2498 if (found.isEmpty()) {
2499 const QString candidate = QDir::currentPath() + u'/' + base;
2500 if (QFileInfo::exists(candidate)) {
2502 }
else if (QTestLog::verboseLevel() >= 2) {
2503 QTestLog::info(qPrintable(
2504 "testdata %1 not found in current directory [%2]"_L1
2505 .arg(base, QDir::toNativeSeparators(candidate))),
2511 if (found.isEmpty()) {
2512 const QString candidate = QTest::mainSourcePath % u'/' % base;
2513 if (QFileInfo::exists(candidate)) {
2515 }
else if (QTestLog::verboseLevel() >= 2) {
2516 QTestLog::info(qPrintable(
2517 "testdata %1 not found in main source directory [%2]"_L1
2518 .arg(base, QDir::toNativeSeparators(candidate))),
2524 if (found.isEmpty() && sourcedir) {
2525 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2526 if (QFileInfo::exists(candidate)) {
2528 }
else if (QTestLog::verboseLevel() >= 2) {
2529 QTestLog::info(qPrintable(
2530 "testdata %1 not found in supplied source directory [%2]"_L1
2531 .arg(base, QDir::toNativeSeparators(candidate))),
2537 if (found.isEmpty()) {
2538 QTestLog::warn(qPrintable(
2539 "testdata %1 could not be located!"_L1.arg(base)),
2541 }
else if (QTestLog::verboseLevel() >= 1) {
2542 QTestLog::info(qPrintable(
2543 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2551
2552QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2553 const char *sourcedir)
2555 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2559
2562 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2566
2569 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2573
2576 QTEST_ASSERT(tagName);
2577 QTestData *data = QTestResult::currentTestData();
2579 QTEST_ASSERT(data->parent());
2581 int idx = data->parent()->indexOf(tagName);
2582 QTEST_ASSERT(idx != -1);
2583 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2585 return data->data(data->parent()->indexOf(tagName));
2589
2592 QTestTable *tbl = QTestTable::currentTestTable();
2593 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2595 tbl->addColumn(id, name);
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618QTestData &
QTest::newRow(
const char *dataTag)
2620 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2621 QTestTable *tbl = QTestTable::currentTestTable();
2622 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2623 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2624 "Must add columns before attempting to add rows.");
2626 return *tbl->newData(dataTag);
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656QTestData &
QTest::addRow(
const char *format, ...)
2658 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2659 QTestTable *tbl = QTestTable::currentTestTable();
2660 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2661 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2662 "Must add columns before attempting to add rows.");
2667 va_start(va, format);
2670 std::vsnprintf(buf,
sizeof buf, format, va);
2673 return *tbl->newData(buf);
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2698
2699
2702 return QTestResult::currentAppName();
2706
2707
2708
2709
2710
2711
2714 return QTestResult::currentTestFunction();
2718
2719
2720
2723 return QTestResult::currentDataTag();
2727
2728
2729
2730
2731
2734 return QTestResult::currentGlobalDataTag();
2738
2739
2740
2741
2744 return QTestResult::currentTestFailed();
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2762 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2766
2767
2768
2769
2770
2771
2772
2779
2782 return currentTestObject;
2786
2789 QString mainSourceFile = QFile::decodeName(file);
2792 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2794 fi.setFile(mainSourceFile);
2798#if QT_DEPRECATED_SINCE(6
, 4
)
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817bool QTest::compare_helper(
bool success,
const char *failureMsg,
2818 char *actualVal,
char *expectedVal,
2819 const char *actual,
const char *expected,
2820 const char *file,
int line)
2822 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2823 actual, expected, file, line);
2827#if QT_DEPRECATED_SINCE(6
, 8
)
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841bool QTest::compare_helper(
bool success,
const char *failureMsg,
2842 qxp::function_ref<
const char *()> actualVal,
2843 qxp::function_ref<
const char *()> expectedVal,
2844 const char *actual,
const char *expected,
2845 const char *file,
int line)
2847 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2848 QTest::functionRefFormatter,
2849 QTest::functionRefFormatter, actual, expected,
2850 QTest::ComparisonOperation::CustomCompare,
2851 file, line, failureMsg);
2856
2857
2858
2859
2860
2861
2862
2863
2866 const void *actualPtr,
const void *expectedPtr,
2867 const char *(*actualFormatter)(
const void *),
2868 const char *(*expectedFormatter)(
const void *),
2869 const char *actual,
const char *expected,
2870 const char *file,
int line)
2872 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2873 actualFormatter, expectedFormatter,
2875 QTest::ComparisonOperation::CustomCompare,
2876 file, line, failureMsg);
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2908 const void *lhsPtr,
const void *rhsPtr,
2909 const char *(*lhsFormatter)(
const void*),
2910 const char *(*rhsFormatter)(
const void*),
2911 const char *lhsExpression,
const char *rhsExpression,
2912 const char *(*actualOrderFormatter)(
const void *),
2913 const char *(*expectedOrderFormatter)(
const void *),
2914 const void *actualOrderPtr,
const void *expectedOrderPtr,
2915 const char *expectedExpression,
2916 const char *file,
int line)
2918 return QTestResult::report3WayResult(success, failureMsg,
2920 lhsFormatter, rhsFormatter,
2921 lhsExpression, rhsExpression,
2922 actualOrderFormatter,
2923 expectedOrderFormatter,
2924 actualOrderPtr, expectedOrderPtr,
2930
2931
2932
2933
2934
2935
2936
2937
2938
2940 const char *expected,
const char *file,
int line)
2942 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2945template <
typename T>
2948 switch (qFpClassify(expected))
2951 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2953 return qFpClassify(actual) == FP_NAN;
2955 if (!qFuzzyIsNull(expected))
2956 return qFuzzyCompare(actual, expected);
2960 return qFuzzyIsNull(actual);
2965
2966
2967bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2968 const char *file,
int line)
2970 auto formatter = Internal::genericToString<qfloat16>;
2971 return compare_helper(floatingCompare(t1, t2),
2972 "Compared qfloat16s are not the same (fuzzy compare)",
2973 &t1, &t2, formatter, formatter,
2974 actual, expected, file, line);
2978
2979
2980bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
2981 const char *file,
int line)
2983 return QTestResult::compare(floatingCompare(t1, t2),
2984 "Compared floats are not the same (fuzzy compare)",
2985 t1, t2, actual, expected, file, line);
2989
2990
2991bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
2992 const char *file,
int line)
2994 return QTestResult::compare(floatingCompare(t1, t2),
2995 "Compared doubles are not the same (fuzzy compare)",
2996 t1, t2, actual, expected, file, line);
3000
3001
3002
3004 const char *file,
int line)
3006 return QTestResult::compare(t1 == t2,
3007 "Compared values are not the same",
3008 t1, t2, actual, expected, file, line);
3011#if QT_POINTER_SIZE == 8
3013
3014
3015
3017bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3018 const char *file,
int line)
3020 return QTestResult::compare(t1 == t2,
3021 "Compared values are not the same",
3022 t1, t2, actual, expected, file, line);
3027
3028
3029
3030bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3031 const char *file,
int line)
3033 return QTestResult::compare(t1 == t2,
3034 "Compared values are not the same",
3035 t1, t2, actual, expected, file, line);
3039
3040
3041
3042bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3043 const char *file,
int line)
3045 return QTestResult::compare(t1 == t2,
3046 "Compared values are not the same",
3047 t1, t2, actual, expected, file, line);
3051
3052
3053
3054bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3055 const char *file,
int line)
3057 return QTestResult::compare(t1 == t2,
3058 "Compared values are not the same",
3059 t1, t2, actual, expected, file, line);
3063
3064
3065
3066bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3067 const char *file,
int line)
3069 return QTestResult::compare(t1 == t2,
3070 "Compared values are not the same",
3071 t1, t2, actual, expected, file, line);
3075
3076
3077
3080
3081
3082
3085
3086
3087
3090
3091
3094
3095
3097#define TO_STRING_IMPL(TYPE, FORMAT) template
3098 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3099{
3100 char *msg = new char[128
];
3101 std::snprintf(msg, 128
, #FORMAT, t);
3103}
3120 constexpr int Digits =
std::numeric_limits<T>::digits;
3121 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3122 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3123 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3129 Q_ASSERT(qIsNaN(t));
3130 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3131 r.payload = u & PayloadMask;
3132 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3136static bool signbit(qfloat16 f) {
return f.signBit(); }
3144 char *msg =
new char[128];
3145 bool negative = signbit(t);
3147 switch (qFpClassify(t)) {
3149 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3152 if (
auto r = decodeNanPayload(t); r.payload) {
3153 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3154 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3156 Q_ASSERT(r.isQuiet);
3157 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3161 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3164 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3171#define TO_STRING_FLOAT(TYPE) template
3172 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3173{
3174 return toStringFp(t); \
3175}
3182 unsigned char c =
static_cast<
unsigned char>(t);
3183 char *msg =
new char[16];
3186 qstrcpy(msg,
"'\\0'");
3189 qstrcpy(msg,
"'\\a'");
3192 qstrcpy(msg,
"'\\b'");
3195 qstrcpy(msg,
"'\\t'");
3198 qstrcpy(msg,
"'\\n'");
3201 qstrcpy(msg,
"'\\v'");
3204 qstrcpy(msg,
"'\\f'");
3207 qstrcpy(msg,
"'\\r'");
3210 qstrcpy(msg,
"'\\\"'");
3213 qstrcpy(msg,
"'\\\''");
3216 qstrcpy(msg,
"'\\\\'");
3219 if (c < 0x20 || c >= 0x7F)
3220 std::snprintf(msg, 16,
"'\\x%02x'", c);
3222 std::snprintf(msg, 16,
"'%c'" , c);
3228
3232 char *msg =
new char[1];
3236 char *msg =
new char[strlen(str) + 1];
3237 return qstrcpy(msg, str);
3241
3244 char *msg =
new char[128];
3245 std::snprintf(msg, 128,
"%p", p);
3250
3254 return qstrdup(
"<null>");
3256 return QTest::toString(
const_cast<
const QObject*>(vo));
3260
3264 return qstrdup(
"<null>");
3266 const QString &name = o->objectName();
3267 const char *className = o->metaObject()->className();
3268 char *msg =
new char[256];
3270 std::snprintf(msg, 256,
"%s/%p", className, o);
3272 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3278
3279
3282
3283
3286
3287
3290
3291
3294
3295
3298
3299
3302
3304 const char *expected,
const char *file,
int line)
3306 auto formatter = Internal::genericToString<
const char *>;
3307 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3308 &t1, &t2, formatter, formatter,
3309 actual, expected, file, line);
3313
3314
3315
3318
3319
3322
3323
3326
3327
3330
3331
3334
3335
3338
3339
3342
3343
3346
3347
3350
3351
3354
3355
3358
3359
3362
3363
3366
3367
3370
3371
3374
3375
3378
3379
3382
3383
3386
3387
3390
3391
3394
3395
3398
3399
3402
3403
3406
3407
3410
3411
3414
3415
3418
3419
3422
3423
3426
3427
3430
3431
3434
3435
3438
3439
3442
3443
3446
3447
3450
3451
3454
3455
3458
3459
3462
3463
static QMetaMethod findMethod(const QObject *obj, const char *signature)
TestMethods(const QObject *o, MetaMethods m={})
void invokeTests(QObject *testObject) const
Q_TESTLIB_EXPORT int lastMouseTimestamp
Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
constexpr qsizetype PrettyUnicodeMaxIncrement
void runWithWatchdog(std::optional< WatchDog > &watchDog, Functor &&f)
Q_TESTLIB_EXPORT int qRun()
Q_TESTLIB_EXPORT bool currentTestResolved()
bool reportResult(bool success, const void *lhs, const void *rhs, const char *(*lhsFormatter)(const void *), const char *(*rhsFormatter)(const void *), const char *lhsExpr, const char *rhsExpr, ComparisonOperation op, const char *file, int line)
Q_TESTLIB_EXPORT bool qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected, const char *file, int line)
constexpr qsizetype PrettyUnicodeMaxOutputSize
static void invokeTestMethodIfExists(const char *methodName, QObject *obj=QTest::currentTestObject)
Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool qml)
Q_TESTLIB_EXPORT bool compare_3way_helper(bool success, const char *failureMsg, const void *lhsPtr, const void *rhsPtr, const char *(*lhsFormatter)(const void *), const char *(*rhsFormatter)(const void *), const char *lhsStr, const char *rhsStr, const char *(*actualOrderFormatter)(const void *), const char *(*expectedOrderFormatter)(const void *), const void *actualOrderPtr, const void *expectedOrderPtr, const char *expectedExpression, const char *file, int line)
Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description, const char *file, int line)
void * fetchData(QTestData *data, const char *tagName, int typeId)
static QList< QBenchmarkResult > qMedian(const QList< QList< QBenchmarkResult > > &container)
Q_TESTLIB_EXPORT const char * currentTestFunction()
Returns the name of the test function that is currently executed.
Q_TESTLIB_EXPORT bool runningTest()
Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir=nullptr)
static char * writePrettyUnicodeChar(char16_t ch, char *const buffer)
Q_TESTLIB_EXPORT char * toString(const char *)
Q_TESTLIB_EXPORT char * toString(const volatile QObject *)
static void qPrintDataTags(FILE *stream)
Q_TESTLIB_EXPORT void * qElementData(const char *elementName, int metaTypeId)
Q_TESTLIB_EXPORT bool qCompare(int t1, int t2, const char *actual, const char *expected, const char *file, int line)
static QObject * currentTestObject
void setThrowOnFail(bool enable) noexcept
Q_TESTLIB_EXPORT char * toString(const volatile void *)
Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, const char *file, int line)
static bool invokeTestMethodIfValid(QMetaMethod m, QObject *obj=QTest::currentTestObject)
static bool qPrintTestSlots(FILE *stream, const char *filter=nullptr, const char *preamble="")
Q_TESTLIB_EXPORT void * qData(const char *tagName, int typeId)
Q_TESTLIB_EXPORT bool qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT bool currentTestFailed()
Returns true if the current test function has failed, otherwise false.
static bool skipBlacklisted
Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line)
void setThrowOnSkip(bool enable) noexcept
char * formatString(const char *prefix, const char *suffix, size_t numArguments,...)
static bool inTestFunction
char * toPrettyCString(const char *p, qsizetype length)
char * toHexRepresentation(const char *ba, qsizetype length)
Returns a pointer to a string that is the string ba represented as a space-separated sequence of hex ...
Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line)
static void printUnknownDataTagError(QLatin1StringView name, QLatin1StringView tag, const QTestTable &lTable, const QTestTable &gTable)
Q_TESTLIB_EXPORT bool qCompare(const QLatin1StringView &t1, QStringView t2, const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT const char * currentGlobalDataTag()
Returns the name of the current global test data.
Q_TESTLIB_EXPORT void failOnWarning()
Q_DECL_COLD_FUNCTION Q_TESTLIB_EXPORT void qCaught(const char *expected, const char *what, const char *file, int line)
Q_TESTLIB_EXPORT bool printAvailableFunctions
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Ignores messages created by qDebug(), qInfo() or qWarning().
Q_TESTLIB_EXPORT void failOnWarning(const char *message)
char * toString(std::chrono::duration< Rep, Period > duration)
Q_TESTLIB_EXPORT void qSkip(const char *message, const char *file, int line)
bool qCompare(QString const &t1, QLatin1StringView const &t2, const char *actual, const char *expected, const char *file, int line)
static int qToInt(const char *str)
Q_TESTLIB_EXPORT char * toString(const QObject *)
char * toPrettyUnicode(QStringView string)
Q_DECL_COLD_FUNCTION Q_TESTLIB_EXPORT void qCaught(const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT const char * currentDataTag()
Returns the name of the current test data.
Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg, const void *actualPtr, const void *expectedPtr, const char *(*actualFormatter)(const void *), const char *(*expectedFormatter)(const void *), const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg, const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT void qCleanup()
Q_TESTLIB_EXPORT void addColumnInternal(int id, const char *name)
static QString mainSourcePath
Q_DECL_COLD_FUNCTION Q_TESTLIB_EXPORT void qFail(const char *message, const char *file, int line)
Q_TESTLIB_EXPORT void * qGlobalData(const char *tagName, int typeId)
Q_TESTLIB_EXPORT bool qCompare(QStringView t1, const QLatin1StringView &t2, const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT const char * currentAppName()
Returns the name of the binary that is currently executed.
static char * toStringFp(T t)
static bool floatingCompare(const T &actual, const T &expected)
static bool signbit(qfloat16 f)
#define TO_STRING_IMPL(TYPE, FORMAT)
static bool installCoverageTool(const char *appname, const char *testname)
#define TO_STRING_FLOAT(TYPE)
static bool isValidSlot(const QMetaMethod &sl)
static void initEnvironment()
static auto decodeNanPayload(T t)
QTestDataSetter(QTestData *data)