5#include <QtTest/qtestcase.h>
6#include <QtTest/private/qtestcase_p.h>
7#include <QtTest/qtestassert.h>
9#include <QtCore/qbytearray.h>
10#include <QtCore/qcoreapplication.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qdir.h>
13#include <QtCore/qdirlisting.h>
15#include <QtCore/qexception.h>
17#include <QtCore/qfile.h>
18#include <QtCore/qfileinfo.h>
19#include <QtCore/qfloat16.h>
20#include <QtCore/qlibraryinfo.h>
21#include <QtCore/qlist.h>
22#include <QtCore/qmetaobject.h>
23#include <QtCore/qobject.h>
24#include <QtCore/qstringlist.h>
25#include <QtCore/qtemporarydir.h>
26#include <QtCore/qthread.h>
27#include <QtCore/qvarlengtharray.h>
28#include <QtCore/private/qlocking_p.h>
29#include <QtCore/private/qtools_p.h>
30#include <QtCore/private/qwaitcondition_p.h>
32#include <QtCore/qtestsupport_core.h>
34#include <QtTest/private/qtestlog_p.h>
35#include <QtTest/private/qtesttable_p.h>
36#include <QtTest/qtestdata.h>
37#include <QtTest/private/qtestresult_p.h>
38#include <QtTest/private/qsignaldumper_p.h>
39#include <QtTest/private/qbenchmark_p.h>
40#if QT_CONFIG(batch_test_support)
41#include <QtTest/private/qtestregistry_p.h>
43#include <QtTest/private/cycle_include_p.h>
44#include <QtTest/private/qtestblacklist_p.h>
45#include <QtTest/private/qtestcrashhandler_p.h>
46#if defined(HAVE_XCTEST)
47#include <QtTest/private/qxctestlogger_p.h>
50#include <QtTest/private/qtestutil_macos_p.h>
53#if defined(Q_OS_DARWIN)
54#include <QtTest/private/qappletestlogger_p.h>
59#if !defined(Q_OS_INTEGRITY) || __GHS_VERSION_NUMBER > 202014
63# undef __cpp_lib_to_chars
77#if defined(Q_OS_LINUX)
84# if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR))
87#include <qt_windows.h>
90#include <QtCore/private/qcore_unix_p.h>
93#if __has_include(<paths.h>)
101# if !defined(Q_OS_INTEGRITY)
102# include <sys/resource.h>
106#if defined(Q_OS_MACOS)
107#include <IOKit/pwr_mgt/IOPMLib.h>
108#include <mach/task.h>
109#include <mach/mach_init.h>
110#include <CoreFoundation/CFPreferences.h>
113#if defined(Q_OS_WASM)
114#include <emscripten.h>
118#include <QtCore/QStandardPaths>
125using namespace Qt::StringLiterals;
127using QtMiscUtils::toHexUpper;
128using QtMiscUtils::fromHex;
132#if defined(__COVERAGESCANNER__) && !QT_CONFIG(testlib_selfcover)
133 if (!qEnvironmentVariableIsEmpty(
"QT_TESTCOCOON_ACTIVE"))
137 qputenv(
"QT_TESTCOCOON_ACTIVE",
"1");
140 __coveragescanner_install(appname);
141 __coveragescanner_testname(testname);
142 __coveragescanner_clear();
153 if (sl.access() != QMetaMethod::Private || sl.parameterCount() != 0
154 || sl.returnType() != QMetaType::Void || sl.methodType() != QMetaMethod::Slot)
156 const QByteArray name = sl.name();
157 return !(name.isEmpty() || name.endsWith(
"_data")
158 || name ==
"initTestCase" || name ==
"cleanupTestCase"
159 || name ==
"init" || name ==
"cleanup");
169#if !QT_CONFIG(future)
170using QException = std::exception;
173class TestFailedException :
public QException
176 TestFailedException() =
default;
177 ~TestFailedException() override =
default;
179 const char *what()
const noexcept override {
return "QtTest: test failed"; }
182 TestFailedException *clone()
const override {
return new TestFailedException(); }
183 void raise()
const override {
throw TestFailedException(); }
187class TestSkippedException :
public QException
190 TestSkippedException() =
default;
191 ~TestSkippedException() override =
default;
193 const char *what()
const noexcept override {
return "QtTest: test was skipped"; }
196 TestSkippedException *clone()
const override {
return new TestSkippedException(); }
197 void raise()
const override {
throw TestSkippedException(); }
225
226
227
228
229
230
231
232
233
234
237
238
239
240
241
242
243
244
245
248
249
250
251
252
253
254
255
256
259
260
261
262
263
264
266
267
268
269
271
272
273
274
277
278
279
280
281
282
284
285
286
287
289
290
291
292
295
296
297
298
299
300
302
303
304
305
307
308
309
310
313
314
315
316
317
318
320
321
322
323
325
326
327
328
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
351 g_throwOnFail.fetchAndAddRelaxed(enable ? 1 : -1);
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
375 g_throwOnSkip.fetchAndAddRelaxed(enable ? 1 : -1);
382 return "QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) "
383 "was too short, %3 ms would have been sufficient this time."_L1
395#if defined(Q_OS_MACOS)
413 void invokeTest(
int index, QLatin1StringView tag,
std::optional<
WatchDog> &watchDog)
const;
414 void invokeTestOnData(
int index)
const;
416 QMetaMethod m_initTestCaseMethod;
417 QMetaMethod m_initTestCaseDataMethod;
418 QMetaMethod m_cleanupTestCaseMethod;
419 QMetaMethod m_initMethod;
420 QMetaMethod m_cleanupMethod;
422 MetaMethods m_methods;
433 if (m_methods.empty()) {
434 const QMetaObject *metaObject = o->metaObject();
435 const int count = metaObject->methodCount();
436 m_methods.reserve(count);
437 for (
int i = 0; i < count; ++i) {
438 const QMetaMethod me = metaObject->method(i);
440 m_methods.push_back(me);
445QMetaMethod
TestMethods::findMethod(
const QObject *obj,
const char *signature)
447 const QMetaObject *metaObject = obj->metaObject();
448 const int funcIndex = metaObject->indexOfMethod(signature);
449 return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
470 try { ok = m.invoke(obj, Qt ::DirectConnection); }
471 catch (
const TestFailedException &) {}
472 catch (
const TestSkippedException &) {}
479 const QMetaObject *metaObject = obj->metaObject();
480 int funcIndex = metaObject->indexOfMethod(methodName);
482 invokeTestMethodIfValid(metaObject->method(funcIndex), obj);
488 const QByteArray env = qgetenv(
"QTEST_EVENT_DELAY");
538static bool qPrintTestSlots(FILE *stream,
const char *filter =
nullptr,
const char *preamble =
"")
540 const auto matches = [filter](
const QByteArray &s) {
541 return !filter || QLatin1StringView(s).contains(QLatin1StringView(filter),
542 Qt::CaseInsensitive);
544 bool matched =
false;
546 QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
547 if (isValidSlot(sl)) {
548 const QByteArray signature = sl.methodSignature();
549 if (matches(signature)) {
550 std::fprintf(stream,
"%s%s\n", preamble, signature.constData());
562 QTestLog::setPrintAvailableTagsMode();
565 QTestTable::globalTestTable();
567 const QTestTable *gTable = QTestTable::globalTestTable();
569 const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject();
572 for (
int i = 0; i < currTestMetaObj->methodCount(); ++i) {
573 QMetaMethod tf = currTestMetaObj->method(i);
575 if (isValidSlot(tf)) {
578 QStringList localTags;
580 const QByteArray slot = tf.methodSignature().chopped(2);
581 const QByteArray member = slot +
"_data()";
582 invokeTestMethodIfExists(member.constData());
583 const int dataCount = table.dataCount();
584 localTags.reserve(dataCount);
585 for (
int j = 0; j < dataCount; ++j)
586 localTags << QLatin1StringView(table.testData(j)->dataTag());
589 if (gTable->dataCount() == 0) {
590 if (localTags.size() == 0) {
592 std::fprintf(stream,
"%s %s\n", currTestMetaObj->className(), slot.data());
595 for (
int k = 0; k < localTags.size(); ++k)
596 std::fprintf(stream,
"%s %s %s\n",
597 currTestMetaObj->className(),
599 localTags.at(k).toLatin1().data());
602 for (
int j = 0; j < gTable->dataCount(); ++j) {
603 if (localTags.size() == 0) {
605 std::fprintf(stream,
"%s %s __global__ %s\n",
606 currTestMetaObj->className(),
608 gTable->testData(j)->dataTag());
612 for (
int k = 0; k < localTags.size(); ++k)
613 std::fprintf(stream,
"%s %s %s __global__ %s\n",
614 currTestMetaObj->className(),
616 localTags.at(k).toLatin1().data(),
617 gTable->testData(j)->dataTag());
628 int l =
static_cast<
int>(strtol(str, &pEnd, 10));
630 std::fprintf(stderr,
"Invalid numeric parameter: '%s'\n", str);
639 const char *logFilename =
nullptr;
643 QTest::testFunctions.clear();
644 QTest::testTags.clear();
646#if defined(Q_OS_DARWIN) && defined(HAVE_XCTEST)
647 if (QXcodeTestLogger::canLogTestProgress())
648 logFormat = QTestLog::XCTest;
651 const char *testOptions =
652 " New-style logging options:\n"
653 " -o filename,format : Output results to file in the specified format\n"
654 " Use - to output to stdout\n"
655 " Valid formats are:\n"
656 " txt : Plain text\n"
657 " csv : CSV format (suitable for benchmarks)\n"
658 " junitxml : XML JUnit document\n"
659 " xml : XML document\n"
660 " lightxml : A stream of XML tags\n"
661 " teamcity : TeamCity format\n"
662 " tap : Test Anything Protocol\n"
664 " *** Multiple loggers can be specified, but at most one can log to stdout.\n"
666 " Old-style logging options:\n"
667 " -o filename : Write the output into file\n"
668 " -txt : Output results in Plain Text\n"
669 " -csv : Output results in a CSV format (suitable for benchmarks)\n"
670 " -junitxml : Output results as XML JUnit document\n"
671 " -xml : Output results as XML document\n"
672 " -lightxml : Output results as stream of XML tags\n"
673 " -teamcity : Output results in TeamCity format\n"
674 " -tap : Output results in Test Anything Protocol format\n"
676 " *** If no output file is specified, stdout is assumed.\n"
677 " *** If no output format is specified, -txt is assumed.\n"
679 " Test log detail options:\n"
680 " -silent : Log failures and fatal errors only\n"
681 " -v1 : Log the start of each testfunction\n"
682 " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n"
683 " -vs : Log every signal emission and resulting slot invocations\n"
685 " *** The -silent and -v1 options only affect plain text output.\n"
687 " Testing options:\n"
688 " -functions : Returns a list of current testfunctions\n"
689 " -datatags : Returns a list of current data tags.\n"
690 " A global data tag is preceded by ' __global__ '.\n"
691 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
692 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
693 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
694 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
695 " 0 means unlimited, default: 2000\n"
696 " -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
697 " -repeat n : Run the testsuite n times or until the test fails.\n"
698 " Useful for finding flaky tests. If negative, the tests are\n"
699 " repeated forever. This is intended as a developer tool, and\n"
700 " is only supported with the plain text logger.\n"
701 " -skipblacklisted : Skip blacklisted tests. Useful for measuring test coverage.\n"
702 " -trytimeout ms : Set default timeout for the QTRY_* macros and the qWaitFor()\n"
703 " functions to ms milliseconds.\n"
705 " Benchmarking options:\n"
706#if QT_CONFIG(valgrind)
707 " -callgrind : Use callgrind to time benchmarks\n"
709#ifdef QTESTLIB_USE_PERF_EVENTS
710 " -perf : Use Linux perf events to time benchmarks\n"
711 " -perfcounter name : Use the counter named 'name'\n"
712 " -perfcounterlist : Lists the counters available\n"
714#ifdef HAVE_TICK_COUNTER
715 " -tickcounter : Use CPU tick counters to time benchmarks\n"
717 " -eventcounter : Counts events received during benchmarks\n"
718 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
719 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
720 " -iterations n : Sets the number of accumulation iterations.\n"
721 " -median n : Sets the number of median iterations.\n"
722 " -vb : Print out verbose benchmarking information.\n";
724 for (
int i = 1; i < argc; ++i) {
725 if (strcmp(argv[i],
"-help") == 0 || strcmp(argv[i],
"--help") == 0
726 || strcmp(argv[i],
"/?") == 0) {
727 std::printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
728 " By default, all testfunctions will be run.\n\n"
729 "%s", argv[0], testOptions);
733 " QmlTest options:\n"
734 " -import dir : Specify an import directory.\n"
735 " -plugins dir : Specify a directory where to search for plugins.\n"
736 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
737 " -translation file : Specify the translation file.\n"
738 " -file-selector dir : Specify a file selector for the QML engine.\n");
742 " -help : This help\n");
744 }
else if (strcmp(argv[i],
"-functions") == 0) {
751 }
else if (strcmp(argv[i],
"-datatags") == 0) {
756 }
else if (strcmp(argv[i],
"-txt") == 0) {
757 logFormat = QTestLog::Plain;
758 }
else if (strcmp(argv[i],
"-csv") == 0) {
759 logFormat = QTestLog::CSV;
760 }
else if (strcmp(argv[i],
"-junitxml") == 0) {
761 logFormat = QTestLog::JUnitXML;
762 }
else if (strcmp(argv[i],
"-xunitxml") == 0) {
763 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
764 logFormat = QTestLog::JUnitXML;
765 }
else if (strcmp(argv[i],
"-xml") == 0) {
766 logFormat = QTestLog::XML;
767 }
else if (strcmp(argv[i],
"-lightxml") == 0) {
768 logFormat = QTestLog::LightXML;
769 }
else if (strcmp(argv[i],
"-teamcity") == 0) {
770 logFormat = QTestLog::TeamCity;
771 }
else if (strcmp(argv[i],
"-tap") == 0) {
772 logFormat = QTestLog::TAP;
773 }
else if (strcmp(argv[i],
"-silent") == 0) {
774 QTestLog::setVerboseLevel(-1);
775 }
else if (strcmp(argv[i],
"-v1") == 0) {
776 QTestLog::setVerboseLevel(1);
777 }
else if (strcmp(argv[i],
"-v2") == 0) {
778 QTestLog::setVerboseLevel(2);
779 }
else if (strcmp(argv[i],
"-vs") == 0) {
780 QSignalDumper::setEnabled(
true);
781 }
else if (strcmp(argv[i],
"-o") == 0) {
783 std::fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
788 char *filename =
new char[strlen(argv[i])+1];
789 char *format =
new char[strlen(argv[i])+1];
790 if (
std::sscanf(argv[i],
"%[^,],%s", filename, format) == 1) {
792 logFilename = argv[i];
795 if (strcmp(format,
"txt") == 0)
796 logFormat = QTestLog::Plain;
797 else if (strcmp(format,
"csv") == 0)
798 logFormat = QTestLog::CSV;
799 else if (strcmp(format,
"lightxml") == 0)
800 logFormat = QTestLog::LightXML;
801 else if (strcmp(format,
"xml") == 0)
802 logFormat = QTestLog::XML;
803 else if (strcmp(format,
"junitxml") == 0)
804 logFormat = QTestLog::JUnitXML;
805 else if (strcmp(format,
"xunitxml") == 0) {
806 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
807 logFormat = QTestLog::JUnitXML;
808 }
else if (strcmp(format,
"teamcity") == 0)
809 logFormat = QTestLog::TeamCity;
810 else if (strcmp(format,
"tap") == 0)
811 logFormat = QTestLog::TAP;
813 std::fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
816 if (strcmp(filename,
"-") == 0 && QTestLog::loggerUsingStdout()) {
817 std::fprintf(stderr,
"only one logger can log to stdout\n");
820 QTestLog::addLogger(QTestLog::LogMode(logFormat), filename);
824 }
else if (strcmp(argv[i],
"-eventdelay") == 0) {
826 std::fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
831 }
else if (strcmp(argv[i],
"-keydelay") == 0) {
833 std::fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
838 }
else if (strcmp(argv[i],
"-mousedelay") == 0) {
840 std::fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
845 }
else if (strcmp(argv[i],
"-maxwarnings") == 0) {
847 std::fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
850 QTestLog::setMaxWarnings(qToInt(argv[++i]));
852 }
else if (strcmp(argv[i],
"-repeat") == 0) {
854 std::fprintf(stderr,
"-repeat needs an extra parameter for the number of repetitions\n");
859 }
else if (strcmp(argv[i],
"-nocrashhandler") == 0) {
861 }
else if (strcmp(argv[i],
"-skipblacklisted") == 0) {
863 }
else if (strcmp(argv[i],
"-trytimeout") == 0) {
865 std::fprintf(stderr,
"-trytimeout needs an extra parameter to indicate the timeout(ms)\n");
868 QTest::defaultTryTimeout.store(std::chrono::milliseconds{qToInt(argv[++i])},
869 std::memory_order_relaxed);
871#if QT_CONFIG(valgrind)
872 }
else if (strcmp(argv[i],
"-callgrind") == 0) {
873 if (!QBenchmarkValgrindUtils::haveValgrind()) {
875 "WARNING: Valgrind not found or too old. "
876 "Make sure it is installed and in your path. "
877 "Using the walltime measurer.\n");
878 }
else if (QFileInfo(QDir::currentPath()).isWritable()) {
879 QBenchmarkGlobalData::current->setMode(
880 QBenchmarkGlobalData::CallgrindParentProcess);
883 "WARNING: Current directory not writable. "
884 "Using the walltime measurer.\n");
886 }
else if (strcmp(argv[i],
"-callgrindchild") == 0) {
887 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
888 QBenchmarkGlobalData::current->callgrindOutFileBase =
889 QBenchmarkValgrindUtils::outFileBase();
891#ifdef QTESTLIB_USE_PERF_EVENTS
892 }
else if (strcmp(argv[i],
"-perf") == 0) {
893 if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
895 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
897 std::fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
899 }
else if (strcmp(argv[i],
"-perfcounter") == 0) {
901 std::fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
904 QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
906 }
else if (strcmp(argv[i],
"-perfcounterlist") == 0) {
907 QBenchmarkPerfEventsMeasurer::listCounters();
910#ifdef HAVE_TICK_COUNTER
911 }
else if (strcmp(argv[i],
"-tickcounter") == 0) {
912 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
914 }
else if (strcmp(argv[i],
"-eventcounter") == 0) {
915 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
916 }
else if (strcmp(argv[i],
"-minimumvalue") == 0) {
918 std::fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
921 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
923 }
else if (strcmp(argv[i],
"-minimumtotal") == 0) {
925 std::fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
928 QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
930 }
else if (strcmp(argv[i],
"-iterations") == 0) {
932 std::fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
935 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
937 }
else if (strcmp(argv[i],
"-median") == 0) {
939 std::fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
942 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
945 }
else if (strcmp(argv[i],
"-vb") == 0) {
946 QBenchmarkGlobalData::current->verboseOutput =
true;
947#if defined(Q_OS_DARWIN)
948 }
else if (strncmp(argv[i],
"-Apple", 6) == 0) {
951# if defined(HAVE_XCTEST)
952 }
else if (
int skip = QXcodeTestLogger::parseCommandLineArgument(argv[i])) {
957 }
else if (argv[i][0] ==
'-') {
958 std::fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[i], testOptions);
960 std::fprintf(stderr,
"\nqmltest related options:\n"
961 " -import : Specify an import directory.\n"
962 " -plugins : Specify a directory where to search for plugins.\n"
963 " -input : Specify the root directory for test cases.\n");
966 std::fprintf(stderr,
"\n"
967 " -help : This help\n");
974 for (offset = 0; argv[i][offset]; ++offset) {
975 if (argv[i][offset] ==
':') {
976 if (argv[i][offset + 1] ==
':') {
987 QTest::testFunctions += QString::fromLatin1(argv[i]);
988 QTest::testTags += QString();
990 QTest::testFunctions += QString::fromLatin1(argv[i], colon);
991 QTest::testTags += QString::fromLatin1(argv[i] + colon + 1);
996 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
997 QTestLog::setInstalledTestCoverage(installedTestCoverage);
1001 const bool explicitLoggerRequested = logFormat != -1;
1002 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
1003 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
1005 bool addFallbackLogger = !explicitLoggerRequested;
1007#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
1009 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
1010 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1011 QTestLog::addLogger(QTestLog::Apple,
nullptr);
1012 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
1013 addFallbackLogger =
false;
1017 if (addFallbackLogger)
1018 QTestLog::addLogger(QTestLog::Plain, logFilename);
1020 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
1021 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
1028 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
1033 const int count = container.size();
1038 return container.front();
1040 QList<QList<QBenchmarkResult>> containerCopy = container;
1041 std::sort(containerCopy.begin(), containerCopy.end(),
1042 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
1043 return a.first() < b.first();
1046 const int middle = count / 2;
1049 return containerCopy.at(middle);
1056 QTestResult::setCurrentTestData(data);
1060 QTestResult::setCurrentTestData(
nullptr);
1064void TestMethods::invokeTestOnData(
int index)
const
1068 bool isBenchmark =
false;
1069 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1071 QList<QList<QBenchmarkResult>> resultsList;
1072 bool minimumTotalReached =
false;
1074 QBenchmarkTestMethodData::current->beginDataRun();
1076 QBenchmarkTestMethodData::current->iterationCount = 1;
1082 invokeTestMethodIfValid(m_initMethod);
1084 const bool initQuit =
1085 QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
1087 QBenchmarkTestMethodData::current->results.clear();
1088 QBenchmarkTestMethodData::current->resultAccepted =
false;
1089 QBenchmarkTestMethodData::current->valid =
false;
1091 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1092 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1094 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1096 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1098 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1104 QTestResult::finishedCurrentTestData();
1107 invokeTestMethodIfValid(m_cleanupMethod);
1111 if (QCoreApplication::instance())
1112 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1117 QTestResult::finishedCurrentTestDataCleanup();
1123 }
while (invokeOk && isBenchmark
1124 && QBenchmarkTestMethodData::current->resultsAccepted() ==
false
1125 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1127 QBenchmarkTestMethodData::current->endDataRun();
1128 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1130 resultsList.append(QBenchmarkTestMethodData::current->results);
1132 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1133 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1135 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1136 QString pattern = i < 0 ?
"warmup stage result : %1 std.dev: %2"_L1
1137 :
"accumulation stage result: %1 std.dev: %2"_L1;
1138 QTestLog::info(qPrintable(pattern.arg(first.measurement.value, 0,
'f', 3)
1139 .arg(sqrt(first.measurement.variance), 0,
'e', 2)),
1146 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1147 minimumTotalReached =
true;
1149 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1151 current += r.first().measurement.value;
1154 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1155 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1157 }
while (isBenchmark
1158 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1159 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1163 bool testPassed = !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed();
1164 QTestResult::finishedCurrentTestDataCleanup();
1166 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1167 QTestLog::addBenchmarkResults(qMedian(resultsList));
1171#if QT_CONFIG(thread)
1268 qFatal(
"Test function timed out");
1291template <
typename Functor>
1295 watchDog->beginTest();
1300 watchDog->testFinished();
1304 const QTestTable &lTable,
const QTestTable &gTable)
1306 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1307 const int localDataCount = lTable.dataCount();
1308 if (localDataCount) {
1309 std::fputs(
"Available test-specific data tags:\n", stderr);
1310 for (
int i = 0; i < localDataCount; ++i)
1311 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1313 const int globalDataCount = gTable.dataCount();
1314 if (globalDataCount) {
1315 std::fputs(
"Available global data tags:\n", stderr);
1316 for (
int i = 0; i < globalDataCount; ++i)
1317 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1319 if (localDataCount == 0 && globalDataCount == 0)
1320 std::fputs(
"Function has no data tags\n", stderr);
1324
1325
1326
1327
1328
1331 QBenchmarkTestMethodData benchmarkData;
1332 QBenchmarkTestMethodData::current = &benchmarkData;
1334 const QByteArray &name = m_methods[index].name();
1335 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1340 QTestResult::setCurrentTestFunction(name.constData());
1342 const QTestTable *gTable = QTestTable::globalTestTable();
1343 const int globalDataCount = gTable->dataCount();
1344 int curGlobalDataIndex = 0;
1345 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1346 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1349 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1350 QLatin1StringView global) {
1353 if (tag == local || tag == global)
1356 return tag.startsWith(global) && tag.endsWith(local) &&
1357 tag.size() == global.size() + 1 + local.size() &&
1358 tag[global.size()] ==
':';
1360 bool foundFunction =
false;
1361 bool blacklisted =
false;
1365 if (!gTable->isEmpty())
1366 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1368 if (curGlobalDataIndex == 0) {
1369 std::snprintf(member, 512,
"%s_data()", name.constData());
1370 runWithWatchdog(watchDog, [&member] {
1373 if (QTestResult::skipCurrentTest())
1377 int curDataIndex = 0;
1378 const int dataCount = table.dataCount();
1379 const auto dataTag = [&table, dataCount](
int index) {
1380 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1385 QTestResult::setSkipCurrentTest(
false);
1386 QTestResult::setBlacklistCurrentTest(
false);
1387 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1388 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1389 foundFunction =
true;
1390 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1391 globalDataTag(curGlobalDataIndex));
1393 QTestResult::setBlacklistCurrentTest(
true);
1396 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1398 QTestResult::finishedCurrentTestData();
1399 QTestResult::finishedCurrentTestDataCleanup();
1402 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1404 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1410 runWithWatchdog(watchDog, [
this, index] {
1411 invokeTestOnData(index);
1415 if (!tag.isEmpty() && !globalDataCount)
1419 }
while (curDataIndex < dataCount);
1421 QTestResult::setCurrentGlobalTestData(
nullptr);
1422 ++curGlobalDataIndex;
1423 }
while (curGlobalDataIndex < globalDataCount);
1425 if (!tag.isEmpty() && !foundFunction) {
1426 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1427 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1429 QTestResult::finishedCurrentTestFunction();
1430 QTestResult::setSkipCurrentTest(
false);
1431 QTestResult::setBlacklistCurrentTest(
false);
1434void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1436 QTEST_ASSERT(typeId);
1437 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1438 QTEST_ASSERT(data->parent());
1440 int idx = data->parent()->indexOf(tagName);
1442 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1443 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1447 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1448 qFatal(
"Requested type '%s' does not match available type '%s'.",
1449 QMetaType(typeId).name(),
1450 QMetaType(data->parent()->elementTypeId(idx)).name());
1453 return data->data(idx);
1457
1458
1459char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1462 va_start(ap, numArguments);
1464 QByteArray arguments;
1465 arguments += prefix;
1467 if (numArguments > 0) {
1468 arguments += va_arg(ap,
const char *);
1470 for (size_t i = 1; i < numArguments; ++i) {
1472 arguments += va_arg(ap,
const char *);
1477 arguments += suffix;
1478 return qstrdup(arguments.constData());
1482
1483
1484
1485
1486
1487
1488
1489
1490
1497
1498
1499
1500
1501
1502
1503 const qsizetype maxLen = 50;
1504 const qsizetype len = qMin(maxLen, length);
1505 char *result =
nullptr;
1507 if (length > maxLen) {
1508 const qsizetype size = len * 3 + 4;
1509 result =
new char[size];
1511 char *
const forElipsis = result + size - 5;
1512 forElipsis[0] =
' ';
1513 forElipsis[1] =
'.';
1514 forElipsis[2] =
'.';
1515 forElipsis[3] =
'.';
1516 result[size - 1] =
'\0';
1519 const qsizetype size = len * 3;
1520 result =
new char[size];
1521 result[size - 1] =
'\0';
1528 const char at = ba[i];
1530 result[o] = toHexUpper(at >> 4);
1532 result[o] = toHexUpper(at);
1546
1547
1548
1549
1552 bool trimmed =
false;
1553 auto buffer =
std::make_unique<
char[]>(256);
1554 const char *end = p + length;
1555 char *dst = buffer.get();
1557 bool lastWasHexEscape =
false;
1559 for ( ; p != end; ++p) {
1565 if (dst - buffer.get() > 246) {
1572 if (Q_UNLIKELY(lastWasHexEscape)) {
1573 if (fromHex(*p) != -1) {
1578 lastWasHexEscape =
false;
1581 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1612 *dst++ = toHexUpper(uchar(*p) >> 4);
1613 *dst++ = toHexUpper(uchar(*p));
1614 lastWasHexEscape =
true;
1626 return buffer.release();
1630
1631
1632
1633
1634
1635
1636
1645 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1646 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1675 *dst++ = toHexUpper(ch >> 12);
1676 *dst++ = toHexUpper(ch >> 8);
1677 *dst++ = toHexUpper(ch >> 4);
1678 *dst++ = toHexUpper(ch);
1686 auto p = string.utf16();
1687 auto length = string.size();
1689 bool trimmed =
false;
1690 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1691 const auto end = p + length;
1692 char *dst = buffer.get();
1695 for ( ; p != end; ++p) {
1696 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1700 dst = writePrettyUnicodeChar(*p, dst);
1710 return buffer.release();
1715 const QMetaObject *metaObject = testObject->metaObject();
1716 QTEST_ASSERT(metaObject);
1719 if (!CrashHandler::alreadyDebugging()
1720#if QT_CONFIG(valgrind)
1721 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1727 QTestResult::setCurrentTestFunction(
"initTestCase");
1728 runWithWatchdog(watchDog, [
this, testObject] {
1729 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1732 QSignalDumper::startDump();
1734 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1736 runWithWatchdog(watchDog, [
this, testObject] {
1737 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1741 const bool previousFailed = QTestResult::currentTestFailed();
1742 QTestResult::finishedCurrentTestData();
1743 QTestResult::finishedCurrentTestDataCleanup();
1744 QTestResult::finishedCurrentTestFunction();
1746 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1747 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1748 const char *data =
nullptr;
1749 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1750 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1751 invokeTest(i, QLatin1StringView(data), watchDog);
1756 const bool wasSkipped = QTestResult::skipCurrentTest();
1757 QTestResult::setSkipCurrentTest(
false);
1758 QTestResult::setBlacklistCurrentTest(
false);
1759 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1760 runWithWatchdog(watchDog, [
this, testObject] {
1761 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1764 QTestResult::finishedCurrentTestData();
1766 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1767 QTestResult::finishedCurrentTestDataCleanup();
1769 QTestResult::finishedCurrentTestFunction();
1770 QTestResult::setCurrentTestFunction(
nullptr);
1772 QSignalDumper::endDump();
1775#if QT_DEPRECATED_SINCE(6
, 8
)
1794 const char *(*lhsFormatter)(
const void*),
1795 const char *(*rhsFormatter)(
const void*),
1796 const char *lhsExpr,
const char *rhsExpr,
1797 ComparisonOperation op,
const char *file,
int line)
1799 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1800 lhsExpr, rhsExpr, op, file, line);
1806 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1810static QFile androidExitCodeFile()
1812 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1813 return QFile(testHome +
"/qtest_last_exit_code"_L1);
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1855int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1861 qInit(testObject, argc, argv);
1865#if defined(Q_OS_WASM)
1867 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1868 Module.notifyTestFinished($0);
1876
1877void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1880 CrashHandler::maybeDisableCoreDump();
1881 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1883#if defined(Q_OS_MACOS)
1885 QTestPrivate::disableWindowRestore();
1888 if (!appNapDisabler)
1889 appNapDisabler.emplace();
1891 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1892 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1893 &macPowerSavingDisabled);
1896 QTestPrivate::parseBlackList();
1897 QTestResult::reset();
1899 QTEST_ASSERT(testObject);
1900 QTEST_ASSERT(!currentTestObject);
1903 const QMetaObject *metaObject = testObject->metaObject();
1904 QTEST_ASSERT(metaObject);
1906 QTestResult::setCurrentTestObject(metaObject->className());
1908 QTestResult::setCurrentAppName(argv[0]);
1912#if QT_CONFIG(valgrind)
1913 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1915 QTestLog::startLogging();
1918 androidExitCodeFile().remove();
1923
1926 QTEST_ASSERT(currentTestObject);
1928#if QT_CONFIG(valgrind)
1929 int callgrindChildExitCode = 0;
1932#ifndef QT_NO_EXCEPTIONS
1936#if QT_CONFIG(valgrind)
1937 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1938 if (Q_UNLIKELY(!qApp))
1939 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1941 const QStringList origAppArgs(QCoreApplication::arguments());
1942 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1945 QBenchmarkValgrindUtils::cleanup();
1950 std::optional<CrashHandler::FatalSignalHandler> handler;
1951 CrashHandler::prepareStackTrace();
1955 TestMethods::MetaMethods commandLineMethods;
1956 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1957 std::vector<size_t> badFunctionIndices;
1959 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1960 const QByteArray tfB = tf.toLatin1();
1961 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1962 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1963 if (m.isValid() && isValidSlot(m)) {
1964 commandLineMethods.push_back(m);
1966 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1967 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1968 std::fputc(
'\n', stderr);
1969 QTestResult::setCurrentTestFunction(tfB.constData());
1970 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1971 QTestResult::finishedCurrentTestFunction();
1973 badFunctionIndices.insert(badFunctionIndices.begin(), index);
1977 if (badFunctionIndices.size() > 0) {
1979 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1980 QTestResult::currentAppName());
1981 if (commandLineMethods.empty())
1987 for (size_t i : std::as_const(badFunctionIndices)) {
1994 QTest::testFunctions.removeAt(i);
1995 QTest::testTags.removeAt(i);
2003 const int badArgCount = QTestLog::failCount();
2004 while (!(QTestLog::failCount() > badArgCount)
2005 && (repeatForever || remainingRepetitions-- > 0)) {
2006 QTestTable::globalTestTable();
2007 test.invokeTests(currentTestObject);
2008 QTestTable::clearGlobalTestTable();
2012#ifndef QT_NO_EXCEPTIONS
2014 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
2015 if (QTestResult::currentTestFunction()) {
2016 QTestResult::finishedCurrentTestFunction();
2017 QTestResult::setCurrentTestFunction(
nullptr);
2028#if QT_CONFIG(valgrind)
2029 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2030 return callgrindChildExitCode;
2034 const int exitCode = qMin(QTestLog::failCount(), 127);
2037 QFile exitCodeFile = androidExitCodeFile();
2038 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2039 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2041 qWarning(
"Failed to open %s for writing test exit code: %s",
2042 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2050
2055#if QT_CONFIG(valgrind)
2056 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2058 QTestLog::stopLogging();
2060 delete QBenchmarkGlobalData::current;
2061 QBenchmarkGlobalData::current =
nullptr;
2063#if defined(Q_OS_MACOS)
2064 IOPMAssertionRelease(macPowerSavingDisabled);
2065 appNapDisabler = std::nullopt;
2069#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2082 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2085QList<QString> QTest::qGetTestCaseNames()
2087 return QTest::TestRegistry::instance()->getAllTestNames();
2090QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2092 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2098
2099
2100
2101
2102
2103
2104int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2106 const int argc = arguments.size();
2107 QVarLengthArray<
char *> argv(argc);
2109 QList<QByteArray> args;
2112 for (
int i = 0; i < argc; ++i)
2114 args.append(arguments.at(i).toLocal8Bit().constData());
2115 argv[i] = args.last().data();
2118 return qExec(testObject, argc, argv.data());
2122
2123void QTest::
qFail(
const char *message,
const char *file,
int line)
2125 QTestResult::fail(message, file, line);
2129
2130bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2131 const char *file,
int line)
2133 return QTestResult::verify(statement, statementStr, description, file, line);
2137
2138
2139void QTest::
qSkip(
const char *message,
const char *file,
int line)
2141 QTestResult::addSkip(message, file, line);
2142 QTestResult::setSkipCurrentTest(
true);
2146
2147
2149 QTest::TestFailMode mode,
const char *file,
int line)
2151 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2172 auto message = [&] {
2173 const auto exType = what ?
"std::" :
"unknown ";
2174 const auto ofType = expected ?
" of type " :
"";
2175 const auto no = expected ?
"an" :
"no";
2176 const auto withMsg = what ?
" with message " :
"";
2177 const auto protect = [](
const char *s) {
return s ? s :
""; };
2179 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2180 "but caught %sexception%s%s",
2181 no, ofType, protect(expected),
2182 exType, withMsg, protect(what));
2184 qFail(message().toUtf8().constData(), file, line);
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2210 std::rethrow_exception(
std::current_exception());
2211 }
catch (
const std::exception &e) {
2212 qCaught(expected, e.what(), file, line);
2214 qCaught(expected,
nullptr, file, line);
2221#if QT_DEPRECATED_SINCE(6
, 3
)
2223
2224
2225
2226void QTest::qWarn(
const char *message,
const char *file,
int line)
2228 QTestLog::warn(message, file, line);
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2252 QTestLog::ignoreMessage(type, message);
2255#if QT_CONFIG(regularexpression)
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2273 QTestLog::ignoreMessage(type, messagePattern);
2278
2279
2281
2282
2283
2284
2287 return QTestLog::failOnWarning();
2291
2292
2294
2295
2296
2297
2300 return QTestLog::failOnWarning(message);
2303#if QT_CONFIG(regularexpression)
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2358 QTestLog::failOnWarning(messagePattern);
2363
2366static inline bool isWindowsBuildDirectory(
const QString &dirName)
2368 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2369 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2373#if QT_CONFIG(temporaryfile)
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2386 QSharedPointer<QTemporaryDir> result;
2388 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2390 tempDir->setAutoRemove(
true);
2392 if (!tempDir->isValid())
2395 const QString dataPath = tempDir->path();
2396 const QString resourcePath = u':' + dirName;
2397 const QFileInfo fileInfo(resourcePath);
2399 if (!fileInfo.isDir()) {
2400 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2404 bool isResourceDirEmpty =
true;
2405 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2406 isResourceDirEmpty =
false;
2407 if (!dirEntry.isDir()) {
2408 const QString &filePath = dirEntry.filePath();
2409 const QString destination =
2410 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2411 QFileInfo destinationFileInfo(destination);
2412 QDir().mkpath(destinationFileInfo.path());
2413 QFile file(filePath);
2414 if (!file.copy(destination, QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2415 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2416 qUtf16Printable(file.errorString()));
2422 if (isResourceDirEmpty) {
2423 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2427 result = std::move(tempDir);
2434
2436QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2437 const char *sourcedir)
2445 QDir binDirectory(QCoreApplication::applicationDirPath());
2446 if (binDirectory.exists(base)) {
2447 found = binDirectory.absoluteFilePath(base);
2452 else if (isWindowsBuildDirectory(binDirectory.dirName())
2453 && binDirectory.cdUp() && binDirectory.exists(base)) {
2454 found = binDirectory.absoluteFilePath(base);
2457 else if (QTestLog::verboseLevel() >= 2) {
2458 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2459 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2460 "checking next location"_L1.arg(base, candidate)),
2466 if (found.isEmpty()) {
2467 const char *testObjectName = QTestResult::currentTestObjectName();
2468 if (testObjectName) {
2469 const QStringList testsPaths = QLibraryInfo::paths(QLibraryInfo::TestsPath);
2470 for (
const QString &testsPath : testsPaths) {
2471 const QString candidate =
"%1/%2/%3"_L1
2472 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2473 if (QFileInfo::exists(candidate)) {
2475 }
else if (QTestLog::verboseLevel() >= 2) {
2476 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2477 "checking next location"_L1
2478 .arg(base, QDir::toNativeSeparators(candidate))),
2486 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2488 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2492 if (!srcdir.isAbsolute() && builddir)
2493 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2495 const QString canonicalPath = srcdir.canonicalFilePath();
2496 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2497 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2499 }
else if (QTestLog::verboseLevel() >= 2) {
2500 QTestLog::info(qPrintable(
2501 "testdata %1 not found relative to source path [%2]"_L1
2502 .arg(base, QDir::toNativeSeparators(candidate))),
2508 if (found.isEmpty()) {
2509 const QString candidate =
":/%1"_L1.arg(base);
2510 if (QFileInfo::exists(candidate)) {
2512 }
else if (QTestLog::verboseLevel() >= 2) {
2513 QTestLog::info(qPrintable(
2514 "testdata %1 not found in resources [%2]"_L1
2515 .arg(base, QDir::toNativeSeparators(candidate))),
2521 if (found.isEmpty()) {
2522 const QString candidate = QDir::currentPath() + u'/' + base;
2523 if (QFileInfo::exists(candidate)) {
2525 }
else if (QTestLog::verboseLevel() >= 2) {
2526 QTestLog::info(qPrintable(
2527 "testdata %1 not found in current directory [%2]"_L1
2528 .arg(base, QDir::toNativeSeparators(candidate))),
2534 if (found.isEmpty()) {
2535 const QString candidate = QTest::mainSourcePath % u'/' % base;
2536 if (QFileInfo::exists(candidate)) {
2538 }
else if (QTestLog::verboseLevel() >= 2) {
2539 QTestLog::info(qPrintable(
2540 "testdata %1 not found in main source directory [%2]"_L1
2541 .arg(base, QDir::toNativeSeparators(candidate))),
2547 if (found.isEmpty() && sourcedir) {
2548 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2549 if (QFileInfo::exists(candidate)) {
2551 }
else if (QTestLog::verboseLevel() >= 2) {
2552 QTestLog::info(qPrintable(
2553 "testdata %1 not found in supplied source directory [%2]"_L1
2554 .arg(base, QDir::toNativeSeparators(candidate))),
2560 if (found.isEmpty()) {
2561 QTestLog::warn(qPrintable(
2562 "testdata %1 could not be located!"_L1.arg(base)),
2564 }
else if (QTestLog::verboseLevel() >= 1) {
2565 QTestLog::info(qPrintable(
2566 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2574
2575QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2576 const char *sourcedir)
2578 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2582
2585 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2589
2592 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2596
2599 QTEST_ASSERT(tagName);
2600 QTestData *data = QTestResult::currentTestData();
2602 QTEST_ASSERT(data->parent());
2604 int idx = data->parent()->indexOf(tagName);
2605 QTEST_ASSERT(idx != -1);
2606 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2608 return data->data(data->parent()->indexOf(tagName));
2612
2615 QTestTable *tbl = QTestTable::currentTestTable();
2616 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2618 tbl->addColumn(id, name);
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641QTestData &
QTest::newRow(
const char *dataTag)
2643 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2644 QTestTable *tbl = QTestTable::currentTestTable();
2645 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2646 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2647 "Must add columns before attempting to add rows.");
2649 return *tbl->newData(dataTag);
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679QTestData &
QTest::addRow(
const char *format, ...)
2681 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2682 QTestTable *tbl = QTestTable::currentTestTable();
2683 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2684 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2685 "Must add columns before attempting to add rows.");
2690 va_start(va, format);
2693 std::vsnprintf(buf,
sizeof buf, format, va);
2696 return *tbl->newData(buf);
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2721
2722
2725 return QTestResult::currentAppName();
2729
2730
2731
2732
2733
2734
2737 return QTestResult::currentTestFunction();
2741
2742
2743
2746 return QTestResult::currentDataTag();
2750
2751
2752
2753
2754
2757 return QTestResult::currentGlobalDataTag();
2761
2762
2763
2764
2767 return QTestResult::currentTestFailed();
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2785 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2789
2790
2791
2792
2793
2794
2795
2802
2805 return currentTestObject;
2809
2812 QString mainSourceFile = QFile::decodeName(file);
2815 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2817 fi.setFile(mainSourceFile);
2821#if QT_DEPRECATED_SINCE(6
, 4
)
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840bool QTest::compare_helper(
bool success,
const char *failureMsg,
2841 char *actualVal,
char *expectedVal,
2842 const char *actual,
const char *expected,
2843 const char *file,
int line)
2845 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2846 actual, expected, file, line);
2850#if QT_DEPRECATED_SINCE(6
, 8
)
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864bool QTest::compare_helper(
bool success,
const char *failureMsg,
2865 qxp::function_ref<
const char *()> actualVal,
2866 qxp::function_ref<
const char *()> expectedVal,
2867 const char *actual,
const char *expected,
2868 const char *file,
int line)
2870 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2871 QTest::functionRefFormatter,
2872 QTest::functionRefFormatter, actual, expected,
2873 QTest::ComparisonOperation::CustomCompare,
2874 file, line, failureMsg);
2879
2880
2881
2882
2883
2884
2885
2886
2889 const void *actualPtr,
const void *expectedPtr,
2890 const char *(*actualFormatter)(
const void *),
2891 const char *(*expectedFormatter)(
const void *),
2892 const char *actual,
const char *expected,
2893 const char *file,
int line)
2895 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2896 actualFormatter, expectedFormatter,
2898 QTest::ComparisonOperation::CustomCompare,
2899 file, line, failureMsg);
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2931 const void *lhsPtr,
const void *rhsPtr,
2932 const char *(*lhsFormatter)(
const void*),
2933 const char *(*rhsFormatter)(
const void*),
2934 const char *lhsExpression,
const char *rhsExpression,
2935 const char *(*actualOrderFormatter)(
const void *),
2936 const char *(*expectedOrderFormatter)(
const void *),
2937 const void *actualOrderPtr,
const void *expectedOrderPtr,
2938 const char *expectedExpression,
2939 const char *file,
int line)
2941 return QTestResult::report3WayResult(success, failureMsg,
2943 lhsFormatter, rhsFormatter,
2944 lhsExpression, rhsExpression,
2945 actualOrderFormatter,
2946 expectedOrderFormatter,
2947 actualOrderPtr, expectedOrderPtr,
2953
2954
2955
2956
2957
2958
2959
2960
2961
2963 const char *expected,
const char *file,
int line)
2965 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2968template <
typename T>
2971 switch (qFpClassify(expected))
2974 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2976 return qFpClassify(actual) == FP_NAN;
2978 if (!qFuzzyIsNull(expected))
2979 return qFuzzyCompare(actual, expected);
2983 return qFuzzyIsNull(actual);
2988
2989
2990bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2991 const char *file,
int line)
2993 auto formatter = Internal::genericToString<qfloat16>;
2994 return compare_helper(floatingCompare(t1, t2),
2995 "Compared qfloat16s are not the same (fuzzy compare)",
2996 &t1, &t2, formatter, formatter,
2997 actual, expected, file, line);
3001
3002
3003bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
3004 const char *file,
int line)
3006 return QTestResult::compare(floatingCompare(t1, t2),
3007 "Compared floats are not the same (fuzzy compare)",
3008 t1, t2, actual, expected, file, line);
3012
3013
3014bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
3015 const char *file,
int line)
3017 return QTestResult::compare(floatingCompare(t1, t2),
3018 "Compared doubles are not the same (fuzzy compare)",
3019 t1, t2, actual, expected, file, line);
3023
3024
3025
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);
3034#if QT_POINTER_SIZE == 8
3036
3037
3038
3040bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3041 const char *file,
int line)
3043 return QTestResult::compare(t1 == t2,
3044 "Compared values are not the same",
3045 t1, t2, actual, expected, file, line);
3050
3051
3052
3053bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3054 const char *file,
int line)
3056 return QTestResult::compare(t1 == t2,
3057 "Compared values are not the same",
3058 t1, t2, actual, expected, file, line);
3062
3063
3064
3065bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3066 const char *file,
int line)
3068 return QTestResult::compare(t1 == t2,
3069 "Compared values are not the same",
3070 t1, t2, actual, expected, file, line);
3074
3075
3076
3077bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3078 const char *file,
int line)
3080 return QTestResult::compare(t1 == t2,
3081 "Compared values are not the same",
3082 t1, t2, actual, expected, file, line);
3086
3087
3088
3089bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3090 const char *file,
int line)
3092 return QTestResult::compare(t1 == t2,
3093 "Compared values are not the same",
3094 t1, t2, actual, expected, file, line);
3098
3099
3100
3103
3104
3105
3108
3109
3110
3113
3114
3117
3118
3120#define TO_STRING_IMPL(TYPE, FORMAT) template
3121 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3122{
3123 char *msg = new char[128
];
3124 std::snprintf(msg, 128
, #FORMAT, t);
3126}
3143 constexpr int Digits =
std::numeric_limits<T>::digits;
3144 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3145 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3146 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3152 Q_ASSERT(qIsNaN(t));
3153 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3154 r.payload = u & PayloadMask;
3155 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3165 char *msg =
new char[128];
3166 bool negative = signbit(t);
3168 switch (qFpClassify(t)) {
3170 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3173 if (
auto r = decodeNanPayload(t); r.payload) {
3174 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3175 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3177 Q_ASSERT(r.isQuiet);
3178 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3182 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3185 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3192#define TO_STRING_FLOAT(TYPE) template
3193 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3194{
3195 return toStringFp(t); \
3196}
3203 unsigned char c =
static_cast<
unsigned char>(t);
3204 char *msg =
new char[16];
3207 qstrcpy(msg,
"'\\0'");
3210 qstrcpy(msg,
"'\\a'");
3213 qstrcpy(msg,
"'\\b'");
3216 qstrcpy(msg,
"'\\t'");
3219 qstrcpy(msg,
"'\\n'");
3222 qstrcpy(msg,
"'\\v'");
3225 qstrcpy(msg,
"'\\f'");
3228 qstrcpy(msg,
"'\\r'");
3231 qstrcpy(msg,
"'\\\"'");
3234 qstrcpy(msg,
"'\\\''");
3237 qstrcpy(msg,
"'\\\\'");
3240 if (c < 0x20 || c >= 0x7F)
3241 std::snprintf(msg, 16,
"'\\x%02x'", c);
3243 std::snprintf(msg, 16,
"'%c'" , c);
3249
3253 char *msg =
new char[1];
3257 char *msg =
new char[strlen(str) + 1];
3258 return qstrcpy(msg, str);
3262
3265 char *msg =
new char[128];
3266 std::snprintf(msg, 128,
"%p", p);
3271
3275 return qstrdup(
"<null>");
3277 return QTest::toString(
const_cast<
const QObject*>(vo));
3281
3285 return qstrdup(
"<null>");
3287 const QString &name = o->objectName();
3288 const char *className = o->metaObject()->className();
3289 char *msg =
new char[256];
3291 std::snprintf(msg, 256,
"%s/%p", className, o);
3293 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3299
3300
3303
3304
3307
3308
3311
3312
3315
3316
3319
3320
3323
3325 const char *expected,
const char *file,
int line)
3327 auto formatter = Internal::genericToString<
const char *>;
3328 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3329 &t1, &t2, formatter, formatter,
3330 actual, expected, file, line);
3334
3335
3336
3339
3340
3343
3344
3347
3348
3351
3352
3355
3356
3359
3360
3363
3364
3367
3368
3371
3372
3375
3376
3379
3380
3383
3384
3387
3388
3391
3392
3395
3396
3399
3400
3403
3404
3407
3408
3411
3412
3415
3416
3419
3420
3423
3424
3427
3428
3431
3432
3435
3436
3439
3440
3443
3444
3447
3448
3451
3452
3455
3456
3459
3460
3463
3464
3467
3468
3471
3472
3475
3476
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)