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"_L1
1127 :
"accumulation stage result: %1"_L1;
1128 QTestLog::info(qPrintable(pattern.arg(first.measurement.value)),
nullptr, 0);
1134 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1135 minimumTotalReached =
true;
1137 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1139 current += r.first().measurement.value;
1142 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1143 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1145 }
while (isBenchmark
1146 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1147 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1151 bool testPassed = !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed();
1152 QTestResult::finishedCurrentTestDataCleanup();
1154 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1155 QTestLog::addBenchmarkResults(qMedian(resultsList));
1159#if QT_CONFIG(thread)
1256 qFatal(
"Test function timed out");
1279template <
typename Functor>
1283 watchDog->beginTest();
1288 watchDog->testFinished();
1292 const QTestTable &lTable,
const QTestTable &gTable)
1294 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1295 const int localDataCount = lTable.dataCount();
1296 if (localDataCount) {
1297 std::fputs(
"Available test-specific data tags:\n", stderr);
1298 for (
int i = 0; i < localDataCount; ++i)
1299 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1301 const int globalDataCount = gTable.dataCount();
1302 if (globalDataCount) {
1303 std::fputs(
"Available global data tags:\n", stderr);
1304 for (
int i = 0; i < globalDataCount; ++i)
1305 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1307 if (localDataCount == 0 && globalDataCount == 0)
1308 std::fputs(
"Function has no data tags\n", stderr);
1312
1313
1314
1315
1316
1319 QBenchmarkTestMethodData benchmarkData;
1320 QBenchmarkTestMethodData::current = &benchmarkData;
1322 const QByteArray &name = m_methods[index].name();
1323 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1328 QTestResult::setCurrentTestFunction(name.constData());
1330 const QTestTable *gTable = QTestTable::globalTestTable();
1331 const int globalDataCount = gTable->dataCount();
1332 int curGlobalDataIndex = 0;
1333 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1334 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1337 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1338 QLatin1StringView global) {
1341 if (tag == local || tag == global)
1344 return tag.startsWith(global) && tag.endsWith(local) &&
1345 tag.size() == global.size() + 1 + local.size() &&
1346 tag[global.size()] ==
':';
1348 bool foundFunction =
false;
1349 bool blacklisted =
false;
1353 if (!gTable->isEmpty())
1354 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1356 if (curGlobalDataIndex == 0) {
1357 std::snprintf(member, 512,
"%s_data()", name.constData());
1358 runWithWatchdog(watchDog, [&member] {
1361 if (QTestResult::skipCurrentTest())
1365 int curDataIndex = 0;
1366 const int dataCount = table.dataCount();
1367 const auto dataTag = [&table, dataCount](
int index) {
1368 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1373 QTestResult::setSkipCurrentTest(
false);
1374 QTestResult::setBlacklistCurrentTest(
false);
1375 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1376 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1377 foundFunction =
true;
1378 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1379 globalDataTag(curGlobalDataIndex));
1381 QTestResult::setBlacklistCurrentTest(
true);
1384 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1386 QTestResult::finishedCurrentTestData();
1387 QTestResult::finishedCurrentTestDataCleanup();
1390 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1392 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1398 runWithWatchdog(watchDog, [
this, index] {
1399 invokeTestOnData(index);
1403 if (!tag.isEmpty() && !globalDataCount)
1407 }
while (curDataIndex < dataCount);
1409 QTestResult::setCurrentGlobalTestData(
nullptr);
1410 ++curGlobalDataIndex;
1411 }
while (curGlobalDataIndex < globalDataCount);
1413 if (!tag.isEmpty() && !foundFunction) {
1414 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1415 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1417 QTestResult::finishedCurrentTestFunction();
1418 QTestResult::setSkipCurrentTest(
false);
1419 QTestResult::setBlacklistCurrentTest(
false);
1422void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1424 QTEST_ASSERT(typeId);
1425 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1426 QTEST_ASSERT(data->parent());
1428 int idx = data->parent()->indexOf(tagName);
1430 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1431 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1435 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1436 qFatal(
"Requested type '%s' does not match available type '%s'.",
1437 QMetaType(typeId).name(),
1438 QMetaType(data->parent()->elementTypeId(idx)).name());
1441 return data->data(idx);
1445
1446
1447char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1450 va_start(ap, numArguments);
1452 QByteArray arguments;
1453 arguments += prefix;
1455 if (numArguments > 0) {
1456 arguments += va_arg(ap,
const char *);
1458 for (size_t i = 1; i < numArguments; ++i) {
1460 arguments += va_arg(ap,
const char *);
1465 arguments += suffix;
1466 return qstrdup(arguments.constData());
1470
1471
1472
1473
1474
1475
1476
1477
1478
1485
1486
1487
1488
1489
1490
1491 const qsizetype maxLen = 50;
1492 const qsizetype len = qMin(maxLen, length);
1493 char *result =
nullptr;
1495 if (length > maxLen) {
1496 const qsizetype size = len * 3 + 4;
1497 result =
new char[size];
1499 char *
const forElipsis = result + size - 5;
1500 forElipsis[0] =
' ';
1501 forElipsis[1] =
'.';
1502 forElipsis[2] =
'.';
1503 forElipsis[3] =
'.';
1504 result[size - 1] =
'\0';
1507 const qsizetype size = len * 3;
1508 result =
new char[size];
1509 result[size - 1] =
'\0';
1516 const char at = ba[i];
1518 result[o] = toHexUpper(at >> 4);
1520 result[o] = toHexUpper(at);
1534
1535
1536
1537
1540 bool trimmed =
false;
1541 auto buffer =
std::make_unique<
char[]>(256);
1542 const char *end = p + length;
1543 char *dst = buffer.get();
1545 bool lastWasHexEscape =
false;
1547 for ( ; p != end; ++p) {
1553 if (dst - buffer.get() > 246) {
1560 if (Q_UNLIKELY(lastWasHexEscape)) {
1561 if (fromHex(*p) != -1) {
1566 lastWasHexEscape =
false;
1569 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1600 *dst++ = toHexUpper(uchar(*p) >> 4);
1601 *dst++ = toHexUpper(uchar(*p));
1602 lastWasHexEscape =
true;
1614 return buffer.release();
1618
1619
1620
1621
1622
1623
1624
1633 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1634 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1663 *dst++ = toHexUpper(ch >> 12);
1664 *dst++ = toHexUpper(ch >> 8);
1665 *dst++ = toHexUpper(ch >> 4);
1666 *dst++ = toHexUpper(ch);
1674 auto p = string.utf16();
1675 auto length = string.size();
1677 bool trimmed =
false;
1678 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1679 const auto end = p + length;
1680 char *dst = buffer.get();
1683 for ( ; p != end; ++p) {
1684 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1688 dst = writePrettyUnicodeChar(*p, dst);
1698 return buffer.release();
1703 const QMetaObject *metaObject = testObject->metaObject();
1704 QTEST_ASSERT(metaObject);
1707 if (!CrashHandler::alreadyDebugging()
1708#if QT_CONFIG(valgrind)
1709 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1715 QTestResult::setCurrentTestFunction(
"initTestCase");
1716 runWithWatchdog(watchDog, [
this, testObject] {
1717 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1720 QSignalDumper::startDump();
1722 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1724 runWithWatchdog(watchDog, [
this, testObject] {
1725 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1729 const bool previousFailed = QTestResult::currentTestFailed();
1730 QTestResult::finishedCurrentTestData();
1731 QTestResult::finishedCurrentTestDataCleanup();
1732 QTestResult::finishedCurrentTestFunction();
1734 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1735 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1736 const char *data =
nullptr;
1737 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1738 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1739 invokeTest(i, QLatin1StringView(data), watchDog);
1744 const bool wasSkipped = QTestResult::skipCurrentTest();
1745 QTestResult::setSkipCurrentTest(
false);
1746 QTestResult::setBlacklistCurrentTest(
false);
1747 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1748 runWithWatchdog(watchDog, [
this, testObject] {
1749 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1752 QTestResult::finishedCurrentTestData();
1754 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1755 QTestResult::finishedCurrentTestDataCleanup();
1757 QTestResult::finishedCurrentTestFunction();
1758 QTestResult::setCurrentTestFunction(
nullptr);
1760 QSignalDumper::endDump();
1763#if QT_DEPRECATED_SINCE(6
, 8
)
1782 const char *(*lhsFormatter)(
const void*),
1783 const char *(*rhsFormatter)(
const void*),
1784 const char *lhsExpr,
const char *rhsExpr,
1785 ComparisonOperation op,
const char *file,
int line)
1787 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1788 lhsExpr, rhsExpr, op, file, line);
1794 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1798static QFile androidExitCodeFile()
1800 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1801 return QFile(testHome +
"/qtest_last_exit_code"_L1);
1806
1807
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
1843int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1849 qInit(testObject, argc, argv);
1853#if defined(Q_OS_WASM)
1855 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1856 Module.notifyTestFinished($0);
1864
1865void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1868 CrashHandler::maybeDisableCoreDump();
1869 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1871#if defined(Q_OS_MACOS)
1873 QTestPrivate::disableWindowRestore();
1876 if (!appNapDisabler)
1877 appNapDisabler.emplace();
1879 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1880 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1881 &macPowerSavingDisabled);
1884 QTestPrivate::parseBlackList();
1885 QTestResult::reset();
1887 QTEST_ASSERT(testObject);
1888 QTEST_ASSERT(!currentTestObject);
1891 const QMetaObject *metaObject = testObject->metaObject();
1892 QTEST_ASSERT(metaObject);
1894 QTestResult::setCurrentTestObject(metaObject->className());
1896 QTestResult::setCurrentAppName(argv[0]);
1900#if QT_CONFIG(valgrind)
1901 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1903 QTestLog::startLogging();
1906 androidExitCodeFile().remove();
1911
1914 QTEST_ASSERT(currentTestObject);
1916#if QT_CONFIG(valgrind)
1917 int callgrindChildExitCode = 0;
1920#ifndef QT_NO_EXCEPTIONS
1924#if QT_CONFIG(valgrind)
1925 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1926 if (Q_UNLIKELY(!qApp))
1927 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1929 const QStringList origAppArgs(QCoreApplication::arguments());
1930 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1933 QBenchmarkValgrindUtils::cleanup();
1938 std::optional<CrashHandler::FatalSignalHandler> handler;
1939 CrashHandler::prepareStackTrace();
1943 TestMethods::MetaMethods commandLineMethods;
1944 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1945 std::vector<size_t> badFunctionIndices;
1947 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1948 const QByteArray tfB = tf.toLatin1();
1949 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1950 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1951 if (m.isValid() && isValidSlot(m)) {
1952 commandLineMethods.push_back(m);
1954 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1955 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1956 std::fputc(
'\n', stderr);
1957 QTestResult::setCurrentTestFunction(tfB.constData());
1958 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1959 QTestResult::finishedCurrentTestFunction();
1961 badFunctionIndices.insert(badFunctionIndices.begin(), index);
1965 if (badFunctionIndices.size() > 0) {
1967 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1968 QTestResult::currentAppName());
1969 if (commandLineMethods.empty())
1975 for (size_t i : std::as_const(badFunctionIndices)) {
1982 QTest::testFunctions.removeAt(i);
1983 QTest::testTags.removeAt(i);
1991 const int badArgCount = QTestLog::failCount();
1992 while (!(QTestLog::failCount() > badArgCount)
1993 && (repeatForever || remainingRepetitions-- > 0)) {
1994 QTestTable::globalTestTable();
1995 test.invokeTests(currentTestObject);
1996 QTestTable::clearGlobalTestTable();
2000#ifndef QT_NO_EXCEPTIONS
2002 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
2003 if (QTestResult::currentTestFunction()) {
2004 QTestResult::finishedCurrentTestFunction();
2005 QTestResult::setCurrentTestFunction(
nullptr);
2016#if QT_CONFIG(valgrind)
2017 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2018 return callgrindChildExitCode;
2022 const int exitCode = qMin(QTestLog::failCount(), 127);
2025 QFile exitCodeFile = androidExitCodeFile();
2026 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2027 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2029 qWarning(
"Failed to open %s for writing test exit code: %s",
2030 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2038
2043#if QT_CONFIG(valgrind)
2044 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2046 QTestLog::stopLogging();
2048 delete QBenchmarkGlobalData::current;
2049 QBenchmarkGlobalData::current =
nullptr;
2051#if defined(Q_OS_MACOS)
2052 IOPMAssertionRelease(macPowerSavingDisabled);
2053 appNapDisabler = std::nullopt;
2057#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2070 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2073QList<QString> QTest::qGetTestCaseNames()
2075 return QTest::TestRegistry::instance()->getAllTestNames();
2078QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2080 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2086
2087
2088
2089
2090
2091
2092int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2094 const int argc = arguments.size();
2095 QVarLengthArray<
char *> argv(argc);
2097 QList<QByteArray> args;
2100 for (
int i = 0; i < argc; ++i)
2102 args.append(arguments.at(i).toLocal8Bit().constData());
2103 argv[i] = args.last().data();
2106 return qExec(testObject, argc, argv.data());
2110
2111void QTest::
qFail(
const char *message,
const char *file,
int line)
2113 QTestResult::fail(message, file, line);
2117
2118bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2119 const char *file,
int line)
2121 return QTestResult::verify(statement, statementStr, description, file, line);
2125
2126
2127void QTest::
qSkip(
const char *message,
const char *file,
int line)
2129 QTestResult::addSkip(message, file, line);
2130 QTestResult::setSkipCurrentTest(
true);
2134
2135
2137 QTest::TestFailMode mode,
const char *file,
int line)
2139 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2160 auto message = [&] {
2161 const auto exType = what ?
"std::" :
"unknown ";
2162 const auto ofType = expected ?
" of type " :
"";
2163 const auto no = expected ?
"an" :
"no";
2164 const auto withMsg = what ?
" with message " :
"";
2165 const auto protect = [](
const char *s) {
return s ? s :
""; };
2167 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2168 "but caught %sexception%s%s",
2169 no, ofType, protect(expected),
2170 exType, withMsg, protect(what));
2172 qFail(message().toUtf8().constData(), file, line);
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2198 std::rethrow_exception(
std::current_exception());
2199 }
catch (
const std::exception &e) {
2200 qCaught(expected, e.what(), file, line);
2202 qCaught(expected,
nullptr, file, line);
2209#if QT_DEPRECATED_SINCE(6
, 3
)
2211
2212
2213
2214void QTest::qWarn(
const char *message,
const char *file,
int line)
2216 QTestLog::warn(message, file, line);
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2240 QTestLog::ignoreMessage(type, message);
2243#if QT_CONFIG(regularexpression)
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2261 QTestLog::ignoreMessage(type, messagePattern);
2266
2267
2269
2270
2271
2272
2275 return QTestLog::failOnWarning();
2279
2280
2282
2283
2284
2285
2288 return QTestLog::failOnWarning(message);
2291#if QT_CONFIG(regularexpression)
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2346 QTestLog::failOnWarning(messagePattern);
2351
2354static inline bool isWindowsBuildDirectory(
const QString &dirName)
2356 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2357 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2361#if QT_CONFIG(temporaryfile)
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2374 QSharedPointer<QTemporaryDir> result;
2376 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2378 tempDir->setAutoRemove(
true);
2380 if (!tempDir->isValid())
2383 const QString dataPath = tempDir->path();
2384 const QString resourcePath = u':' + dirName;
2385 const QFileInfo fileInfo(resourcePath);
2387 if (!fileInfo.isDir()) {
2388 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2392 bool isResourceDirEmpty =
true;
2393 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2394 isResourceDirEmpty =
false;
2395 if (!dirEntry.isDir()) {
2396 const QString &filePath = dirEntry.filePath();
2397 const QString destination =
2398 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2399 QFileInfo destinationFileInfo(destination);
2400 QDir().mkpath(destinationFileInfo.path());
2401 QFile file(filePath);
2402 if (!file.copy(destination, QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2403 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2404 qUtf16Printable(file.errorString()));
2410 if (isResourceDirEmpty) {
2411 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2415 result = std::move(tempDir);
2422
2424QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2425 const char *sourcedir)
2433 QDir binDirectory(QCoreApplication::applicationDirPath());
2434 if (binDirectory.exists(base)) {
2435 found = binDirectory.absoluteFilePath(base);
2440 else if (isWindowsBuildDirectory(binDirectory.dirName())
2441 && binDirectory.cdUp() && binDirectory.exists(base)) {
2442 found = binDirectory.absoluteFilePath(base);
2445 else if (QTestLog::verboseLevel() >= 2) {
2446 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2447 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2448 "checking next location"_L1.arg(base, candidate)),
2454 if (found.isEmpty()) {
2455 const char *testObjectName = QTestResult::currentTestObjectName();
2456 if (testObjectName) {
2457 const QString testsPath = QLibraryInfo::path(QLibraryInfo::TestsPath);
2458 const QString candidate =
"%1/%2/%3"_L1
2459 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2460 if (QFileInfo::exists(candidate)) {
2462 }
else if (QTestLog::verboseLevel() >= 2) {
2463 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2464 "checking next location"_L1
2465 .arg(base, QDir::toNativeSeparators(candidate))),
2472 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2474 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2478 if (!srcdir.isAbsolute() && builddir)
2479 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2481 const QString canonicalPath = srcdir.canonicalFilePath();
2482 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2483 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2485 }
else if (QTestLog::verboseLevel() >= 2) {
2486 QTestLog::info(qPrintable(
2487 "testdata %1 not found relative to source path [%2]"_L1
2488 .arg(base, QDir::toNativeSeparators(candidate))),
2494 if (found.isEmpty()) {
2495 const QString candidate =
":/%1"_L1.arg(base);
2496 if (QFileInfo::exists(candidate)) {
2498 }
else if (QTestLog::verboseLevel() >= 2) {
2499 QTestLog::info(qPrintable(
2500 "testdata %1 not found in resources [%2]"_L1
2501 .arg(base, QDir::toNativeSeparators(candidate))),
2507 if (found.isEmpty()) {
2508 const QString candidate = QDir::currentPath() + u'/' + base;
2509 if (QFileInfo::exists(candidate)) {
2511 }
else if (QTestLog::verboseLevel() >= 2) {
2512 QTestLog::info(qPrintable(
2513 "testdata %1 not found in current directory [%2]"_L1
2514 .arg(base, QDir::toNativeSeparators(candidate))),
2520 if (found.isEmpty()) {
2521 const QString candidate = QTest::mainSourcePath % u'/' % base;
2522 if (QFileInfo::exists(candidate)) {
2524 }
else if (QTestLog::verboseLevel() >= 2) {
2525 QTestLog::info(qPrintable(
2526 "testdata %1 not found in main source directory [%2]"_L1
2527 .arg(base, QDir::toNativeSeparators(candidate))),
2533 if (found.isEmpty() && sourcedir) {
2534 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2535 if (QFileInfo::exists(candidate)) {
2537 }
else if (QTestLog::verboseLevel() >= 2) {
2538 QTestLog::info(qPrintable(
2539 "testdata %1 not found in supplied source directory [%2]"_L1
2540 .arg(base, QDir::toNativeSeparators(candidate))),
2546 if (found.isEmpty()) {
2547 QTestLog::warn(qPrintable(
2548 "testdata %1 could not be located!"_L1.arg(base)),
2550 }
else if (QTestLog::verboseLevel() >= 1) {
2551 QTestLog::info(qPrintable(
2552 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2560
2561QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2562 const char *sourcedir)
2564 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2568
2571 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2575
2578 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2582
2585 QTEST_ASSERT(tagName);
2586 QTestData *data = QTestResult::currentTestData();
2588 QTEST_ASSERT(data->parent());
2590 int idx = data->parent()->indexOf(tagName);
2591 QTEST_ASSERT(idx != -1);
2592 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2594 return data->data(data->parent()->indexOf(tagName));
2598
2601 QTestTable *tbl = QTestTable::currentTestTable();
2602 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2604 tbl->addColumn(id, name);
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627QTestData &
QTest::newRow(
const char *dataTag)
2629 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2630 QTestTable *tbl = QTestTable::currentTestTable();
2631 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2632 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2633 "Must add columns before attempting to add rows.");
2635 return *tbl->newData(dataTag);
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665QTestData &
QTest::addRow(
const char *format, ...)
2667 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2668 QTestTable *tbl = QTestTable::currentTestTable();
2669 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2670 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2671 "Must add columns before attempting to add rows.");
2676 va_start(va, format);
2679 std::vsnprintf(buf,
sizeof buf, format, va);
2682 return *tbl->newData(buf);
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2707
2708
2711 return QTestResult::currentAppName();
2715
2716
2717
2718
2719
2720
2723 return QTestResult::currentTestFunction();
2727
2728
2729
2732 return QTestResult::currentDataTag();
2736
2737
2738
2739
2740
2743 return QTestResult::currentGlobalDataTag();
2747
2748
2749
2750
2753 return QTestResult::currentTestFailed();
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2771 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2775
2776
2777
2778
2779
2780
2781
2788
2791 return currentTestObject;
2795
2798 QString mainSourceFile = QFile::decodeName(file);
2801 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2803 fi.setFile(mainSourceFile);
2807#if QT_DEPRECATED_SINCE(6
, 4
)
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826bool QTest::compare_helper(
bool success,
const char *failureMsg,
2827 char *actualVal,
char *expectedVal,
2828 const char *actual,
const char *expected,
2829 const char *file,
int line)
2831 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2832 actual, expected, file, line);
2836#if QT_DEPRECATED_SINCE(6
, 8
)
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850bool QTest::compare_helper(
bool success,
const char *failureMsg,
2851 qxp::function_ref<
const char *()> actualVal,
2852 qxp::function_ref<
const char *()> expectedVal,
2853 const char *actual,
const char *expected,
2854 const char *file,
int line)
2856 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2857 QTest::functionRefFormatter,
2858 QTest::functionRefFormatter, actual, expected,
2859 QTest::ComparisonOperation::CustomCompare,
2860 file, line, failureMsg);
2865
2866
2867
2868
2869
2870
2871
2872
2875 const void *actualPtr,
const void *expectedPtr,
2876 const char *(*actualFormatter)(
const void *),
2877 const char *(*expectedFormatter)(
const void *),
2878 const char *actual,
const char *expected,
2879 const char *file,
int line)
2881 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2882 actualFormatter, expectedFormatter,
2884 QTest::ComparisonOperation::CustomCompare,
2885 file, line, failureMsg);
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2917 const void *lhsPtr,
const void *rhsPtr,
2918 const char *(*lhsFormatter)(
const void*),
2919 const char *(*rhsFormatter)(
const void*),
2920 const char *lhsExpression,
const char *rhsExpression,
2921 const char *(*actualOrderFormatter)(
const void *),
2922 const char *(*expectedOrderFormatter)(
const void *),
2923 const void *actualOrderPtr,
const void *expectedOrderPtr,
2924 const char *expectedExpression,
2925 const char *file,
int line)
2927 return QTestResult::report3WayResult(success, failureMsg,
2929 lhsFormatter, rhsFormatter,
2930 lhsExpression, rhsExpression,
2931 actualOrderFormatter,
2932 expectedOrderFormatter,
2933 actualOrderPtr, expectedOrderPtr,
2939
2940
2941
2942
2943
2944
2945
2946
2947
2949 const char *expected,
const char *file,
int line)
2951 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2954template <
typename T>
2957 switch (qFpClassify(expected))
2960 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2962 return qFpClassify(actual) == FP_NAN;
2964 if (!qFuzzyIsNull(expected))
2965 return qFuzzyCompare(actual, expected);
2969 return qFuzzyIsNull(actual);
2974
2975
2976bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2977 const char *file,
int line)
2979 auto formatter = Internal::genericToString<qfloat16>;
2980 return compare_helper(floatingCompare(t1, t2),
2981 "Compared qfloat16s are not the same (fuzzy compare)",
2982 &t1, &t2, formatter, formatter,
2983 actual, expected, file, line);
2987
2988
2989bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
2990 const char *file,
int line)
2992 return QTestResult::compare(floatingCompare(t1, t2),
2993 "Compared floats are not the same (fuzzy compare)",
2994 t1, t2, actual, expected, file, line);
2998
2999
3000bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
3001 const char *file,
int line)
3003 return QTestResult::compare(floatingCompare(t1, t2),
3004 "Compared doubles are not the same (fuzzy compare)",
3005 t1, t2, actual, expected, file, line);
3009
3010
3011
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);
3020#if QT_POINTER_SIZE == 8
3022
3023
3024
3026bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3027 const char *file,
int line)
3029 return QTestResult::compare(t1 == t2,
3030 "Compared values are not the same",
3031 t1, t2, actual, expected, file, line);
3036
3037
3038
3039bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3040 const char *file,
int line)
3042 return QTestResult::compare(t1 == t2,
3043 "Compared values are not the same",
3044 t1, t2, actual, expected, file, line);
3048
3049
3050
3051bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3052 const char *file,
int line)
3054 return QTestResult::compare(t1 == t2,
3055 "Compared values are not the same",
3056 t1, t2, actual, expected, file, line);
3060
3061
3062
3063bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3064 const char *file,
int line)
3066 return QTestResult::compare(t1 == t2,
3067 "Compared values are not the same",
3068 t1, t2, actual, expected, file, line);
3072
3073
3074
3075bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3076 const char *file,
int line)
3078 return QTestResult::compare(t1 == t2,
3079 "Compared values are not the same",
3080 t1, t2, actual, expected, file, line);
3084
3085
3086
3089
3090
3091
3094
3095
3096
3099
3100
3103
3104
3106#define TO_STRING_IMPL(TYPE, FORMAT) template
3107 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3108{
3109 char *msg = new char[128
];
3110 std::snprintf(msg, 128
, #FORMAT, t);
3112}
3129 constexpr int Digits =
std::numeric_limits<T>::digits;
3130 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3131 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3132 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3138 Q_ASSERT(qIsNaN(t));
3139 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3140 r.payload = u & PayloadMask;
3141 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3151 char *msg =
new char[128];
3152 bool negative = signbit(t);
3154 switch (qFpClassify(t)) {
3156 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3159 if (
auto r = decodeNanPayload(t); r.payload) {
3160 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3161 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3163 Q_ASSERT(r.isQuiet);
3164 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3168 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3171 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3178#define TO_STRING_FLOAT(TYPE) template
3179 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3180{
3181 return toStringFp(t); \
3182}
3189 unsigned char c =
static_cast<
unsigned char>(t);
3190 char *msg =
new char[16];
3193 qstrcpy(msg,
"'\\0'");
3196 qstrcpy(msg,
"'\\a'");
3199 qstrcpy(msg,
"'\\b'");
3202 qstrcpy(msg,
"'\\t'");
3205 qstrcpy(msg,
"'\\n'");
3208 qstrcpy(msg,
"'\\v'");
3211 qstrcpy(msg,
"'\\f'");
3214 qstrcpy(msg,
"'\\r'");
3217 qstrcpy(msg,
"'\\\"'");
3220 qstrcpy(msg,
"'\\\''");
3223 qstrcpy(msg,
"'\\\\'");
3226 if (c < 0x20 || c >= 0x7F)
3227 std::snprintf(msg, 16,
"'\\x%02x'", c);
3229 std::snprintf(msg, 16,
"'%c'" , c);
3235
3239 char *msg =
new char[1];
3243 char *msg =
new char[strlen(str) + 1];
3244 return qstrcpy(msg, str);
3248
3251 char *msg =
new char[128];
3252 std::snprintf(msg, 128,
"%p", p);
3257
3261 return qstrdup(
"<null>");
3263 return QTest::toString(
const_cast<
const QObject*>(vo));
3267
3271 return qstrdup(
"<null>");
3273 const QString &name = o->objectName();
3274 const char *className = o->metaObject()->className();
3275 char *msg =
new char[256];
3277 std::snprintf(msg, 256,
"%s/%p", className, o);
3279 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3285
3286
3289
3290
3293
3294
3297
3298
3301
3302
3305
3306
3309
3311 const char *expected,
const char *file,
int line)
3313 auto formatter = Internal::genericToString<
const char *>;
3314 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3315 &t1, &t2, formatter, formatter,
3316 actual, expected, file, line);
3320
3321
3322
3325
3326
3329
3330
3333
3334
3337
3338
3341
3342
3345
3346
3349
3350
3353
3354
3357
3358
3361
3362
3365
3366
3369
3370
3373
3374
3377
3378
3381
3382
3385
3386
3389
3390
3393
3394
3397
3398
3401
3402
3405
3406
3409
3410
3413
3414
3417
3418
3421
3422
3425
3426
3429
3430
3433
3434
3437
3438
3441
3442
3445
3446
3449
3450
3453
3454
3457
3458
3461
3462
3465
3466
3469
3470
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)