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 += QString::fromLatin1(argv[i], colon);
981 QTest::testTags += QString::fromLatin1(argv[i] + colon + 1);
986 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
987 QTestLog::setInstalledTestCoverage(installedTestCoverage);
991 const bool explicitLoggerRequested = logFormat != -1;
992 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
993 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
995 bool addFallbackLogger = !explicitLoggerRequested;
997#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
999 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
1000 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1001 QTestLog::addLogger(QTestLog::Apple,
nullptr);
1002 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
1003 addFallbackLogger =
false;
1007 if (addFallbackLogger)
1008 QTestLog::addLogger(QTestLog::Plain, logFilename);
1010 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
1011 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
1018 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
1023 const int count = container.size();
1028 return container.front();
1030 QList<QList<QBenchmarkResult>> containerCopy = container;
1031 std::sort(containerCopy.begin(), containerCopy.end(),
1032 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
1033 return a.first() < b.first();
1036 const int middle = count / 2;
1039 return containerCopy.at(middle);
1046 QTestResult::setCurrentTestData(data);
1050 QTestResult::setCurrentTestData(
nullptr);
1054void TestMethods::invokeTestOnData(
int index)
const
1058 bool isBenchmark =
false;
1059 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1061 QList<QList<QBenchmarkResult>> resultsList;
1062 bool minimumTotalReached =
false;
1064 QBenchmarkTestMethodData::current->beginDataRun();
1066 QBenchmarkTestMethodData::current->iterationCount = 1;
1072 invokeTestMethodIfValid(m_initMethod);
1074 const bool initQuit =
1075 QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
1077 QBenchmarkTestMethodData::current->results.clear();
1078 QBenchmarkTestMethodData::current->resultAccepted =
false;
1079 QBenchmarkTestMethodData::current->valid =
false;
1081 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1082 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1084 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1086 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1088 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1094 QTestResult::finishedCurrentTestData();
1097 invokeTestMethodIfValid(m_cleanupMethod);
1101 if (QCoreApplication::instance())
1102 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1107 QTestResult::finishedCurrentTestDataCleanup();
1113 }
while (invokeOk && isBenchmark
1114 && QBenchmarkTestMethodData::current->resultsAccepted() ==
false
1115 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1117 QBenchmarkTestMethodData::current->endDataRun();
1118 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1120 resultsList.append(QBenchmarkTestMethodData::current->results);
1122 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1123 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1125 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1126 QString pattern = i < 0 ?
"warmup stage result : %1 std.dev: %2"_L1
1127 :
"accumulation stage result: %1 std.dev: %2"_L1;
1128 QTestLog::info(qPrintable(pattern.arg(first.measurement.value, 0,
'f', 3)
1129 .arg(sqrt(first.measurement.variance), 0,
'e', 2)),
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 TestMethods::MetaMethods commandLineMethods;
1946 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1947 std::vector<size_t> badFunctionIndices;
1949 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1950 const QByteArray tfB = tf.toLatin1();
1951 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1952 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1953 if (m.isValid() && isValidSlot(m)) {
1954 commandLineMethods.push_back(m);
1956 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1957 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1958 std::fputc(
'\n', stderr);
1959 QTestResult::setCurrentTestFunction(tfB.constData());
1960 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1961 QTestResult::finishedCurrentTestFunction();
1963 badFunctionIndices.insert(badFunctionIndices.begin(), index);
1967 if (badFunctionIndices.size() > 0) {
1969 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1970 QTestResult::currentAppName());
1971 if (commandLineMethods.empty())
1977 for (size_t i : std::as_const(badFunctionIndices)) {
1984 QTest::testFunctions.removeAt(i);
1985 QTest::testTags.removeAt(i);
1993 const int badArgCount = QTestLog::failCount();
1994 while (!(QTestLog::failCount() > badArgCount)
1995 && (repeatForever || remainingRepetitions-- > 0)) {
1996 QTestTable::globalTestTable();
1997 test.invokeTests(currentTestObject);
1998 QTestTable::clearGlobalTestTable();
2002#ifndef QT_NO_EXCEPTIONS
2004 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
2005 if (QTestResult::currentTestFunction()) {
2006 QTestResult::finishedCurrentTestFunction();
2007 QTestResult::setCurrentTestFunction(
nullptr);
2018#if QT_CONFIG(valgrind)
2019 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2020 return callgrindChildExitCode;
2024 const int exitCode = qMin(QTestLog::failCount(), 127);
2027 QFile exitCodeFile = androidExitCodeFile();
2028 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2029 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2031 qWarning(
"Failed to open %s for writing test exit code: %s",
2032 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2040
2045#if QT_CONFIG(valgrind)
2046 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2048 QTestLog::stopLogging();
2050 delete QBenchmarkGlobalData::current;
2051 QBenchmarkGlobalData::current =
nullptr;
2053#if defined(Q_OS_MACOS)
2054 IOPMAssertionRelease(macPowerSavingDisabled);
2055 appNapDisabler = std::nullopt;
2059#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2072 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2075QList<QString> QTest::qGetTestCaseNames()
2077 return QTest::TestRegistry::instance()->getAllTestNames();
2080QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2082 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2088
2089
2090
2091
2092
2093
2094int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2096 const int argc = arguments.size();
2097 QVarLengthArray<
char *> argv(argc);
2099 QList<QByteArray> args;
2102 for (
int i = 0; i < argc; ++i)
2104 args.append(arguments.at(i).toLocal8Bit().constData());
2105 argv[i] = args.last().data();
2108 return qExec(testObject, argc, argv.data());
2112
2113void QTest::
qFail(
const char *message,
const char *file,
int line)
2115 QTestResult::fail(message, file, line);
2119
2120bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2121 const char *file,
int line)
2123 return QTestResult::verify(statement, statementStr, description, file, line);
2127
2128
2129void QTest::
qSkip(
const char *message,
const char *file,
int line)
2131 QTestResult::addSkip(message, file, line);
2132 QTestResult::setSkipCurrentTest(
true);
2136
2137
2139 QTest::TestFailMode mode,
const char *file,
int line)
2141 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2162 auto message = [&] {
2163 const auto exType = what ?
"std::" :
"unknown ";
2164 const auto ofType = expected ?
" of type " :
"";
2165 const auto no = expected ?
"an" :
"no";
2166 const auto withMsg = what ?
" with message " :
"";
2167 const auto protect = [](
const char *s) {
return s ? s :
""; };
2169 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2170 "but caught %sexception%s%s",
2171 no, ofType, protect(expected),
2172 exType, withMsg, protect(what));
2174 qFail(message().toUtf8().constData(), file, line);
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2200 std::rethrow_exception(
std::current_exception());
2201 }
catch (
const std::exception &e) {
2202 qCaught(expected, e.what(), file, line);
2204 qCaught(expected,
nullptr, file, line);
2211#if QT_DEPRECATED_SINCE(6
, 3
)
2213
2214
2215
2216void QTest::qWarn(
const char *message,
const char *file,
int line)
2218 QTestLog::warn(message, file, line);
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2242 QTestLog::ignoreMessage(type, message);
2245#if QT_CONFIG(regularexpression)
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2263 QTestLog::ignoreMessage(type, messagePattern);
2268
2269
2271
2272
2273
2274
2277 return QTestLog::failOnWarning();
2281
2282
2284
2285
2286
2287
2290 return QTestLog::failOnWarning(message);
2293#if QT_CONFIG(regularexpression)
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
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2348 QTestLog::failOnWarning(messagePattern);
2353
2356static inline bool isWindowsBuildDirectory(
const QString &dirName)
2358 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2359 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2363#if QT_CONFIG(temporaryfile)
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2376 QSharedPointer<QTemporaryDir> result;
2378 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2380 tempDir->setAutoRemove(
true);
2382 if (!tempDir->isValid())
2385 const QString dataPath = tempDir->path();
2386 const QString resourcePath = u':' + dirName;
2387 const QFileInfo fileInfo(resourcePath);
2389 if (!fileInfo.isDir()) {
2390 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2394 bool isResourceDirEmpty =
true;
2395 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2396 isResourceDirEmpty =
false;
2397 if (!dirEntry.isDir()) {
2398 const QString &filePath = dirEntry.filePath();
2399 const QString destination =
2400 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2401 QFileInfo destinationFileInfo(destination);
2402 QDir().mkpath(destinationFileInfo.path());
2403 QFile file(filePath);
2404 if (!file.copy(destination, QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2405 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2406 qUtf16Printable(file.errorString()));
2412 if (isResourceDirEmpty) {
2413 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2417 result = std::move(tempDir);
2424
2426QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2427 const char *sourcedir)
2435 QDir binDirectory(QCoreApplication::applicationDirPath());
2436 if (binDirectory.exists(base)) {
2437 found = binDirectory.absoluteFilePath(base);
2442 else if (isWindowsBuildDirectory(binDirectory.dirName())
2443 && binDirectory.cdUp() && binDirectory.exists(base)) {
2444 found = binDirectory.absoluteFilePath(base);
2447 else if (QTestLog::verboseLevel() >= 2) {
2448 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2449 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2450 "checking next location"_L1.arg(base, candidate)),
2456 if (found.isEmpty()) {
2457 const char *testObjectName = QTestResult::currentTestObjectName();
2458 if (testObjectName) {
2459 const QString testsPath = QLibraryInfo::path(QLibraryInfo::TestsPath);
2460 const QString candidate =
"%1/%2/%3"_L1
2461 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2462 if (QFileInfo::exists(candidate)) {
2464 }
else if (QTestLog::verboseLevel() >= 2) {
2465 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2466 "checking next location"_L1
2467 .arg(base, QDir::toNativeSeparators(candidate))),
2474 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2476 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2480 if (!srcdir.isAbsolute() && builddir)
2481 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2483 const QString canonicalPath = srcdir.canonicalFilePath();
2484 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2485 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2487 }
else if (QTestLog::verboseLevel() >= 2) {
2488 QTestLog::info(qPrintable(
2489 "testdata %1 not found relative to source path [%2]"_L1
2490 .arg(base, QDir::toNativeSeparators(candidate))),
2496 if (found.isEmpty()) {
2497 const QString candidate =
":/%1"_L1.arg(base);
2498 if (QFileInfo::exists(candidate)) {
2500 }
else if (QTestLog::verboseLevel() >= 2) {
2501 QTestLog::info(qPrintable(
2502 "testdata %1 not found in resources [%2]"_L1
2503 .arg(base, QDir::toNativeSeparators(candidate))),
2509 if (found.isEmpty()) {
2510 const QString candidate = QDir::currentPath() + u'/' + base;
2511 if (QFileInfo::exists(candidate)) {
2513 }
else if (QTestLog::verboseLevel() >= 2) {
2514 QTestLog::info(qPrintable(
2515 "testdata %1 not found in current directory [%2]"_L1
2516 .arg(base, QDir::toNativeSeparators(candidate))),
2522 if (found.isEmpty()) {
2523 const QString candidate = QTest::mainSourcePath % u'/' % base;
2524 if (QFileInfo::exists(candidate)) {
2526 }
else if (QTestLog::verboseLevel() >= 2) {
2527 QTestLog::info(qPrintable(
2528 "testdata %1 not found in main source directory [%2]"_L1
2529 .arg(base, QDir::toNativeSeparators(candidate))),
2535 if (found.isEmpty() && sourcedir) {
2536 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2537 if (QFileInfo::exists(candidate)) {
2539 }
else if (QTestLog::verboseLevel() >= 2) {
2540 QTestLog::info(qPrintable(
2541 "testdata %1 not found in supplied source directory [%2]"_L1
2542 .arg(base, QDir::toNativeSeparators(candidate))),
2548 if (found.isEmpty()) {
2549 QTestLog::warn(qPrintable(
2550 "testdata %1 could not be located!"_L1.arg(base)),
2552 }
else if (QTestLog::verboseLevel() >= 1) {
2553 QTestLog::info(qPrintable(
2554 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2562
2563QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2564 const char *sourcedir)
2566 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2570
2573 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2577
2580 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2584
2587 QTEST_ASSERT(tagName);
2588 QTestData *data = QTestResult::currentTestData();
2590 QTEST_ASSERT(data->parent());
2592 int idx = data->parent()->indexOf(tagName);
2593 QTEST_ASSERT(idx != -1);
2594 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2596 return data->data(data->parent()->indexOf(tagName));
2600
2603 QTestTable *tbl = QTestTable::currentTestTable();
2604 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2606 tbl->addColumn(id, name);
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629QTestData &
QTest::newRow(
const char *dataTag)
2631 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2632 QTestTable *tbl = QTestTable::currentTestTable();
2633 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2634 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2635 "Must add columns before attempting to add rows.");
2637 return *tbl->newData(dataTag);
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667QTestData &
QTest::addRow(
const char *format, ...)
2669 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2670 QTestTable *tbl = QTestTable::currentTestTable();
2671 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2672 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2673 "Must add columns before attempting to add rows.");
2678 va_start(va, format);
2681 std::vsnprintf(buf,
sizeof buf, format, va);
2684 return *tbl->newData(buf);
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2709
2710
2713 return QTestResult::currentAppName();
2717
2718
2719
2720
2721
2722
2725 return QTestResult::currentTestFunction();
2729
2730
2731
2734 return QTestResult::currentDataTag();
2738
2739
2740
2741
2742
2745 return QTestResult::currentGlobalDataTag();
2749
2750
2751
2752
2755 return QTestResult::currentTestFailed();
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2773 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2777
2778
2779
2780
2781
2782
2783
2790
2793 return currentTestObject;
2797
2800 QString mainSourceFile = QFile::decodeName(file);
2803 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2805 fi.setFile(mainSourceFile);
2809#if QT_DEPRECATED_SINCE(6
, 4
)
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828bool QTest::compare_helper(
bool success,
const char *failureMsg,
2829 char *actualVal,
char *expectedVal,
2830 const char *actual,
const char *expected,
2831 const char *file,
int line)
2833 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2834 actual, expected, file, line);
2838#if QT_DEPRECATED_SINCE(6
, 8
)
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852bool QTest::compare_helper(
bool success,
const char *failureMsg,
2853 qxp::function_ref<
const char *()> actualVal,
2854 qxp::function_ref<
const char *()> expectedVal,
2855 const char *actual,
const char *expected,
2856 const char *file,
int line)
2858 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2859 QTest::functionRefFormatter,
2860 QTest::functionRefFormatter, actual, expected,
2861 QTest::ComparisonOperation::CustomCompare,
2862 file, line, failureMsg);
2867
2868
2869
2870
2871
2872
2873
2874
2877 const void *actualPtr,
const void *expectedPtr,
2878 const char *(*actualFormatter)(
const void *),
2879 const char *(*expectedFormatter)(
const void *),
2880 const char *actual,
const char *expected,
2881 const char *file,
int line)
2883 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2884 actualFormatter, expectedFormatter,
2886 QTest::ComparisonOperation::CustomCompare,
2887 file, line, failureMsg);
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2919 const void *lhsPtr,
const void *rhsPtr,
2920 const char *(*lhsFormatter)(
const void*),
2921 const char *(*rhsFormatter)(
const void*),
2922 const char *lhsExpression,
const char *rhsExpression,
2923 const char *(*actualOrderFormatter)(
const void *),
2924 const char *(*expectedOrderFormatter)(
const void *),
2925 const void *actualOrderPtr,
const void *expectedOrderPtr,
2926 const char *expectedExpression,
2927 const char *file,
int line)
2929 return QTestResult::report3WayResult(success, failureMsg,
2931 lhsFormatter, rhsFormatter,
2932 lhsExpression, rhsExpression,
2933 actualOrderFormatter,
2934 expectedOrderFormatter,
2935 actualOrderPtr, expectedOrderPtr,
2941
2942
2943
2944
2945
2946
2947
2948
2949
2951 const char *expected,
const char *file,
int line)
2953 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2956template <
typename T>
2959 switch (qFpClassify(expected))
2962 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2964 return qFpClassify(actual) == FP_NAN;
2966 if (!qFuzzyIsNull(expected))
2967 return qFuzzyCompare(actual, expected);
2971 return qFuzzyIsNull(actual);
2976
2977
2978bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2979 const char *file,
int line)
2981 auto formatter = Internal::genericToString<qfloat16>;
2982 return compare_helper(floatingCompare(t1, t2),
2983 "Compared qfloat16s are not the same (fuzzy compare)",
2984 &t1, &t2, formatter, formatter,
2985 actual, expected, file, line);
2989
2990
2991bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
2992 const char *file,
int line)
2994 return QTestResult::compare(floatingCompare(t1, t2),
2995 "Compared floats are not the same (fuzzy compare)",
2996 t1, t2, actual, expected, file, line);
3000
3001
3002bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
3003 const char *file,
int line)
3005 return QTestResult::compare(floatingCompare(t1, t2),
3006 "Compared doubles are not the same (fuzzy compare)",
3007 t1, t2, actual, expected, file, line);
3011
3012
3013
3015 const char *file,
int line)
3017 return QTestResult::compare(t1 == t2,
3018 "Compared values are not the same",
3019 t1, t2, actual, expected, file, line);
3022#if QT_POINTER_SIZE == 8
3024
3025
3026
3028bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3029 const char *file,
int line)
3031 return QTestResult::compare(t1 == t2,
3032 "Compared values are not the same",
3033 t1, t2, actual, expected, file, line);
3038
3039
3040
3041bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3042 const char *file,
int line)
3044 return QTestResult::compare(t1 == t2,
3045 "Compared values are not the same",
3046 t1, t2, actual, expected, file, line);
3050
3051
3052
3053bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3054 const char *file,
int line)
3056 return QTestResult::compare(t1 == t2,
3057 "Compared values are not the same",
3058 t1, t2, actual, expected, file, line);
3062
3063
3064
3065bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3066 const char *file,
int line)
3068 return QTestResult::compare(t1 == t2,
3069 "Compared values are not the same",
3070 t1, t2, actual, expected, file, line);
3074
3075
3076
3077bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3078 const char *file,
int line)
3080 return QTestResult::compare(t1 == t2,
3081 "Compared values are not the same",
3082 t1, t2, actual, expected, file, line);
3086
3087
3088
3091
3092
3093
3096
3097
3098
3101
3102
3105
3106
3108#define TO_STRING_IMPL(TYPE, FORMAT) template
3109 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3110{
3111 char *msg = new char[128
];
3112 std::snprintf(msg, 128
, #FORMAT, t);
3114}
3131 constexpr int Digits =
std::numeric_limits<T>::digits;
3132 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3133 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3134 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3140 Q_ASSERT(qIsNaN(t));
3141 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3142 r.payload = u & PayloadMask;
3143 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3153 char *msg =
new char[128];
3154 bool negative = signbit(t);
3156 switch (qFpClassify(t)) {
3158 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3161 if (
auto r = decodeNanPayload(t); r.payload) {
3162 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3163 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3165 Q_ASSERT(r.isQuiet);
3166 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3170 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3173 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3180#define TO_STRING_FLOAT(TYPE) template
3181 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3182{
3183 return toStringFp(t); \
3184}
3191 unsigned char c =
static_cast<
unsigned char>(t);
3192 char *msg =
new char[16];
3195 qstrcpy(msg,
"'\\0'");
3198 qstrcpy(msg,
"'\\a'");
3201 qstrcpy(msg,
"'\\b'");
3204 qstrcpy(msg,
"'\\t'");
3207 qstrcpy(msg,
"'\\n'");
3210 qstrcpy(msg,
"'\\v'");
3213 qstrcpy(msg,
"'\\f'");
3216 qstrcpy(msg,
"'\\r'");
3219 qstrcpy(msg,
"'\\\"'");
3222 qstrcpy(msg,
"'\\\''");
3225 qstrcpy(msg,
"'\\\\'");
3228 if (c < 0x20 || c >= 0x7F)
3229 std::snprintf(msg, 16,
"'\\x%02x'", c);
3231 std::snprintf(msg, 16,
"'%c'" , c);
3237
3241 char *msg =
new char[1];
3245 char *msg =
new char[strlen(str) + 1];
3246 return qstrcpy(msg, str);
3250
3253 char *msg =
new char[128];
3254 std::snprintf(msg, 128,
"%p", p);
3259
3263 return qstrdup(
"<null>");
3265 return QTest::toString(
const_cast<
const QObject*>(vo));
3269
3273 return qstrdup(
"<null>");
3275 const QString &name = o->objectName();
3276 const char *className = o->metaObject()->className();
3277 char *msg =
new char[256];
3279 std::snprintf(msg, 256,
"%s/%p", className, o);
3281 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3287
3288
3291
3292
3295
3296
3299
3300
3303
3304
3307
3308
3311
3313 const char *expected,
const char *file,
int line)
3315 auto formatter = Internal::genericToString<
const char *>;
3316 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3317 &t1, &t2, formatter, formatter,
3318 actual, expected, file, line);
3322
3323
3324
3327
3328
3331
3332
3335
3336
3339
3340
3343
3344
3347
3348
3351
3352
3355
3356
3359
3360
3363
3364
3367
3368
3371
3372
3375
3376
3379
3380
3383
3384
3387
3388
3391
3392
3395
3396
3399
3400
3403
3404
3407
3408
3411
3412
3415
3416
3419
3420
3423
3424
3427
3428
3431
3432
3435
3436
3439
3440
3443
3444
3447
3448
3451
3452
3455
3456
3459
3460
3463
3464
3467
3468
3471
3472
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)