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>
14#include <QtCore/qfile.h>
15#include <QtCore/qfileinfo.h>
16#include <QtCore/qfloat16.h>
17#include <QtCore/qlibraryinfo.h>
18#include <QtCore/qlist.h>
19#include <QtCore/qmetaobject.h>
20#include <QtCore/qobject.h>
21#include <QtCore/qstringlist.h>
22#include <QtCore/qtemporarydir.h>
23#include <QtCore/qthread.h>
24#include <QtCore/qvarlengtharray.h>
25#include <QtCore/private/qlocking_p.h>
26#include <QtCore/private/qtools_p.h>
27#include <QtCore/private/qwaitcondition_p.h>
29#include <QtCore/qtestsupport_core.h>
31#include <QtTest/private/qtestlog_p.h>
32#include <QtTest/private/qtesttable_p.h>
33#include <QtTest/qtestdata.h>
34#include <QtTest/private/qtestresult_p.h>
35#include <QtTest/private/qsignaldumper_p.h>
36#include <QtTest/private/qbenchmark_p.h>
37#if QT_CONFIG(batch_test_support)
38#include <QtTest/private/qtestregistry_p.h>
40#include <QtTest/private/cycle_include_p.h>
41#include <QtTest/private/qtestblacklist_p.h>
42#include <QtTest/private/qtestcrashhandler_p.h>
43#if defined(HAVE_XCTEST)
44#include <QtTest/private/qxctestlogger_p.h>
47#include <QtTest/private/qtestutil_macos_p.h>
50#if defined(Q_OS_DARWIN)
51#include <QtTest/private/qappletestlogger_p.h>
56#if !defined(Q_OS_INTEGRITY) || __GHS_VERSION_NUMBER > 202014
60# undef __cpp_lib_to_chars
74#if defined(Q_OS_LINUX)
81# if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR))
84#include <qt_windows.h>
87#include <QtCore/private/qcore_unix_p.h>
90#if __has_include(<paths.h>)
98# if !defined(Q_OS_INTEGRITY)
99# include <sys/resource.h>
103#if defined(Q_OS_MACOS)
104#include <IOKit/pwr_mgt/IOPMLib.h>
105#include <mach/task.h>
106#include <mach/mach_init.h>
107#include <CoreFoundation/CFPreferences.h>
110#if defined(Q_OS_WASM)
111#include <emscripten.h>
115#include <QtCore/QStandardPaths>
122using namespace Qt::StringLiterals;
124using QtMiscUtils::toHexUpper;
125using QtMiscUtils::fromHex;
129#if defined(__COVERAGESCANNER__) && !QT_CONFIG(testlib_selfcover)
130 if (!qEnvironmentVariableIsEmpty(
"QT_TESTCOCOON_ACTIVE"))
134 qputenv(
"QT_TESTCOCOON_ACTIVE",
"1");
137 __coveragescanner_install(appname);
138 __coveragescanner_testname(testname);
139 __coveragescanner_clear();
150 if (sl.access() != QMetaMethod::Private || sl.parameterCount() != 0
151 || sl.returnType() != QMetaType::Void || sl.methodType() != QMetaMethod::Slot)
153 const QByteArray name = sl.name();
154 return !(name.isEmpty() || name.endsWith(
"_data")
155 || name ==
"initTestCase" || name ==
"cleanupTestCase"
156 || name ==
"init" || name ==
"cleanup");
166class TestFailedException :
public std::exception
169 TestFailedException() =
default;
170 ~TestFailedException()
override =
default;
172 const char *what()
const noexcept override {
return "QtTest: test failed"; }
175class TestSkippedException :
public std::exception
178 TestSkippedException() =
default;
179 ~TestSkippedException()
override =
default;
181 const char *what()
const noexcept override {
return "QtTest: test was skipped"; }
208
209
210
211
212
213
214
217
218
219
220
221
222
223
226
227
228
229
230
231
233
234
235
236
238
239
240
241
244
245
246
247
248
249
251
252
253
254
256
257
258
259
262
263
264
265
266
267
269
270
271
272
274
275
276
277
280
281
282
283
284
285
287
288
289
290
292
293
294
295
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
318 g_throwOnFail.fetchAndAddRelaxed(enable ? 1 : -1);
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
342 g_throwOnSkip.fetchAndAddRelaxed(enable ? 1 : -1);
347 return "QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) "
348 "was too short, %3 ms would have been sufficient this time."_L1
360#if defined(Q_OS_MACOS)
377 bool invokeTest(
int index, QLatin1StringView tag,
std::optional<
WatchDog> &watchDog)
const;
378 void invokeTestOnData(
int index)
const;
380 QMetaMethod m_initTestCaseMethod;
381 QMetaMethod m_initTestCaseDataMethod;
382 QMetaMethod m_cleanupTestCaseMethod;
383 QMetaMethod m_initMethod;
384 QMetaMethod m_cleanupMethod;
386 MetaMethods m_methods;
397 if (m_methods.empty()) {
398 const QMetaObject *metaObject = o->metaObject();
399 const int count = metaObject->methodCount();
400 m_methods.reserve(count);
401 for (
int i = 0; i < count; ++i) {
402 const QMetaMethod me = metaObject->method(i);
404 m_methods.push_back(me);
409QMetaMethod
TestMethods::findMethod(
const QObject *obj,
const char *signature)
411 const QMetaObject *metaObject = obj->metaObject();
412 const int funcIndex = metaObject->indexOfMethod(signature);
413 return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
434 try { ok = m.invoke(obj, Qt ::DirectConnection); }
435 catch (
const TestFailedException &) {}
436 catch (
const TestSkippedException &) {}
443 const QMetaObject *metaObject = obj->metaObject();
444 int funcIndex = metaObject->indexOfMethod(methodName);
446 invokeTestMethodIfValid(metaObject->method(funcIndex), obj);
452 const QByteArray env = qgetenv(
"QTEST_EVENT_DELAY");
502static bool qPrintTestSlots(FILE *stream,
const char *filter =
nullptr,
const char *preamble =
"")
504 const auto matches = [filter](
const QByteArray &s) {
505 return !filter || QLatin1StringView(s).contains(QLatin1StringView(filter),
506 Qt::CaseInsensitive);
508 bool matched =
false;
510 QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
511 if (isValidSlot(sl)) {
512 const QByteArray signature = sl.methodSignature();
513 if (matches(signature)) {
514 std::fprintf(stream,
"%s%s\n", preamble, signature.constData());
526 QTestLog::setPrintAvailableTagsMode();
529 QTestTable::globalTestTable();
531 const QTestTable *gTable = QTestTable::globalTestTable();
533 const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject();
536 for (
int i = 0; i < currTestMetaObj->methodCount(); ++i) {
537 QMetaMethod tf = currTestMetaObj->method(i);
539 if (isValidSlot(tf)) {
542 QStringList localTags;
544 const QByteArray slot = tf.methodSignature().chopped(2);
545 const QByteArray member = slot +
"_data()";
546 invokeTestMethodIfExists(member.constData());
547 const int dataCount = table.dataCount();
548 localTags.reserve(dataCount);
549 for (
int j = 0; j < dataCount; ++j)
550 localTags << QLatin1StringView(table.testData(j)->dataTag());
553 if (gTable->dataCount() == 0) {
554 if (localTags.size() == 0) {
556 std::fprintf(stream,
"%s %s\n", currTestMetaObj->className(), slot.data());
559 for (
int k = 0; k < localTags.size(); ++k)
560 std::fprintf(stream,
"%s %s %s\n",
561 currTestMetaObj->className(),
563 localTags.at(k).toLatin1().data());
566 for (
int j = 0; j < gTable->dataCount(); ++j) {
567 if (localTags.size() == 0) {
569 std::fprintf(stream,
"%s %s __global__ %s\n",
570 currTestMetaObj->className(),
572 gTable->testData(j)->dataTag());
576 for (
int k = 0; k < localTags.size(); ++k)
577 std::fprintf(stream,
"%s %s %s __global__ %s\n",
578 currTestMetaObj->className(),
580 localTags.at(k).toLatin1().data(),
581 gTable->testData(j)->dataTag());
592 int l =
static_cast<
int>(strtol(str, &pEnd, 10));
594 std::fprintf(stderr,
"Invalid numeric parameter: '%s'\n", str);
603 const char *logFilename =
nullptr;
607 QTest::testFunctions.clear();
608 QTest::testTags.clear();
610#if defined(Q_OS_DARWIN) && defined(HAVE_XCTEST)
611 if (QXcodeTestLogger::canLogTestProgress())
612 logFormat = QTestLog::XCTest;
615 const char *testOptions =
616 " New-style logging options:\n"
617 " -o filename,format : Output results to file in the specified format\n"
618 " Use - to output to stdout\n"
619 " Valid formats are:\n"
620 " txt : Plain text\n"
621 " csv : CSV format (suitable for benchmarks)\n"
622 " junitxml : XML JUnit document\n"
623 " xml : XML document\n"
624 " lightxml : A stream of XML tags\n"
625 " teamcity : TeamCity format\n"
626 " tap : Test Anything Protocol\n"
628 " *** Multiple loggers can be specified, but at most one can log to stdout.\n"
630 " Old-style logging options:\n"
631 " -o filename : Write the output into file\n"
632 " -txt : Output results in Plain Text\n"
633 " -csv : Output results in a CSV format (suitable for benchmarks)\n"
634 " -junitxml : Output results as XML JUnit document\n"
635 " -xml : Output results as XML document\n"
636 " -lightxml : Output results as stream of XML tags\n"
637 " -teamcity : Output results in TeamCity format\n"
638 " -tap : Output results in Test Anything Protocol format\n"
640 " *** If no output file is specified, stdout is assumed.\n"
641 " *** If no output format is specified, -txt is assumed.\n"
643 " Test log detail options:\n"
644 " -silent : Log failures and fatal errors only\n"
645 " -v1 : Log the start of each testfunction\n"
646 " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n"
647 " -vs : Log every signal emission and resulting slot invocations\n"
649 " *** The -silent and -v1 options only affect plain text output.\n"
651 " Testing options:\n"
652 " -functions : Returns a list of current testfunctions\n"
653 " -datatags : Returns a list of current data tags.\n"
654 " A global data tag is preceded by ' __global__ '.\n"
655 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
656 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
657 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
658 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
659 " 0 means unlimited, default: 2000\n"
660 " -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
661 " -repeat n : Run the testsuite n times or until the test fails.\n"
662 " Useful for finding flaky tests. If negative, the tests are\n"
663 " repeated forever. This is intended as a developer tool, and\n"
664 " is only supported with the plain text logger.\n"
665 " -skipblacklisted : Skip blacklisted tests. Useful for measuring test coverage.\n"
667 " Benchmarking options:\n"
668#if QT_CONFIG(valgrind)
669 " -callgrind : Use callgrind to time benchmarks\n"
671#ifdef QTESTLIB_USE_PERF_EVENTS
672 " -perf : Use Linux perf events to time benchmarks\n"
673 " -perfcounter name : Use the counter named 'name'\n"
674 " -perfcounterlist : Lists the counters available\n"
676#ifdef HAVE_TICK_COUNTER
677 " -tickcounter : Use CPU tick counters to time benchmarks\n"
679 " -eventcounter : Counts events received during benchmarks\n"
680 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
681 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
682 " -iterations n : Sets the number of accumulation iterations.\n"
683 " -median n : Sets the number of median iterations.\n"
684 " -vb : Print out verbose benchmarking information.\n";
686 for (
int i = 1; i < argc; ++i) {
687 if (strcmp(argv[i],
"-help") == 0 || strcmp(argv[i],
"--help") == 0
688 || strcmp(argv[i],
"/?") == 0) {
689 std::printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
690 " By default, all testfunctions will be run.\n\n"
691 "%s", argv[0], testOptions);
695 " QmlTest options:\n"
696 " -import dir : Specify an import directory.\n"
697 " -plugins dir : Specify a directory where to search for plugins.\n"
698 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
699 " -translation file : Specify the translation file.\n"
700 " -file-selector dir : Specify a file selector for the QML engine.\n");
704 " -help : This help\n");
706 }
else if (strcmp(argv[i],
"-functions") == 0) {
713 }
else if (strcmp(argv[i],
"-datatags") == 0) {
718 }
else if (strcmp(argv[i],
"-txt") == 0) {
719 logFormat = QTestLog::Plain;
720 }
else if (strcmp(argv[i],
"-csv") == 0) {
721 logFormat = QTestLog::CSV;
722 }
else if (strcmp(argv[i],
"-junitxml") == 0) {
723 logFormat = QTestLog::JUnitXML;
724 }
else if (strcmp(argv[i],
"-xunitxml") == 0) {
725 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
726 logFormat = QTestLog::JUnitXML;
727 }
else if (strcmp(argv[i],
"-xml") == 0) {
728 logFormat = QTestLog::XML;
729 }
else if (strcmp(argv[i],
"-lightxml") == 0) {
730 logFormat = QTestLog::LightXML;
731 }
else if (strcmp(argv[i],
"-teamcity") == 0) {
732 logFormat = QTestLog::TeamCity;
733 }
else if (strcmp(argv[i],
"-tap") == 0) {
734 logFormat = QTestLog::TAP;
735 }
else if (strcmp(argv[i],
"-silent") == 0) {
736 QTestLog::setVerboseLevel(-1);
737 }
else if (strcmp(argv[i],
"-v1") == 0) {
738 QTestLog::setVerboseLevel(1);
739 }
else if (strcmp(argv[i],
"-v2") == 0) {
740 QTestLog::setVerboseLevel(2);
741 }
else if (strcmp(argv[i],
"-vs") == 0) {
742 QSignalDumper::setEnabled(
true);
743 }
else if (strcmp(argv[i],
"-o") == 0) {
745 std::fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
750 char *filename =
new char[strlen(argv[i])+1];
751 char *format =
new char[strlen(argv[i])+1];
752 if (
std::sscanf(argv[i],
"%[^,],%s", filename, format) == 1) {
754 logFilename = argv[i];
757 if (strcmp(format,
"txt") == 0)
758 logFormat = QTestLog::Plain;
759 else if (strcmp(format,
"csv") == 0)
760 logFormat = QTestLog::CSV;
761 else if (strcmp(format,
"lightxml") == 0)
762 logFormat = QTestLog::LightXML;
763 else if (strcmp(format,
"xml") == 0)
764 logFormat = QTestLog::XML;
765 else if (strcmp(format,
"junitxml") == 0)
766 logFormat = QTestLog::JUnitXML;
767 else if (strcmp(format,
"xunitxml") == 0) {
768 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
769 logFormat = QTestLog::JUnitXML;
770 }
else if (strcmp(format,
"teamcity") == 0)
771 logFormat = QTestLog::TeamCity;
772 else if (strcmp(format,
"tap") == 0)
773 logFormat = QTestLog::TAP;
775 std::fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
778 if (strcmp(filename,
"-") == 0 && QTestLog::loggerUsingStdout()) {
779 std::fprintf(stderr,
"only one logger can log to stdout\n");
782 QTestLog::addLogger(QTestLog::LogMode(logFormat), filename);
786 }
else if (strcmp(argv[i],
"-eventdelay") == 0) {
788 std::fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
793 }
else if (strcmp(argv[i],
"-keydelay") == 0) {
795 std::fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
800 }
else if (strcmp(argv[i],
"-mousedelay") == 0) {
802 std::fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
807 }
else if (strcmp(argv[i],
"-maxwarnings") == 0) {
809 std::fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
812 QTestLog::setMaxWarnings(qToInt(argv[++i]));
814 }
else if (strcmp(argv[i],
"-repeat") == 0) {
816 std::fprintf(stderr,
"-repeat needs an extra parameter for the number of repetitions\n");
821 }
else if (strcmp(argv[i],
"-nocrashhandler") == 0) {
823 }
else if (strcmp(argv[i],
"-skipblacklisted") == 0) {
825#if QT_CONFIG(valgrind)
826 }
else if (strcmp(argv[i],
"-callgrind") == 0) {
827 if (!QBenchmarkValgrindUtils::haveValgrind()) {
829 "WARNING: Valgrind not found or too old. "
830 "Make sure it is installed and in your path. "
831 "Using the walltime measurer.\n");
832 }
else if (QFileInfo(QDir::currentPath()).isWritable()) {
833 QBenchmarkGlobalData::current->setMode(
834 QBenchmarkGlobalData::CallgrindParentProcess);
837 "WARNING: Current directory not writable. "
838 "Using the walltime measurer.\n");
840 }
else if (strcmp(argv[i],
"-callgrindchild") == 0) {
841 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
842 QBenchmarkGlobalData::current->callgrindOutFileBase =
843 QBenchmarkValgrindUtils::outFileBase();
845#ifdef QTESTLIB_USE_PERF_EVENTS
846 }
else if (strcmp(argv[i],
"-perf") == 0) {
847 if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
849 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
851 std::fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
853 }
else if (strcmp(argv[i],
"-perfcounter") == 0) {
855 std::fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
858 QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
860 }
else if (strcmp(argv[i],
"-perfcounterlist") == 0) {
861 QBenchmarkPerfEventsMeasurer::listCounters();
864#ifdef HAVE_TICK_COUNTER
865 }
else if (strcmp(argv[i],
"-tickcounter") == 0) {
866 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
868 }
else if (strcmp(argv[i],
"-eventcounter") == 0) {
869 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
870 }
else if (strcmp(argv[i],
"-minimumvalue") == 0) {
872 std::fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
875 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
877 }
else if (strcmp(argv[i],
"-minimumtotal") == 0) {
879 std::fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
882 QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
884 }
else if (strcmp(argv[i],
"-iterations") == 0) {
886 std::fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
889 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
891 }
else if (strcmp(argv[i],
"-median") == 0) {
893 std::fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
896 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
899 }
else if (strcmp(argv[i],
"-vb") == 0) {
900 QBenchmarkGlobalData::current->verboseOutput =
true;
901#if defined(Q_OS_DARWIN)
902 }
else if (strncmp(argv[i],
"-Apple", 6) == 0) {
905# if defined(HAVE_XCTEST)
906 }
else if (
int skip = QXcodeTestLogger::parseCommandLineArgument(argv[i])) {
911 }
else if (argv[i][0] ==
'-') {
912 std::fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[i], testOptions);
914 std::fprintf(stderr,
"\nqmltest related options:\n"
915 " -import : Specify an import directory.\n"
916 " -plugins : Specify a directory where to search for plugins.\n"
917 " -input : Specify the root directory for test cases.\n");
920 std::fprintf(stderr,
"\n"
921 " -help : This help\n");
928 for (offset = 0; argv[i][offset]; ++offset) {
929 if (argv[i][offset] ==
':') {
930 if (argv[i][offset + 1] ==
':') {
941 QTest::testFunctions += QString::fromLatin1(argv[i]);
942 QTest::testTags += QString();
944 QTest::testFunctions +=
945 QString::fromLatin1(argv[i], colon);
947 QString::fromLatin1(argv[i] + colon + 1);
952 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
953 QTestLog::setInstalledTestCoverage(installedTestCoverage);
957 const bool explicitLoggerRequested = logFormat != -1;
958 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
959 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
961 bool addFallbackLogger = !explicitLoggerRequested;
963#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
965 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
966 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
967 QTestLog::addLogger(QTestLog::Apple,
nullptr);
968 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
969 addFallbackLogger =
false;
973 if (addFallbackLogger)
974 QTestLog::addLogger(QTestLog::Plain, logFilename);
976 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
977 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
984 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
989 const int count = container.size();
994 return container.front();
996 QList<QList<QBenchmarkResult>> containerCopy = container;
997 std::sort(containerCopy.begin(), containerCopy.end(),
998 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
999 return a.first() < b.first();
1002 const int middle = count / 2;
1005 return containerCopy.at(middle);
1012 QTestResult::setCurrentTestData(data);
1016 QTestResult::setCurrentTestData(
nullptr);
1020void TestMethods::invokeTestOnData(
int index)
const
1024 bool isBenchmark =
false;
1025 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1027 QList<QList<QBenchmarkResult>> resultsList;
1028 bool minimumTotalReached =
false;
1030 QBenchmarkTestMethodData::current->beginDataRun();
1032 QBenchmarkTestMethodData::current->iterationCount = 1;
1038 invokeTestMethodIfValid(m_initMethod);
1040 const bool initQuit =
1041 QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
1043 QBenchmarkTestMethodData::current->results.clear();
1044 QBenchmarkTestMethodData::current->resultAccepted =
false;
1045 QBenchmarkTestMethodData::current->valid =
false;
1047 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1048 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1050 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1052 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1054 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1060 QTestResult::finishedCurrentTestData();
1063 invokeTestMethodIfValid(m_cleanupMethod);
1067 if (QCoreApplication::instance())
1068 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1073 QTestResult::finishedCurrentTestDataCleanup();
1079 }
while (invokeOk && isBenchmark
1080 && QBenchmarkTestMethodData::current->resultsAccepted() ==
false
1081 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1083 QBenchmarkTestMethodData::current->endDataRun();
1084 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1086 resultsList.append(QBenchmarkTestMethodData::current->results);
1088 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1089 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1091 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1092 QString pattern = i < 0 ?
"warmup stage result : %1"_L1
1093 :
"accumulation stage result: %1"_L1;
1094 QTestLog::info(qPrintable(pattern.arg(first.measurement.value)),
nullptr, 0);
1100 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1101 minimumTotalReached =
true;
1103 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1105 current += r.first().measurement.value;
1108 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1109 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1111 }
while (isBenchmark
1112 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1113 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1117 bool testPassed = !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed();
1118 QTestResult::finishedCurrentTestDataCleanup();
1120 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1121 QTestLog::addBenchmarkResults(qMedian(resultsList));
1125#if QT_CONFIG(thread)
1222 qFatal(
"Test function timed out");
1245template <
typename Functor>
1249 watchDog->beginTest();
1254 watchDog->testFinished();
1258 const QTestTable &lTable,
const QTestTable &gTable)
1260 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1261 const int localDataCount = lTable.dataCount();
1262 if (localDataCount) {
1263 std::fputs(
"Available test-specific data tags:\n", stderr);
1264 for (
int i = 0; i < localDataCount; ++i)
1265 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1267 const int globalDataCount = gTable.dataCount();
1268 if (globalDataCount) {
1269 std::fputs(
"Available global data tags:\n", stderr);
1270 for (
int i = 0; i < globalDataCount; ++i)
1271 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1273 if (localDataCount == 0 && globalDataCount == 0)
1274 std::fputs(
"Function has no data tags\n", stderr);
1278
1279
1280
1281
1282
1283
1284
1285
1288 QBenchmarkTestMethodData benchmarkData;
1289 QBenchmarkTestMethodData::current = &benchmarkData;
1291 const QByteArray &name = m_methods[index].name();
1292 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1297 QTestResult::setCurrentTestFunction(name.constData());
1299 const QTestTable *gTable = QTestTable::globalTestTable();
1300 const int globalDataCount = gTable->dataCount();
1301 int curGlobalDataIndex = 0;
1302 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1303 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1306 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1307 QLatin1StringView global) {
1310 if (tag == local || tag == global)
1313 return tag.startsWith(global) && tag.endsWith(local) &&
1314 tag.size() == global.size() + 1 + local.size() &&
1315 tag[global.size()] ==
':';
1317 bool foundFunction =
false;
1318 bool blacklisted =
false;
1322 if (!gTable->isEmpty())
1323 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1325 if (curGlobalDataIndex == 0) {
1326 std::snprintf(member, 512,
"%s_data()", name.constData());
1327 runWithWatchdog(watchDog, [&member] {
1330 if (QTestResult::skipCurrentTest())
1334 int curDataIndex = 0;
1335 const int dataCount = table.dataCount();
1336 const auto dataTag = [&table, dataCount](
int index) {
1337 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1342 QTestResult::setSkipCurrentTest(
false);
1343 QTestResult::setBlacklistCurrentTest(
false);
1344 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1345 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1346 foundFunction =
true;
1347 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1348 globalDataTag(curGlobalDataIndex));
1350 QTestResult::setBlacklistCurrentTest(
true);
1353 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1355 QTestResult::finishedCurrentTestData();
1356 QTestResult::finishedCurrentTestDataCleanup();
1359 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1361 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1367 runWithWatchdog(watchDog, [
this, index] {
1368 invokeTestOnData(index);
1372 if (!tag.isEmpty() && !globalDataCount)
1376 }
while (curDataIndex < dataCount);
1378 QTestResult::setCurrentGlobalTestData(
nullptr);
1379 ++curGlobalDataIndex;
1380 }
while (curGlobalDataIndex < globalDataCount);
1382 if (!tag.isEmpty() && !foundFunction) {
1383 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1384 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1386 QTestResult::finishedCurrentTestFunction();
1387 QTestResult::setSkipCurrentTest(
false);
1388 QTestResult::setBlacklistCurrentTest(
false);
1393void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1395 QTEST_ASSERT(typeId);
1396 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1397 QTEST_ASSERT(data->parent());
1399 int idx = data->parent()->indexOf(tagName);
1401 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1402 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1406 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1407 qFatal(
"Requested type '%s' does not match available type '%s'.",
1408 QMetaType(typeId).name(),
1409 QMetaType(data->parent()->elementTypeId(idx)).name());
1412 return data->data(idx);
1416
1417
1418char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1421 va_start(ap, numArguments);
1423 QByteArray arguments;
1424 arguments += prefix;
1426 if (numArguments > 0) {
1427 arguments += va_arg(ap,
const char *);
1429 for (size_t i = 1; i < numArguments; ++i) {
1431 arguments += va_arg(ap,
const char *);
1436 arguments += suffix;
1437 return qstrdup(arguments.constData());
1441
1442
1443
1444
1445
1446
1447
1448
1449
1456
1457
1458
1459
1460
1461
1462 const qsizetype maxLen = 50;
1463 const qsizetype len = qMin(maxLen, length);
1464 char *result =
nullptr;
1466 if (length > maxLen) {
1467 const qsizetype size = len * 3 + 4;
1468 result =
new char[size];
1470 char *
const forElipsis = result + size - 5;
1471 forElipsis[0] =
' ';
1472 forElipsis[1] =
'.';
1473 forElipsis[2] =
'.';
1474 forElipsis[3] =
'.';
1475 result[size - 1] =
'\0';
1478 const qsizetype size = len * 3;
1479 result =
new char[size];
1480 result[size - 1] =
'\0';
1487 const char at = ba[i];
1489 result[o] = toHexUpper(at >> 4);
1491 result[o] = toHexUpper(at);
1505
1506
1507
1508
1511 bool trimmed =
false;
1512 auto buffer =
std::make_unique<
char[]>(256);
1513 const char *end = p + length;
1514 char *dst = buffer.get();
1516 bool lastWasHexEscape =
false;
1518 for ( ; p != end; ++p) {
1524 if (dst - buffer.get() > 246) {
1531 if (Q_UNLIKELY(lastWasHexEscape)) {
1532 if (fromHex(*p) != -1) {
1537 lastWasHexEscape =
false;
1540 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1571 *dst++ = toHexUpper(uchar(*p) >> 4);
1572 *dst++ = toHexUpper(uchar(*p));
1573 lastWasHexEscape =
true;
1585 return buffer.release();
1589
1590
1591
1592
1593
1594
1595
1604 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1605 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1634 *dst++ = toHexUpper(ch >> 12);
1635 *dst++ = toHexUpper(ch >> 8);
1636 *dst++ = toHexUpper(ch >> 4);
1637 *dst++ = toHexUpper(ch);
1645 auto p = string.utf16();
1646 auto length = string.size();
1648 bool trimmed =
false;
1649 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1650 const auto end = p + length;
1651 char *dst = buffer.get();
1654 for ( ; p != end; ++p) {
1655 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1659 dst = writePrettyUnicodeChar(*p, dst);
1669 return buffer.release();
1674 const QMetaObject *metaObject = testObject->metaObject();
1675 QTEST_ASSERT(metaObject);
1678 if (!CrashHandler::alreadyDebugging()
1679#if QT_CONFIG(valgrind)
1680 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1686 QTestResult::setCurrentTestFunction(
"initTestCase");
1687 runWithWatchdog(watchDog, [
this, testObject] {
1688 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1691 QSignalDumper::startDump();
1693 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1695 runWithWatchdog(watchDog, [
this, testObject] {
1696 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1700 const bool previousFailed = QTestResult::currentTestFailed();
1701 QTestResult::finishedCurrentTestData();
1702 QTestResult::finishedCurrentTestDataCleanup();
1703 QTestResult::finishedCurrentTestFunction();
1705 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1706 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1707 const char *data =
nullptr;
1708 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1709 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1710 const bool ok = invokeTest(i, QLatin1StringView(data), watchDog);
1717 const bool wasSkipped = QTestResult::skipCurrentTest();
1718 QTestResult::setSkipCurrentTest(
false);
1719 QTestResult::setBlacklistCurrentTest(
false);
1720 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1721 runWithWatchdog(watchDog, [
this, testObject] {
1722 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1725 QTestResult::finishedCurrentTestData();
1727 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1728 QTestResult::finishedCurrentTestDataCleanup();
1730 QTestResult::finishedCurrentTestFunction();
1731 QTestResult::setCurrentTestFunction(
nullptr);
1733 QSignalDumper::endDump();
1736#if QT_DEPRECATED_SINCE(6
, 8
)
1755 const char *(*lhsFormatter)(
const void*),
1756 const char *(*rhsFormatter)(
const void*),
1757 const char *lhsExpr,
const char *rhsExpr,
1758 ComparisonOperation op,
const char *file,
int line)
1760 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1761 lhsExpr, rhsExpr, op, file, line);
1767 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1771static QFile androidExitCodeFile()
1773 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1774 return QFile(testHome +
"/qtest_last_exit_code"_L1);
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1816int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1822 qInit(testObject, argc, argv);
1826#if defined(Q_OS_WASM)
1828 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1829 Module.notifyTestFinished($0);
1837
1838void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1841 CrashHandler::maybeDisableCoreDump();
1842 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1844#if defined(Q_OS_MACOS)
1846 QTestPrivate::disableWindowRestore();
1849 QTestPrivate::AppNapDisabler appNapDisabler;
1851 if (qApp && (qstrcmp(qApp->metaObject()->className(),
"QApplication") == 0)) {
1852 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1853 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1854 &macPowerSavingDisabled);
1858 QTestPrivate::parseBlackList();
1859 QTestResult::reset();
1861 QTEST_ASSERT(testObject);
1862 QTEST_ASSERT(!currentTestObject);
1865 const QMetaObject *metaObject = testObject->metaObject();
1866 QTEST_ASSERT(metaObject);
1868 QTestResult::setCurrentTestObject(metaObject->className());
1870 QTestResult::setCurrentAppName(argv[0]);
1874#if QT_CONFIG(valgrind)
1875 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1877 QTestLog::startLogging();
1880 androidExitCodeFile().remove();
1885
1888 QTEST_ASSERT(currentTestObject);
1890#if QT_CONFIG(valgrind)
1891 int callgrindChildExitCode = 0;
1894#ifndef QT_NO_EXCEPTIONS
1898#if QT_CONFIG(valgrind)
1899 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1900 if (Q_UNLIKELY(!qApp))
1901 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1903 const QStringList origAppArgs(QCoreApplication::arguments());
1904 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1907 QBenchmarkValgrindUtils::cleanup();
1912 std::optional<CrashHandler::FatalSignalHandler> handler;
1913 CrashHandler::prepareStackTrace();
1917 bool seenBad =
false;
1918 TestMethods::MetaMethods commandLineMethods;
1919 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1920 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1921 const QByteArray tfB = tf.toLatin1();
1922 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1923 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1924 if (m.isValid() && isValidSlot(m)) {
1925 commandLineMethods.push_back(m);
1927 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1928 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1929 std::fputc(
'\n', stderr);
1930 QTestResult::setCurrentTestFunction(tfB.constData());
1931 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1932 QTestResult::finishedCurrentTestFunction();
1934 QTest::testTags.remove(commandLineMethods.size());
1940 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1941 QTestResult::currentAppName());
1942 if (commandLineMethods.empty())
1949 while (QTestLog::failCount() == 0 && (repeatForever || remainingRepetitions-- > 0)) {
1950 QTestTable::globalTestTable();
1951 test.invokeTests(currentTestObject);
1952 QTestTable::clearGlobalTestTable();
1956#ifndef QT_NO_EXCEPTIONS
1958 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
1959 if (QTestResult::currentTestFunction()) {
1960 QTestResult::finishedCurrentTestFunction();
1961 QTestResult::setCurrentTestFunction(
nullptr);
1972#if QT_CONFIG(valgrind)
1973 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
1974 return callgrindChildExitCode;
1978 const int exitCode = qMin(QTestLog::failCount(), 127);
1981 QFile exitCodeFile = androidExitCodeFile();
1982 if (exitCodeFile.open(QIODevice::WriteOnly)) {
1983 exitCodeFile.write(qPrintable(QString::number(exitCode)));
1985 qWarning(
"Failed to open %s for writing test exit code: %s",
1986 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
1994
1999#if QT_CONFIG(valgrind)
2000 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2002 QTestLog::stopLogging();
2004 delete QBenchmarkGlobalData::current;
2005 QBenchmarkGlobalData::current =
nullptr;
2007#if defined(Q_OS_MACOS)
2008 IOPMAssertionRelease(macPowerSavingDisabled);
2012#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2025 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2028QList<QString> QTest::qGetTestCaseNames()
2030 return QTest::TestRegistry::instance()->getAllTestNames();
2033QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2035 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2041
2042
2043
2044
2045
2046
2047int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2049 const int argc = arguments.size();
2050 QVarLengthArray<
char *> argv(argc);
2052 QList<QByteArray> args;
2055 for (
int i = 0; i < argc; ++i)
2057 args.append(arguments.at(i).toLocal8Bit().constData());
2058 argv[i] = args.last().data();
2061 return qExec(testObject, argc, argv.data());
2065
2066void QTest::
qFail(
const char *message,
const char *file,
int line)
2068 QTestResult::fail(message, file, line);
2072
2073bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2074 const char *file,
int line)
2076 return QTestResult::verify(statement, statementStr, description, file, line);
2080
2081
2082void QTest::
qSkip(
const char *message,
const char *file,
int line)
2084 QTestResult::addSkip(message, file, line);
2085 QTestResult::setSkipCurrentTest(
true);
2089
2090
2092 QTest::TestFailMode mode,
const char *file,
int line)
2094 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2115 auto message = [&] {
2116 const auto exType = what ?
"std::" :
"unknown ";
2117 const auto ofType = expected ?
" of type " :
"";
2118 const auto no = expected ?
"an" :
"no";
2119 const auto withMsg = what ?
" with message " :
"";
2120 const auto protect = [](
const char *s) {
return s ? s :
""; };
2122 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2123 "but caught %sexception%s%s",
2124 no, ofType, protect(expected),
2125 exType, withMsg, protect(what));
2127 qFail(message().toUtf8().constData(), file, line);
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2153 std::rethrow_exception(
std::current_exception());
2154 }
catch (
const std::exception &e) {
2155 qCaught(expected, e.what(), file, line);
2157 qCaught(expected,
nullptr, file, line);
2164#if QT_DEPRECATED_SINCE(6
, 3
)
2166
2167
2168
2169void QTest::qWarn(
const char *message,
const char *file,
int line)
2171 QTestLog::warn(message, file, line);
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2193 QTestLog::ignoreMessage(type, message);
2196#if QT_CONFIG(regularexpression)
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2214 QTestLog::ignoreMessage(type, messagePattern);
2219
2220
2222
2223
2224
2225
2228 return QTestLog::failOnWarning();
2232
2233
2235
2236
2237
2238
2241 return QTestLog::failOnWarning(message);
2244#if QT_CONFIG(regularexpression)
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2299 QTestLog::failOnWarning(messagePattern);
2304
2307static inline bool isWindowsBuildDirectory(
const QString &dirName)
2309 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2310 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2314#if QT_CONFIG(temporaryfile)
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2327 QSharedPointer<QTemporaryDir> result;
2329 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2331 tempDir->setAutoRemove(
true);
2333 if (!tempDir->isValid())
2336 const QString dataPath = tempDir->path();
2337 const QString resourcePath = u':' + dirName;
2338 const QFileInfo fileInfo(resourcePath);
2340 if (!fileInfo.isDir()) {
2341 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2345 bool isResourceDirEmpty =
true;
2346 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2347 isResourceDirEmpty =
false;
2348 if (!dirEntry.isDir()) {
2349 const QString &filePath = dirEntry.filePath();
2350 const QString destination =
2351 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2352 QFileInfo destinationFileInfo(destination);
2353 QDir().mkpath(destinationFileInfo.path());
2354 QFile file(filePath);
2355 if (!file.copy(destination)) {
2356 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2357 qUtf16Printable(file.errorString()));
2361 file.setFileName(destination);
2362 if (!file.setPermissions(QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2363 qWarning(
"Failed to set permissions on '%ls': %ls.", qUtf16Printable(destination),
2364 qUtf16Printable(file.errorString()));
2370 if (isResourceDirEmpty) {
2371 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2375 result = std::move(tempDir);
2382
2384QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2385 const char *sourcedir)
2393 QDir binDirectory(QCoreApplication::applicationDirPath());
2394 if (binDirectory.exists(base)) {
2395 found = binDirectory.absoluteFilePath(base);
2400 else if (isWindowsBuildDirectory(binDirectory.dirName())
2401 && binDirectory.cdUp() && binDirectory.exists(base)) {
2402 found = binDirectory.absoluteFilePath(base);
2405 else if (QTestLog::verboseLevel() >= 2) {
2406 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2407 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2408 "checking next location"_L1.arg(base, candidate)),
2414 if (found.isEmpty()) {
2415 const char *testObjectName = QTestResult::currentTestObjectName();
2416 if (testObjectName) {
2417 const QString testsPath = QLibraryInfo::path(QLibraryInfo::TestsPath);
2418 const QString candidate =
"%1/%2/%3"_L1
2419 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2420 if (QFileInfo::exists(candidate)) {
2422 }
else if (QTestLog::verboseLevel() >= 2) {
2423 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2424 "checking next location"_L1
2425 .arg(base, QDir::toNativeSeparators(candidate))),
2432 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2434 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2438 if (!srcdir.isAbsolute() && builddir)
2439 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2441 const QString canonicalPath = srcdir.canonicalFilePath();
2442 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2443 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2445 }
else if (QTestLog::verboseLevel() >= 2) {
2446 QTestLog::info(qPrintable(
2447 "testdata %1 not found relative to source path [%2]"_L1
2448 .arg(base, QDir::toNativeSeparators(candidate))),
2454 if (found.isEmpty()) {
2455 const QString candidate =
":/%1"_L1.arg(base);
2456 if (QFileInfo::exists(candidate)) {
2458 }
else if (QTestLog::verboseLevel() >= 2) {
2459 QTestLog::info(qPrintable(
2460 "testdata %1 not found in resources [%2]"_L1
2461 .arg(base, QDir::toNativeSeparators(candidate))),
2467 if (found.isEmpty()) {
2468 const QString candidate = QDir::currentPath() + u'/' + base;
2469 if (QFileInfo::exists(candidate)) {
2471 }
else if (QTestLog::verboseLevel() >= 2) {
2472 QTestLog::info(qPrintable(
2473 "testdata %1 not found in current directory [%2]"_L1
2474 .arg(base, QDir::toNativeSeparators(candidate))),
2480 if (found.isEmpty()) {
2481 const QString candidate = QTest::mainSourcePath % u'/' % base;
2482 if (QFileInfo::exists(candidate)) {
2484 }
else if (QTestLog::verboseLevel() >= 2) {
2485 QTestLog::info(qPrintable(
2486 "testdata %1 not found in main source directory [%2]"_L1
2487 .arg(base, QDir::toNativeSeparators(candidate))),
2493 if (found.isEmpty() && sourcedir) {
2494 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2495 if (QFileInfo::exists(candidate)) {
2497 }
else if (QTestLog::verboseLevel() >= 2) {
2498 QTestLog::info(qPrintable(
2499 "testdata %1 not found in supplied source directory [%2]"_L1
2500 .arg(base, QDir::toNativeSeparators(candidate))),
2506 if (found.isEmpty()) {
2507 QTestLog::warn(qPrintable(
2508 "testdata %1 could not be located!"_L1.arg(base)),
2510 }
else if (QTestLog::verboseLevel() >= 1) {
2511 QTestLog::info(qPrintable(
2512 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2520
2521QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2522 const char *sourcedir)
2524 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2528
2531 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2535
2538 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2542
2545 QTEST_ASSERT(tagName);
2546 QTestData *data = QTestResult::currentTestData();
2548 QTEST_ASSERT(data->parent());
2550 int idx = data->parent()->indexOf(tagName);
2551 QTEST_ASSERT(idx != -1);
2552 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2554 return data->data(data->parent()->indexOf(tagName));
2558
2561 QTestTable *tbl = QTestTable::currentTestTable();
2562 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2564 tbl->addColumn(id, name);
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587QTestData &
QTest::newRow(
const char *dataTag)
2589 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2590 QTestTable *tbl = QTestTable::currentTestTable();
2591 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2592 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2593 "Must add columns before attempting to add rows.");
2595 return *tbl->newData(dataTag);
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625QTestData &
QTest::addRow(
const char *format, ...)
2627 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2628 QTestTable *tbl = QTestTable::currentTestTable();
2629 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2630 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2631 "Must add columns before attempting to add rows.");
2636 va_start(va, format);
2639 std::vsnprintf(buf,
sizeof buf, format, va);
2642 return *tbl->newData(buf);
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2667
2668
2671 return QTestResult::currentAppName();
2675
2676
2677
2678
2679
2680
2683 return QTestResult::currentTestFunction();
2687
2688
2689
2692 return QTestResult::currentDataTag();
2696
2697
2698
2699
2702 return QTestResult::currentTestFailed();
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2720 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2724
2725
2726
2727
2728
2729
2730
2737
2740 return currentTestObject;
2744
2747 QString mainSourceFile = QFile::decodeName(file);
2750 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2752 fi.setFile(mainSourceFile);
2756#if QT_DEPRECATED_SINCE(6
, 4
)
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775bool QTest::compare_helper(
bool success,
const char *failureMsg,
2776 char *actualVal,
char *expectedVal,
2777 const char *actual,
const char *expected,
2778 const char *file,
int line)
2780 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2781 actual, expected, file, line);
2785#if QT_DEPRECATED_SINCE(6
, 8
)
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799bool QTest::compare_helper(
bool success,
const char *failureMsg,
2800 qxp::function_ref<
const char *()> actualVal,
2801 qxp::function_ref<
const char *()> expectedVal,
2802 const char *actual,
const char *expected,
2803 const char *file,
int line)
2805 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2806 QTest::functionRefFormatter,
2807 QTest::functionRefFormatter, actual, expected,
2808 QTest::ComparisonOperation::CustomCompare,
2809 file, line, failureMsg);
2814
2815
2816
2817
2818
2819
2820
2821
2824 const void *actualPtr,
const void *expectedPtr,
2825 const char *(*actualFormatter)(
const void *),
2826 const char *(*expectedFormatter)(
const void *),
2827 const char *actual,
const char *expected,
2828 const char *file,
int line)
2830 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2831 actualFormatter, expectedFormatter,
2833 QTest::ComparisonOperation::CustomCompare,
2834 file, line, failureMsg);
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2866 const void *lhsPtr,
const void *rhsPtr,
2867 const char *(*lhsFormatter)(
const void*),
2868 const char *(*rhsFormatter)(
const void*),
2869 const char *lhsExpression,
const char *rhsExpression,
2870 const char *(*actualOrderFormatter)(
const void *),
2871 const char *(*expectedOrderFormatter)(
const void *),
2872 const void *actualOrderPtr,
const void *expectedOrderPtr,
2873 const char *expectedExpression,
2874 const char *file,
int line)
2876 return QTestResult::report3WayResult(success, failureMsg,
2878 lhsFormatter, rhsFormatter,
2879 lhsExpression, rhsExpression,
2880 actualOrderFormatter,
2881 expectedOrderFormatter,
2882 actualOrderPtr, expectedOrderPtr,
2888
2889
2890
2891
2892
2893
2894
2895
2896
2898 const char *expected,
const char *file,
int line)
2900 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2903template <
typename T>
2906 switch (qFpClassify(expected))
2909 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2911 return qFpClassify(actual) == FP_NAN;
2913 if (!qFuzzyIsNull(expected))
2914 return qFuzzyCompare(actual, expected);
2918 return qFuzzyIsNull(actual);
2923
2924
2925bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2926 const char *file,
int line)
2928 auto formatter = Internal::genericToString<qfloat16>;
2929 return compare_helper(floatingCompare(t1, t2),
2930 "Compared qfloat16s are not the same (fuzzy compare)",
2931 &t1, &t2, formatter, formatter,
2932 actual, expected, file, line);
2936
2937
2938bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
2939 const char *file,
int line)
2941 return QTestResult::compare(floatingCompare(t1, t2),
2942 "Compared floats are not the same (fuzzy compare)",
2943 t1, t2, actual, expected, file, line);
2947
2948
2949bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
2950 const char *file,
int line)
2952 return QTestResult::compare(floatingCompare(t1, t2),
2953 "Compared doubles are not the same (fuzzy compare)",
2954 t1, t2, actual, expected, file, line);
2958
2959
2960
2962 const char *file,
int line)
2964 return QTestResult::compare(t1 == t2,
2965 "Compared values are not the same",
2966 t1, t2, actual, expected, file, line);
2969#if QT_POINTER_SIZE == 8
2971
2972
2973
2975bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
2976 const char *file,
int line)
2978 return QTestResult::compare(t1 == t2,
2979 "Compared values are not the same",
2980 t1, t2, actual, expected, file, line);
2985
2986
2987
2988bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
2989 const char *file,
int line)
2991 return QTestResult::compare(t1 == t2,
2992 "Compared values are not the same",
2993 t1, t2, actual, expected, file, line);
2997
2998
2999
3000bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3001 const char *file,
int line)
3003 return QTestResult::compare(t1 == t2,
3004 "Compared values are not the same",
3005 t1, t2, actual, expected, file, line);
3009
3010
3011
3012bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3013 const char *file,
int line)
3015 return QTestResult::compare(t1 == t2,
3016 "Compared values are not the same",
3017 t1, t2, actual, expected, file, line);
3021
3022
3023
3024bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3025 const char *file,
int line)
3027 return QTestResult::compare(t1 == t2,
3028 "Compared values are not the same",
3029 t1, t2, actual, expected, file, line);
3033
3034
3035
3038
3039
3040
3043
3044
3045
3048
3049
3052
3053
3055#define TO_STRING_IMPL(TYPE, FORMAT) template
3056 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3057{
3058 char *msg = new char[128
];
3059 std::snprintf(msg, 128
, #FORMAT, t);
3061}
3080 char *msg =
new char[128];
3081 switch (qFpClassify(t)) {
3083 qstrncpy(msg, (t < 0 ?
"-inf" :
"inf"), 128);
3086 qstrncpy(msg,
"nan", 128);
3089 std::snprintf(msg, 128,
"%.*g (%a)", digits10, t, t);
3095#define TO_STRING_FLOAT(TYPE) template
3096 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3097{
3098 return toStringFp(t, std::numeric_limits<TYPE>::digits10 + 1
); \
3099}
3106 unsigned char c =
static_cast<
unsigned char>(t);
3107 char *msg =
new char[16];
3110 qstrcpy(msg,
"'\\0'");
3113 qstrcpy(msg,
"'\\a'");
3116 qstrcpy(msg,
"'\\b'");
3119 qstrcpy(msg,
"'\\t'");
3122 qstrcpy(msg,
"'\\n'");
3125 qstrcpy(msg,
"'\\v'");
3128 qstrcpy(msg,
"'\\f'");
3131 qstrcpy(msg,
"'\\r'");
3134 qstrcpy(msg,
"'\\\"'");
3137 qstrcpy(msg,
"'\\\''");
3140 qstrcpy(msg,
"'\\\\'");
3143 if (c < 0x20 || c >= 0x7F)
3144 std::snprintf(msg, 16,
"'\\x%02x'", c);
3146 std::snprintf(msg, 16,
"'%c'" , c);
3152
3156 char *msg =
new char[1];
3160 char *msg =
new char[strlen(str) + 1];
3161 return qstrcpy(msg, str);
3165
3168 char *msg =
new char[128];
3169 std::snprintf(msg, 128,
"%p", p);
3174
3178 return qstrdup(
"<null>");
3180 return QTest::toString(
const_cast<
const QObject*>(vo));
3184
3188 return qstrdup(
"<null>");
3190 const QString &name = o->objectName();
3191 const char *className = o->metaObject()->className();
3192 char *msg =
new char[256];
3194 std::snprintf(msg, 256,
"%s/%p", className, o);
3196 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3202
3203
3206
3207
3210
3211
3214
3215
3218
3219
3222
3223
3226
3228 const char *expected,
const char *file,
int line)
3230 auto formatter = Internal::genericToString<
const char *>;
3231 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3232 &t1, &t2, formatter, formatter,
3233 actual, expected, file, line);
3237
3238
3239
3242
3243
3246
3247
3250
3251
3254
3255
3258
3259
3262
3263
3266
3267
3270
3271
3274
3275
3278
3279
3282
3283
3286
3287
3290
3291
3294
3295
3298
3299
3302
3303
3306
3307
3310
3311
3314
3315
3318
3319
3322
3323
3326
3327
3330
3331
3334
3335
3338
3339
3342
3343
3346
3347
3350
3351
3354
3355
3358
3359
3362
3363
3366
3367
3370
3371
3374
3375
3378
3379
3382
3383
3386
3387
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 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 bool floatingCompare(const T &actual, const T &expected)
static char * toStringFp(double t, int digits10)
#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()
QTestDataSetter(QTestData *data)