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"
702 " -trytimeout ms : Set default timeout for the QTRY_* macros and the qWaitFor()\n"
703 " functions to ms milliseconds.\n"
705 " Benchmarking options:\n"
706#if QT_CONFIG(valgrind)
707 " -callgrind : Use callgrind to time benchmarks\n"
709#ifdef QTESTLIB_USE_PERF_EVENTS
710 " -perf : Use Linux perf events to time benchmarks\n"
711 " -perfcounter name : Use the counter named 'name'\n"
712 " -perfcounterlist : Lists the counters available\n"
714#ifdef HAVE_TICK_COUNTER
715 " -tickcounter : Use CPU tick counters to time benchmarks\n"
717 " -eventcounter : Counts events received during benchmarks\n"
718 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
719 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
720 " -iterations n : Sets the number of accumulation iterations.\n"
721 " -median n : Sets the number of median iterations.\n"
722 " -vb : Print out verbose benchmarking information.\n";
724 for (
int i = 1; i < argc; ++i) {
725 if (strcmp(argv[i],
"-help") == 0 || strcmp(argv[i],
"--help") == 0
726 || strcmp(argv[i],
"/?") == 0) {
727 std::printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
728 " By default, all testfunctions will be run.\n\n"
729 "%s", argv[0], testOptions);
733 " QmlTest options:\n"
734 " -import dir : Specify an import directory.\n"
735 " -plugins dir : Specify a directory where to search for plugins.\n"
736 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
737 " -translation file : Specify the translation file.\n"
738 " -file-selector dir : Specify a file selector for the QML engine.\n");
742 " -help : This help\n");
744 }
else if (strcmp(argv[i],
"-functions") == 0) {
751 }
else if (strcmp(argv[i],
"-datatags") == 0) {
756 }
else if (strcmp(argv[i],
"-txt") == 0) {
757 logFormat = QTestLog::Plain;
758 }
else if (strcmp(argv[i],
"-csv") == 0) {
759 logFormat = QTestLog::CSV;
760 }
else if (strcmp(argv[i],
"-junitxml") == 0) {
761 logFormat = QTestLog::JUnitXML;
762 }
else if (strcmp(argv[i],
"-xunitxml") == 0) {
763 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
764 logFormat = QTestLog::JUnitXML;
765 }
else if (strcmp(argv[i],
"-xml") == 0) {
766 logFormat = QTestLog::XML;
767 }
else if (strcmp(argv[i],
"-lightxml") == 0) {
768 logFormat = QTestLog::LightXML;
769 }
else if (strcmp(argv[i],
"-teamcity") == 0) {
770 logFormat = QTestLog::TeamCity;
771 }
else if (strcmp(argv[i],
"-tap") == 0) {
772 logFormat = QTestLog::TAP;
773 }
else if (strcmp(argv[i],
"-silent") == 0) {
774 QTestLog::setVerboseLevel(-1);
775 }
else if (strcmp(argv[i],
"-v1") == 0) {
776 QTestLog::setVerboseLevel(1);
777 }
else if (strcmp(argv[i],
"-v2") == 0) {
778 QTestLog::setVerboseLevel(2);
779 }
else if (strcmp(argv[i],
"-vs") == 0) {
780 QSignalDumper::setEnabled(
true);
781 }
else if (strcmp(argv[i],
"-o") == 0) {
783 std::fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
788 char *filename =
new char[strlen(argv[i])+1];
789 char *format =
new char[strlen(argv[i])+1];
790 if (
std::sscanf(argv[i],
"%[^,],%s", filename, format) == 1) {
792 logFilename = argv[i];
795 if (strcmp(format,
"txt") == 0)
796 logFormat = QTestLog::Plain;
797 else if (strcmp(format,
"csv") == 0)
798 logFormat = QTestLog::CSV;
799 else if (strcmp(format,
"lightxml") == 0)
800 logFormat = QTestLog::LightXML;
801 else if (strcmp(format,
"xml") == 0)
802 logFormat = QTestLog::XML;
803 else if (strcmp(format,
"junitxml") == 0)
804 logFormat = QTestLog::JUnitXML;
805 else if (strcmp(format,
"xunitxml") == 0) {
806 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
807 logFormat = QTestLog::JUnitXML;
808 }
else if (strcmp(format,
"teamcity") == 0)
809 logFormat = QTestLog::TeamCity;
810 else if (strcmp(format,
"tap") == 0)
811 logFormat = QTestLog::TAP;
813 std::fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
816 if (strcmp(filename,
"-") == 0 && QTestLog::loggerUsingStdout()) {
817 std::fprintf(stderr,
"only one logger can log to stdout\n");
820 QTestLog::addLogger(QTestLog::LogMode(logFormat), filename);
824 }
else if (strcmp(argv[i],
"-eventdelay") == 0) {
826 std::fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
831 }
else if (strcmp(argv[i],
"-keydelay") == 0) {
833 std::fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
838 }
else if (strcmp(argv[i],
"-mousedelay") == 0) {
840 std::fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
845 }
else if (strcmp(argv[i],
"-maxwarnings") == 0) {
847 std::fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
850 QTestLog::setMaxWarnings(qToInt(argv[++i]));
852 }
else if (strcmp(argv[i],
"-repeat") == 0) {
854 std::fprintf(stderr,
"-repeat needs an extra parameter for the number of repetitions\n");
859 }
else if (strcmp(argv[i],
"-nocrashhandler") == 0) {
861 }
else if (strcmp(argv[i],
"-skipblacklisted") == 0) {
863 }
else if (strcmp(argv[i],
"-trytimeout") == 0) {
865 std::fprintf(stderr,
"-trytimeout needs an extra parameter to indicate the timeout(ms)\n");
868 QTest::defaultTryTimeout.store(std::chrono::milliseconds{qToInt(argv[++i])},
869 std::memory_order_relaxed);
871#if QT_CONFIG(valgrind)
872 }
else if (strcmp(argv[i],
"-callgrind") == 0) {
873 if (!QBenchmarkValgrindUtils::haveValgrind()) {
875 "WARNING: Valgrind not found or too old. "
876 "Make sure it is installed and in your path. "
877 "Using the walltime measurer.\n");
878 }
else if (QFileInfo(QDir::currentPath()).isWritable()) {
879 QBenchmarkGlobalData::current->setMode(
880 QBenchmarkGlobalData::CallgrindParentProcess);
883 "WARNING: Current directory not writable. "
884 "Using the walltime measurer.\n");
886 }
else if (strcmp(argv[i],
"-callgrindchild") == 0) {
887 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
888 QBenchmarkGlobalData::current->callgrindOutFileBase =
889 QBenchmarkValgrindUtils::outFileBase();
891#ifdef QTESTLIB_USE_PERF_EVENTS
892 }
else if (strcmp(argv[i],
"-perf") == 0) {
893 if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
895 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
897 std::fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
899 }
else if (strcmp(argv[i],
"-perfcounter") == 0) {
901 std::fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
904 QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
906 }
else if (strcmp(argv[i],
"-perfcounterlist") == 0) {
907 QBenchmarkPerfEventsMeasurer::listCounters();
910#ifdef HAVE_TICK_COUNTER
911 }
else if (strcmp(argv[i],
"-tickcounter") == 0) {
912 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
914 }
else if (strcmp(argv[i],
"-eventcounter") == 0) {
915 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
916 }
else if (strcmp(argv[i],
"-minimumvalue") == 0) {
918 std::fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
921 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
923 }
else if (strcmp(argv[i],
"-minimumtotal") == 0) {
925 std::fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
928 QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
930 }
else if (strcmp(argv[i],
"-iterations") == 0) {
932 std::fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
935 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
937 }
else if (strcmp(argv[i],
"-median") == 0) {
939 std::fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
942 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
945 }
else if (strcmp(argv[i],
"-vb") == 0) {
946 QBenchmarkGlobalData::current->verboseOutput =
true;
947#if defined(Q_OS_DARWIN)
948 }
else if (strncmp(argv[i],
"-Apple", 6) == 0) {
951# if defined(HAVE_XCTEST)
952 }
else if (
int skip = QXcodeTestLogger::parseCommandLineArgument(argv[i])) {
957 }
else if (argv[i][0] ==
'-') {
958 std::fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[i], testOptions);
960 std::fprintf(stderr,
"\nqmltest related options:\n"
961 " -import : Specify an import directory.\n"
962 " -plugins : Specify a directory where to search for plugins.\n"
963 " -input : Specify the root directory for test cases.\n");
966 std::fprintf(stderr,
"\n"
967 " -help : This help\n");
974 for (offset = 0; argv[i][offset]; ++offset) {
975 if (argv[i][offset] ==
':') {
976 if (argv[i][offset + 1] ==
':') {
987 QTest::testFunctions += QString::fromLatin1(argv[i]);
988 QTest::testTags += QString();
990 QTest::testFunctions += QString::fromLatin1(argv[i], colon);
991 QTest::testTags += QString::fromLatin1(argv[i] + colon + 1);
996 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
997 QTestLog::setInstalledTestCoverage(installedTestCoverage);
1001 const bool explicitLoggerRequested = logFormat != -1;
1002 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
1003 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
1005 bool addFallbackLogger = !explicitLoggerRequested;
1007#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
1009 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
1010 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1011 QTestLog::addLogger(QTestLog::Apple,
nullptr);
1012 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
1013 addFallbackLogger =
false;
1017 if (addFallbackLogger)
1018 QTestLog::addLogger(QTestLog::Plain, logFilename);
1020 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
1021 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
1028 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
1033 const int count = container.size();
1038 return container.front();
1040 QList<QList<QBenchmarkResult>> containerCopy = container;
1041 std::sort(containerCopy.begin(), containerCopy.end(),
1042 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
1043 return a.first() < b.first();
1046 const int middle = count / 2;
1049 return containerCopy.at(middle);
1056 QTestResult::setCurrentTestData(data);
1060 QTestResult::setCurrentTestData(
nullptr);
1064void TestMethods::invokeTestOnData(
int index)
const
1068 bool isBenchmark =
false;
1069 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1071 QList<QList<QBenchmarkResult>> resultsList;
1072 bool minimumTotalReached =
false;
1074 QBenchmarkTestMethodData::current->beginDataRun();
1076 QBenchmarkTestMethodData::current->iterationCount = 1;
1082 invokeTestMethodIfValid(m_initMethod);
1084 const bool initQuit = QTest::currentTestResolved();
1086 QBenchmarkTestMethodData::current->results.clear();
1087 QBenchmarkTestMethodData::current->resultAccepted =
false;
1088 QBenchmarkTestMethodData::current->valid =
false;
1090 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1091 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1093 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1095 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1097 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1103 QTestResult::finishedCurrentTestData();
1106 invokeTestMethodIfValid(m_cleanupMethod);
1110 if (QCoreApplication::instance())
1111 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1116 QTestResult::finishedCurrentTestDataCleanup();
1122 }
while (invokeOk && !QTest::currentTestResolved() && isBenchmark
1123 && !QBenchmarkTestMethodData::current->resultsAccepted());
1125 QBenchmarkTestMethodData::current->endDataRun();
1126 if (!QTest::currentTestResolved()) {
1128 resultsList.append(QBenchmarkTestMethodData::current->results);
1130 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1131 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1133 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1134 QString pattern = i < 0 ?
"warmup stage result : %1 std.dev: %2"_L1
1135 :
"accumulation stage result: %1 std.dev: %2"_L1;
1136 QTestLog::info(qPrintable(pattern.arg(first.measurement.value, 0,
'f', 3)
1137 .arg(sqrt(first.measurement.variance), 0,
'e', 2)),
1144 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1145 minimumTotalReached =
true;
1147 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1149 current += r.first().measurement.value;
1152 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1153 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1155 }
while (isBenchmark && !QTest::currentTestResolved()
1156 && (++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()
1158 || !minimumTotalReached));
1162 bool testPassed = !QTest::currentTestResolved();
1163 QTestResult::finishedCurrentTestDataCleanup();
1165 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1166 QTestLog::addBenchmarkResults(qMedian(resultsList));
1170#if QT_CONFIG(thread)
1267 qFatal(
"Test function timed out");
1290template <
typename Functor>
1294 watchDog->beginTest();
1299 watchDog->testFinished();
1303 const QTestTable &lTable,
const QTestTable &gTable)
1305 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1306 const int localDataCount = lTable.dataCount();
1307 if (localDataCount) {
1308 std::fputs(
"Available test-specific data tags:\n", stderr);
1309 for (
int i = 0; i < localDataCount; ++i)
1310 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1312 const int globalDataCount = gTable.dataCount();
1313 if (globalDataCount) {
1314 std::fputs(
"Available global data tags:\n", stderr);
1315 for (
int i = 0; i < globalDataCount; ++i)
1316 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1318 if (localDataCount == 0 && globalDataCount == 0)
1319 std::fputs(
"Function has no data tags\n", stderr);
1323
1324
1325
1326
1327
1330 QBenchmarkTestMethodData benchmarkData;
1331 QBenchmarkTestMethodData::current = &benchmarkData;
1333 const QByteArray &name = m_methods[index].name();
1334 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1339 QTestResult::setCurrentTestFunction(name.constData());
1341 const QTestTable *gTable = QTestTable::globalTestTable();
1342 const int globalDataCount = gTable->dataCount();
1343 int curGlobalDataIndex = 0;
1344 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1345 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1348 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1349 QLatin1StringView global) {
1352 if (tag == local || tag == global)
1355 return tag.startsWith(global) && tag.endsWith(local) &&
1356 tag.size() == global.size() + 1 + local.size() &&
1357 tag[global.size()] ==
':';
1359 bool foundFunction =
false;
1360 bool blacklisted =
false;
1364 if (!gTable->isEmpty())
1365 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1367 if (curGlobalDataIndex == 0) {
1368 std::snprintf(member, 512,
"%s_data()", name.constData());
1369 runWithWatchdog(watchDog, [&member] {
1372 if (QTestResult::skipCurrentTest())
1376 int curDataIndex = 0;
1377 const int dataCount = table.dataCount();
1378 const auto dataTag = [&table, dataCount](
int index) {
1379 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1384 QTestResult::setSkipCurrentTest(
false);
1385 QTestResult::setBlacklistCurrentTest(
false);
1386 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1387 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1388 foundFunction =
true;
1389 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1390 globalDataTag(curGlobalDataIndex));
1392 QTestResult::setBlacklistCurrentTest(
true);
1395 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1397 QTestResult::finishedCurrentTestData();
1398 QTestResult::finishedCurrentTestDataCleanup();
1401 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1403 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1409 runWithWatchdog(watchDog, [
this, index] {
1410 invokeTestOnData(index);
1414 if (!tag.isEmpty() && !globalDataCount)
1418 }
while (curDataIndex < dataCount);
1420 QTestResult::setCurrentGlobalTestData(
nullptr);
1421 ++curGlobalDataIndex;
1422 }
while (curGlobalDataIndex < globalDataCount);
1424 if (!tag.isEmpty() && !foundFunction) {
1425 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1426 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1428 QTestResult::finishedCurrentTestFunction();
1429 QTestResult::setSkipCurrentTest(
false);
1430 QTestResult::setBlacklistCurrentTest(
false);
1433void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1435 QTEST_ASSERT(typeId);
1436 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1437 QTEST_ASSERT(data->parent());
1439 int idx = data->parent()->indexOf(tagName);
1441 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1442 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1446 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1447 qFatal(
"Requested type '%s' does not match available type '%s'.",
1448 QMetaType(typeId).name(),
1449 QMetaType(data->parent()->elementTypeId(idx)).name());
1452 return data->data(idx);
1456
1457
1458char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1461 va_start(ap, numArguments);
1463 QByteArray arguments;
1464 arguments += prefix;
1466 if (numArguments > 0) {
1467 arguments += va_arg(ap,
const char *);
1469 for (size_t i = 1; i < numArguments; ++i) {
1471 arguments += va_arg(ap,
const char *);
1476 arguments += suffix;
1477 return qstrdup(arguments.constData());
1481
1482
1483
1484
1485
1486
1487
1488
1489
1496
1497
1498
1499
1500
1501
1502 const qsizetype maxLen = 50;
1503 const qsizetype len = qMin(maxLen, length);
1504 char *result =
nullptr;
1506 if (length > maxLen) {
1507 const qsizetype size = len * 3 + 4;
1508 result =
new char[size];
1510 char *
const forElipsis = result + size - 5;
1511 forElipsis[0] =
' ';
1512 forElipsis[1] =
'.';
1513 forElipsis[2] =
'.';
1514 forElipsis[3] =
'.';
1515 result[size - 1] =
'\0';
1518 const qsizetype size = len * 3;
1519 result =
new char[size];
1520 result[size - 1] =
'\0';
1527 const char at = ba[i];
1529 result[o] = toHexUpper(at >> 4);
1531 result[o] = toHexUpper(at);
1545
1546
1547
1548
1551 bool trimmed =
false;
1552 auto buffer =
std::make_unique<
char[]>(256);
1553 const char *end = p + length;
1554 char *dst = buffer.get();
1556 bool lastWasHexEscape =
false;
1558 for ( ; p != end; ++p) {
1564 if (dst - buffer.get() > 246) {
1571 if (Q_UNLIKELY(lastWasHexEscape)) {
1572 if (fromHex(*p) != -1) {
1577 lastWasHexEscape =
false;
1580 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1611 *dst++ = toHexUpper(uchar(*p) >> 4);
1612 *dst++ = toHexUpper(uchar(*p));
1613 lastWasHexEscape =
true;
1625 return buffer.release();
1629
1630
1631
1632
1633
1634
1635
1644 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1645 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1674 *dst++ = toHexUpper(ch >> 12);
1675 *dst++ = toHexUpper(ch >> 8);
1676 *dst++ = toHexUpper(ch >> 4);
1677 *dst++ = toHexUpper(ch);
1685 auto p = string.utf16();
1686 auto length = string.size();
1688 bool trimmed =
false;
1689 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1690 const auto end = p + length;
1691 char *dst = buffer.get();
1694 for ( ; p != end; ++p) {
1695 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1699 dst = writePrettyUnicodeChar(*p, dst);
1709 return buffer.release();
1714 const QMetaObject *metaObject = testObject->metaObject();
1715 QTEST_ASSERT(metaObject);
1718 if (!CrashHandler::alreadyDebugging()
1719#if QT_CONFIG(valgrind)
1720 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1726 QTestResult::setCurrentTestFunction(
"initTestCase");
1727 runWithWatchdog(watchDog, [
this, testObject] {
1728 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1731 QSignalDumper::startDump();
1733 if (!QTest::currentTestResolved()) {
1735 runWithWatchdog(watchDog, [
this, testObject] {
1736 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1740 const bool previousFailed = QTestResult::currentTestFailed();
1741 QTestResult::finishedCurrentTestData();
1742 QTestResult::finishedCurrentTestDataCleanup();
1743 QTestResult::finishedCurrentTestFunction();
1745 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1746 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1747 const char *data =
nullptr;
1748 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1749 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1750 invokeTest(i, QLatin1StringView(data), watchDog);
1755 const bool wasSkipped = QTestResult::skipCurrentTest();
1756 QTestResult::setSkipCurrentTest(
false);
1757 QTestResult::setBlacklistCurrentTest(
false);
1758 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1759 runWithWatchdog(watchDog, [
this, testObject] {
1760 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1763 QTestResult::finishedCurrentTestData();
1765 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1766 QTestResult::finishedCurrentTestDataCleanup();
1768 QTestResult::finishedCurrentTestFunction();
1769 QTestResult::setCurrentTestFunction(
nullptr);
1771 QSignalDumper::endDump();
1774#if QT_DEPRECATED_SINCE(6
, 8
)
1793 const char *(*lhsFormatter)(
const void*),
1794 const char *(*rhsFormatter)(
const void*),
1795 const char *lhsExpr,
const char *rhsExpr,
1796 ComparisonOperation op,
const char *file,
int line)
1798 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1799 lhsExpr, rhsExpr, op, file, line);
1805 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1809static QFile androidExitCodeFile()
1811 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1812 return QFile(testHome +
"/qtest_last_exit_code"_L1);
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
1844
1845
1846
1847
1848
1849
1850
1851
1852
1854int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1860 qInit(testObject, argc, argv);
1864#if defined(Q_OS_WASM)
1866 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1867 Module.notifyTestFinished($0);
1875
1876void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1879 CrashHandler::maybeDisableCoreDump();
1880 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1882#if defined(Q_OS_MACOS)
1884 QTestPrivate::disableWindowRestore();
1887 if (!appNapDisabler)
1888 appNapDisabler.emplace();
1890 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1891 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1892 &macPowerSavingDisabled);
1895 QTestPrivate::parseBlackList();
1896 QTestResult::reset();
1898 QTEST_ASSERT(testObject);
1899 QTEST_ASSERT(!currentTestObject);
1902 const QMetaObject *metaObject = testObject->metaObject();
1903 QTEST_ASSERT(metaObject);
1905 QTestResult::setCurrentTestObject(metaObject->className());
1907 QTestResult::setCurrentAppName(argv[0]);
1911#if QT_CONFIG(valgrind)
1912 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1914 QTestLog::startLogging();
1917 androidExitCodeFile().remove();
1922
1925 QTEST_ASSERT(currentTestObject);
1927#if QT_CONFIG(valgrind)
1928 int callgrindChildExitCode = 0;
1931#ifndef QT_NO_EXCEPTIONS
1935#if QT_CONFIG(valgrind)
1936 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1937 if (Q_UNLIKELY(!qApp))
1938 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1940 const QStringList origAppArgs(QCoreApplication::arguments());
1941 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1944 QBenchmarkValgrindUtils::cleanup();
1949 std::optional<CrashHandler::FatalSignalHandler> handler;
1950 CrashHandler::prepareStackTrace();
1954 TestMethods::MetaMethods commandLineMethods;
1955 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1956 std::vector<size_t> badFunctionIndices;
1958 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1959 const QByteArray tfB = tf.toLatin1();
1960 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1961 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1962 if (m.isValid() && isValidSlot(m)) {
1963 commandLineMethods.push_back(m);
1965 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1966 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1967 std::fputc(
'\n', stderr);
1968 QTestResult::setCurrentTestFunction(tfB.constData());
1969 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1970 QTestResult::finishedCurrentTestFunction();
1972 badFunctionIndices.insert(badFunctionIndices.begin(), index);
1976 if (badFunctionIndices.size() > 0) {
1978 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1979 QTestResult::currentAppName());
1980 if (commandLineMethods.empty())
1986 for (size_t i : std::as_const(badFunctionIndices)) {
1993 QTest::testFunctions.removeAt(i);
1994 QTest::testTags.removeAt(i);
2002 const int badArgCount = QTestLog::failCount();
2003 while (!(QTestLog::failCount() > badArgCount)
2004 && (repeatForever || remainingRepetitions-- > 0)) {
2005 QTestTable::globalTestTable();
2006 test.invokeTests(currentTestObject);
2007 QTestTable::clearGlobalTestTable();
2011#ifndef QT_NO_EXCEPTIONS
2013 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
2014 if (QTestResult::currentTestFunction()) {
2015 QTestResult::finishedCurrentTestFunction();
2016 QTestResult::setCurrentTestFunction(
nullptr);
2027#if QT_CONFIG(valgrind)
2028 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2029 return callgrindChildExitCode;
2033 const int exitCode = qMin(QTestLog::failCount(), 127);
2036 QFile exitCodeFile = androidExitCodeFile();
2037 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2038 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2040 qWarning(
"Failed to open %s for writing test exit code: %s",
2041 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2049
2054#if QT_CONFIG(valgrind)
2055 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2057 QTestLog::stopLogging();
2059 delete QBenchmarkGlobalData::current;
2060 QBenchmarkGlobalData::current =
nullptr;
2062#if defined(Q_OS_MACOS)
2063 IOPMAssertionRelease(macPowerSavingDisabled);
2064 appNapDisabler = std::nullopt;
2068#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2081 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2084QList<QString> QTest::qGetTestCaseNames()
2086 return QTest::TestRegistry::instance()->getAllTestNames();
2089QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2091 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2097
2098
2099
2100
2101
2102
2103int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2105 const int argc = arguments.size();
2106 QVarLengthArray<
char *> argv(argc);
2108 QList<QByteArray> args;
2111 for (
int i = 0; i < argc; ++i)
2113 args.append(arguments.at(i).toLocal8Bit().constData());
2114 argv[i] = args.last().data();
2117 return qExec(testObject, argc, argv.data());
2121
2122void QTest::
qFail(
const char *message,
const char *file,
int line)
2124 QTestResult::fail(message, file, line);
2128
2129bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2130 const char *file,
int line)
2132 return QTestResult::verify(statement, statementStr, description, file, line);
2136
2137
2138void QTest::
qSkip(
const char *message,
const char *file,
int line)
2140 QTestResult::addSkip(message, file, line);
2141 QTestResult::setSkipCurrentTest(
true);
2145
2146
2148 QTest::TestFailMode mode,
const char *file,
int line)
2150 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2171 auto message = [&] {
2172 const auto exType = what ?
"std::" :
"unknown ";
2173 const auto ofType = expected ?
" of type " :
"";
2174 const auto no = expected ?
"an" :
"no";
2175 const auto withMsg = what ?
" with message " :
"";
2176 const auto protect = [](
const char *s) {
return s ? s :
""; };
2178 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2179 "but caught %sexception%s%s",
2180 no, ofType, protect(expected),
2181 exType, withMsg, protect(what));
2183 qFail(message().toUtf8().constData(), file, line);
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2209 std::rethrow_exception(
std::current_exception());
2210 }
catch (
const std::exception &e) {
2211 qCaught(expected, e.what(), file, line);
2213 qCaught(expected,
nullptr, file, line);
2220#if QT_DEPRECATED_SINCE(6
, 3
)
2222
2223
2224
2225void QTest::qWarn(
const char *message,
const char *file,
int line)
2227 QTestLog::warn(message, file, line);
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2251 QTestLog::ignoreMessage(type, message);
2254#if QT_CONFIG(regularexpression)
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2272 QTestLog::ignoreMessage(type, messagePattern);
2277
2278
2280
2281
2282
2283
2286 return QTestLog::failOnWarning();
2290
2291
2293
2294
2295
2296
2299 return QTestLog::failOnWarning(message);
2302#if QT_CONFIG(regularexpression)
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2357 QTestLog::failOnWarning(messagePattern);
2362
2365static inline bool isWindowsBuildDirectory(
const QString &dirName)
2367 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2368 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2372#if QT_CONFIG(temporaryfile)
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2385 QSharedPointer<QTemporaryDir> result;
2387 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2389 tempDir->setAutoRemove(
true);
2391 if (!tempDir->isValid())
2394 const QString dataPath = tempDir->path();
2395 const QString resourcePath = u':' + dirName;
2396 const QFileInfo fileInfo(resourcePath);
2398 if (!fileInfo.isDir()) {
2399 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2403 bool isResourceDirEmpty =
true;
2404 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2405 isResourceDirEmpty =
false;
2406 if (!dirEntry.isDir()) {
2407 const QString &filePath = dirEntry.filePath();
2408 const QString destination =
2409 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2410 QFileInfo destinationFileInfo(destination);
2411 QDir().mkpath(destinationFileInfo.path());
2412 QFile file(filePath);
2413 if (!file.copy(destination, QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2414 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2415 qUtf16Printable(file.errorString()));
2421 if (isResourceDirEmpty) {
2422 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2426 result = std::move(tempDir);
2433
2435QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2436 const char *sourcedir)
2444 QDir binDirectory(QCoreApplication::applicationDirPath());
2445 if (binDirectory.exists(base)) {
2446 found = binDirectory.absoluteFilePath(base);
2451 else if (isWindowsBuildDirectory(binDirectory.dirName())
2452 && binDirectory.cdUp() && binDirectory.exists(base)) {
2453 found = binDirectory.absoluteFilePath(base);
2456 else if (QTestLog::verboseLevel() >= 2) {
2457 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2458 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2459 "checking next location"_L1.arg(base, candidate)),
2465 if (found.isEmpty()) {
2466 const char *testObjectName = QTestResult::currentTestObjectName();
2467 if (testObjectName) {
2468 const QStringList testsPaths = QLibraryInfo::paths(QLibraryInfo::TestsPath);
2469 for (
const QString &testsPath : testsPaths) {
2470 const QString candidate =
"%1/%2/%3"_L1
2471 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2472 if (QFileInfo::exists(candidate)) {
2474 }
else if (QTestLog::verboseLevel() >= 2) {
2475 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2476 "checking next location"_L1
2477 .arg(base, QDir::toNativeSeparators(candidate))),
2485 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2487 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2491 if (!srcdir.isAbsolute() && builddir)
2492 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2494 const QString canonicalPath = srcdir.canonicalFilePath();
2495 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2496 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2498 }
else if (QTestLog::verboseLevel() >= 2) {
2499 QTestLog::info(qPrintable(
2500 "testdata %1 not found relative to source path [%2]"_L1
2501 .arg(base, QDir::toNativeSeparators(candidate))),
2507 if (found.isEmpty()) {
2508 const QString candidate =
":/%1"_L1.arg(base);
2509 if (QFileInfo::exists(candidate)) {
2511 }
else if (QTestLog::verboseLevel() >= 2) {
2512 QTestLog::info(qPrintable(
2513 "testdata %1 not found in resources [%2]"_L1
2514 .arg(base, QDir::toNativeSeparators(candidate))),
2520 if (found.isEmpty()) {
2521 const QString candidate = QDir::currentPath() + u'/' + base;
2522 if (QFileInfo::exists(candidate)) {
2524 }
else if (QTestLog::verboseLevel() >= 2) {
2525 QTestLog::info(qPrintable(
2526 "testdata %1 not found in current directory [%2]"_L1
2527 .arg(base, QDir::toNativeSeparators(candidate))),
2533 if (found.isEmpty()) {
2534 const QString candidate = QTest::mainSourcePath % u'/' % base;
2535 if (QFileInfo::exists(candidate)) {
2537 }
else if (QTestLog::verboseLevel() >= 2) {
2538 QTestLog::info(qPrintable(
2539 "testdata %1 not found in main source directory [%2]"_L1
2540 .arg(base, QDir::toNativeSeparators(candidate))),
2546 if (found.isEmpty() && sourcedir) {
2547 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2548 if (QFileInfo::exists(candidate)) {
2550 }
else if (QTestLog::verboseLevel() >= 2) {
2551 QTestLog::info(qPrintable(
2552 "testdata %1 not found in supplied source directory [%2]"_L1
2553 .arg(base, QDir::toNativeSeparators(candidate))),
2559 if (found.isEmpty()) {
2560 QTestLog::warn(qPrintable(
2561 "testdata %1 could not be located!"_L1.arg(base)),
2563 }
else if (QTestLog::verboseLevel() >= 1) {
2564 QTestLog::info(qPrintable(
2565 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2573
2574QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2575 const char *sourcedir)
2577 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2581
2584 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2588
2591 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2595
2598 QTEST_ASSERT(tagName);
2599 QTestData *data = QTestResult::currentTestData();
2601 QTEST_ASSERT(data->parent());
2603 int idx = data->parent()->indexOf(tagName);
2604 QTEST_ASSERT(idx != -1);
2605 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2607 return data->data(data->parent()->indexOf(tagName));
2611
2614 QTestTable *tbl = QTestTable::currentTestTable();
2615 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2617 tbl->addColumn(id, name);
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640QTestData &
QTest::newRow(
const char *dataTag)
2642 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2643 QTestTable *tbl = QTestTable::currentTestTable();
2644 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2645 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2646 "Must add columns before attempting to add rows.");
2648 return *tbl->newData(dataTag);
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678QTestData &
QTest::addRow(
const char *format, ...)
2680 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2681 QTestTable *tbl = QTestTable::currentTestTable();
2682 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2683 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2684 "Must add columns before attempting to add rows.");
2689 va_start(va, format);
2692 std::vsnprintf(buf,
sizeof buf, format, va);
2695 return *tbl->newData(buf);
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2720
2721
2724 return QTestResult::currentAppName();
2728
2729
2730
2731
2732
2733
2736 return QTestResult::currentTestFunction();
2740
2741
2742
2745 return QTestResult::currentDataTag();
2749
2750
2751
2752
2753
2756 return QTestResult::currentGlobalDataTag();
2760
2761
2762
2763
2766 return QTestResult::currentTestFailed();
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2784 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2788
2789
2790
2791
2792
2793
2794
2801
2804 return currentTestObject;
2808
2811 QString mainSourceFile = QFile::decodeName(file);
2814 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2816 fi.setFile(mainSourceFile);
2820#if QT_DEPRECATED_SINCE(6
, 4
)
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839bool QTest::compare_helper(
bool success,
const char *failureMsg,
2840 char *actualVal,
char *expectedVal,
2841 const char *actual,
const char *expected,
2842 const char *file,
int line)
2844 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2845 actual, expected, file, line);
2849#if QT_DEPRECATED_SINCE(6
, 8
)
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863bool QTest::compare_helper(
bool success,
const char *failureMsg,
2864 qxp::function_ref<
const char *()> actualVal,
2865 qxp::function_ref<
const char *()> expectedVal,
2866 const char *actual,
const char *expected,
2867 const char *file,
int line)
2869 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2870 QTest::functionRefFormatter,
2871 QTest::functionRefFormatter, actual, expected,
2872 QTest::ComparisonOperation::CustomCompare,
2873 file, line, failureMsg);
2878
2879
2880
2881
2882
2883
2884
2885
2888 const void *actualPtr,
const void *expectedPtr,
2889 const char *(*actualFormatter)(
const void *),
2890 const char *(*expectedFormatter)(
const void *),
2891 const char *actual,
const char *expected,
2892 const char *file,
int line)
2894 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2895 actualFormatter, expectedFormatter,
2897 QTest::ComparisonOperation::CustomCompare,
2898 file, line, failureMsg);
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2930 const void *lhsPtr,
const void *rhsPtr,
2931 const char *(*lhsFormatter)(
const void*),
2932 const char *(*rhsFormatter)(
const void*),
2933 const char *lhsExpression,
const char *rhsExpression,
2934 const char *(*actualOrderFormatter)(
const void *),
2935 const char *(*expectedOrderFormatter)(
const void *),
2936 const void *actualOrderPtr,
const void *expectedOrderPtr,
2937 const char *expectedExpression,
2938 const char *file,
int line)
2940 return QTestResult::report3WayResult(success, failureMsg,
2942 lhsFormatter, rhsFormatter,
2943 lhsExpression, rhsExpression,
2944 actualOrderFormatter,
2945 expectedOrderFormatter,
2946 actualOrderPtr, expectedOrderPtr,
2952
2953
2954
2955
2956
2957
2958
2959
2960
2962 const char *expected,
const char *file,
int line)
2964 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2967template <
typename T>
2970 switch (qFpClassify(expected))
2973 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2975 return qFpClassify(actual) == FP_NAN;
2977 if (!qFuzzyIsNull(expected))
2978 return qFuzzyCompare(actual, expected);
2982 return qFuzzyIsNull(actual);
2987
2988
2989bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2990 const char *file,
int line)
2992 auto formatter = Internal::genericToString<qfloat16>;
2993 return compare_helper(floatingCompare(t1, t2),
2994 "Compared qfloat16s are not the same (fuzzy compare)",
2995 &t1, &t2, formatter, formatter,
2996 actual, expected, file, line);
3000
3001
3002bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
3003 const char *file,
int line)
3005 return QTestResult::compare(floatingCompare(t1, t2),
3006 "Compared floats are not the same (fuzzy compare)",
3007 t1, t2, actual, expected, file, line);
3011
3012
3013bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
3014 const char *file,
int line)
3016 return QTestResult::compare(floatingCompare(t1, t2),
3017 "Compared doubles are not the same (fuzzy compare)",
3018 t1, t2, actual, expected, file, line);
3022
3023
3024
3026 const char *file,
int line)
3028 return QTestResult::compare(t1 == t2,
3029 "Compared values are not the same",
3030 t1, t2, actual, expected, file, line);
3033#if QT_POINTER_SIZE == 8
3035
3036
3037
3039bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3040 const char *file,
int line)
3042 return QTestResult::compare(t1 == t2,
3043 "Compared values are not the same",
3044 t1, t2, actual, expected, file, line);
3049
3050
3051
3052bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3053 const char *file,
int line)
3055 return QTestResult::compare(t1 == t2,
3056 "Compared values are not the same",
3057 t1, t2, actual, expected, file, line);
3061
3062
3063
3064bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3065 const char *file,
int line)
3067 return QTestResult::compare(t1 == t2,
3068 "Compared values are not the same",
3069 t1, t2, actual, expected, file, line);
3073
3074
3075
3076bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3077 const char *file,
int line)
3079 return QTestResult::compare(t1 == t2,
3080 "Compared values are not the same",
3081 t1, t2, actual, expected, file, line);
3085
3086
3087
3088bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3089 const char *file,
int line)
3091 return QTestResult::compare(t1 == t2,
3092 "Compared values are not the same",
3093 t1, t2, actual, expected, file, line);
3097
3098
3099
3102
3103
3104
3107
3108
3109
3112
3113
3116
3117
3119#define TO_STRING_IMPL(TYPE, FORMAT) template
3120 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3121{
3122 char *msg = new char[128
];
3123 std::snprintf(msg, 128
, #FORMAT, t);
3125}
3142 constexpr int Digits =
std::numeric_limits<T>::digits;
3143 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3144 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3145 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3151 Q_ASSERT(qIsNaN(t));
3152 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3153 r.payload = u & PayloadMask;
3154 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3164 char *msg =
new char[128];
3165 bool negative = signbit(t);
3167 switch (qFpClassify(t)) {
3169 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3172 if (
auto r = decodeNanPayload(t); r.payload) {
3173 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3174 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3176 Q_ASSERT(r.isQuiet);
3177 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3181 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3184 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3191#define TO_STRING_FLOAT(TYPE) template
3192 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3193{
3194 return toStringFp(t); \
3195}
3202 unsigned char c =
static_cast<
unsigned char>(t);
3203 char *msg =
new char[16];
3206 qstrcpy(msg,
"'\\0'");
3209 qstrcpy(msg,
"'\\a'");
3212 qstrcpy(msg,
"'\\b'");
3215 qstrcpy(msg,
"'\\t'");
3218 qstrcpy(msg,
"'\\n'");
3221 qstrcpy(msg,
"'\\v'");
3224 qstrcpy(msg,
"'\\f'");
3227 qstrcpy(msg,
"'\\r'");
3230 qstrcpy(msg,
"'\\\"'");
3233 qstrcpy(msg,
"'\\\''");
3236 qstrcpy(msg,
"'\\\\'");
3239 if (c < 0x20 || c >= 0x7F)
3240 std::snprintf(msg, 16,
"'\\x%02x'", c);
3242 std::snprintf(msg, 16,
"'%c'" , c);
3248
3252 char *msg =
new char[1];
3256 char *msg =
new char[strlen(str) + 1];
3257 return qstrcpy(msg, str);
3261
3264 char *msg =
new char[128];
3265 std::snprintf(msg, 128,
"%p", p);
3270
3274 return qstrdup(
"<null>");
3276 return QTest::toString(
const_cast<
const QObject*>(vo));
3280
3284 return qstrdup(
"<null>");
3286 const QString &name = o->objectName();
3287 const char *className = o->metaObject()->className();
3288 char *msg =
new char[256];
3290 std::snprintf(msg, 256,
"%s/%p", className, o);
3292 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3298
3299
3302
3303
3306
3307
3310
3311
3314
3315
3318
3319
3322
3324 const char *expected,
const char *file,
int line)
3326 auto formatter = Internal::genericToString<
const char *>;
3327 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3328 &t1, &t2, formatter, formatter,
3329 actual, expected, file, line);
3333
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
3466
3467
3470
3471
3474
3475
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)
#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)