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)
412 bool invokeTest(
int index, QLatin1StringView tag,
std::optional<
WatchDog> &watchDog)
const;
413 void invokeTestOnData(
int index)
const;
415 QMetaMethod m_initTestCaseMethod;
416 QMetaMethod m_initTestCaseDataMethod;
417 QMetaMethod m_cleanupTestCaseMethod;
418 QMetaMethod m_initMethod;
419 QMetaMethod m_cleanupMethod;
421 MetaMethods m_methods;
432 if (m_methods.empty()) {
433 const QMetaObject *metaObject = o->metaObject();
434 const int count = metaObject->methodCount();
435 m_methods.reserve(count);
436 for (
int i = 0; i < count; ++i) {
437 const QMetaMethod me = metaObject->method(i);
439 m_methods.push_back(me);
444QMetaMethod
TestMethods::findMethod(
const QObject *obj,
const char *signature)
446 const QMetaObject *metaObject = obj->metaObject();
447 const int funcIndex = metaObject->indexOfMethod(signature);
448 return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
469 try { ok = m.invoke(obj, Qt ::DirectConnection); }
470 catch (
const TestFailedException &) {}
471 catch (
const TestSkippedException &) {}
478 const QMetaObject *metaObject = obj->metaObject();
479 int funcIndex = metaObject->indexOfMethod(methodName);
481 invokeTestMethodIfValid(metaObject->method(funcIndex), obj);
487 const QByteArray env = qgetenv(
"QTEST_EVENT_DELAY");
537static bool qPrintTestSlots(FILE *stream,
const char *filter =
nullptr,
const char *preamble =
"")
539 const auto matches = [filter](
const QByteArray &s) {
540 return !filter || QLatin1StringView(s).contains(QLatin1StringView(filter),
541 Qt::CaseInsensitive);
543 bool matched =
false;
545 QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
546 if (isValidSlot(sl)) {
547 const QByteArray signature = sl.methodSignature();
548 if (matches(signature)) {
549 std::fprintf(stream,
"%s%s\n", preamble, signature.constData());
561 QTestLog::setPrintAvailableTagsMode();
564 QTestTable::globalTestTable();
566 const QTestTable *gTable = QTestTable::globalTestTable();
568 const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject();
571 for (
int i = 0; i < currTestMetaObj->methodCount(); ++i) {
572 QMetaMethod tf = currTestMetaObj->method(i);
574 if (isValidSlot(tf)) {
577 QStringList localTags;
579 const QByteArray slot = tf.methodSignature().chopped(2);
580 const QByteArray member = slot +
"_data()";
581 invokeTestMethodIfExists(member.constData());
582 const int dataCount = table.dataCount();
583 localTags.reserve(dataCount);
584 for (
int j = 0; j < dataCount; ++j)
585 localTags << QLatin1StringView(table.testData(j)->dataTag());
588 if (gTable->dataCount() == 0) {
589 if (localTags.size() == 0) {
591 std::fprintf(stream,
"%s %s\n", currTestMetaObj->className(), slot.data());
594 for (
int k = 0; k < localTags.size(); ++k)
595 std::fprintf(stream,
"%s %s %s\n",
596 currTestMetaObj->className(),
598 localTags.at(k).toLatin1().data());
601 for (
int j = 0; j < gTable->dataCount(); ++j) {
602 if (localTags.size() == 0) {
604 std::fprintf(stream,
"%s %s __global__ %s\n",
605 currTestMetaObj->className(),
607 gTable->testData(j)->dataTag());
611 for (
int k = 0; k < localTags.size(); ++k)
612 std::fprintf(stream,
"%s %s %s __global__ %s\n",
613 currTestMetaObj->className(),
615 localTags.at(k).toLatin1().data(),
616 gTable->testData(j)->dataTag());
627 int l =
static_cast<
int>(strtol(str, &pEnd, 10));
629 std::fprintf(stderr,
"Invalid numeric parameter: '%s'\n", str);
638 const char *logFilename =
nullptr;
642 QTest::testFunctions.clear();
643 QTest::testTags.clear();
645#if defined(Q_OS_DARWIN) && defined(HAVE_XCTEST)
646 if (QXcodeTestLogger::canLogTestProgress())
647 logFormat = QTestLog::XCTest;
650 const char *testOptions =
651 " New-style logging options:\n"
652 " -o filename,format : Output results to file in the specified format\n"
653 " Use - to output to stdout\n"
654 " Valid formats are:\n"
655 " txt : Plain text\n"
656 " csv : CSV format (suitable for benchmarks)\n"
657 " junitxml : XML JUnit document\n"
658 " xml : XML document\n"
659 " lightxml : A stream of XML tags\n"
660 " teamcity : TeamCity format\n"
661 " tap : Test Anything Protocol\n"
663 " *** Multiple loggers can be specified, but at most one can log to stdout.\n"
665 " Old-style logging options:\n"
666 " -o filename : Write the output into file\n"
667 " -txt : Output results in Plain Text\n"
668 " -csv : Output results in a CSV format (suitable for benchmarks)\n"
669 " -junitxml : Output results as XML JUnit document\n"
670 " -xml : Output results as XML document\n"
671 " -lightxml : Output results as stream of XML tags\n"
672 " -teamcity : Output results in TeamCity format\n"
673 " -tap : Output results in Test Anything Protocol format\n"
675 " *** If no output file is specified, stdout is assumed.\n"
676 " *** If no output format is specified, -txt is assumed.\n"
678 " Test log detail options:\n"
679 " -silent : Log failures and fatal errors only\n"
680 " -v1 : Log the start of each testfunction\n"
681 " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n"
682 " -vs : Log every signal emission and resulting slot invocations\n"
684 " *** The -silent and -v1 options only affect plain text output.\n"
686 " Testing options:\n"
687 " -functions : Returns a list of current testfunctions\n"
688 " -datatags : Returns a list of current data tags.\n"
689 " A global data tag is preceded by ' __global__ '.\n"
690 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
691 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
692 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
693 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
694 " 0 means unlimited, default: 2000\n"
695 " -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
696 " -repeat n : Run the testsuite n times or until the test fails.\n"
697 " Useful for finding flaky tests. If negative, the tests are\n"
698 " repeated forever. This is intended as a developer tool, and\n"
699 " is only supported with the plain text logger.\n"
700 " -skipblacklisted : Skip blacklisted tests. Useful for measuring test coverage.\n"
702 " Benchmarking options:\n"
703#if QT_CONFIG(valgrind)
704 " -callgrind : Use callgrind to time benchmarks\n"
706#ifdef QTESTLIB_USE_PERF_EVENTS
707 " -perf : Use Linux perf events to time benchmarks\n"
708 " -perfcounter name : Use the counter named 'name'\n"
709 " -perfcounterlist : Lists the counters available\n"
711#ifdef HAVE_TICK_COUNTER
712 " -tickcounter : Use CPU tick counters to time benchmarks\n"
714 " -eventcounter : Counts events received during benchmarks\n"
715 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
716 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
717 " -iterations n : Sets the number of accumulation iterations.\n"
718 " -median n : Sets the number of median iterations.\n"
719 " -vb : Print out verbose benchmarking information.\n";
721 for (
int i = 1; i < argc; ++i) {
722 if (strcmp(argv[i],
"-help") == 0 || strcmp(argv[i],
"--help") == 0
723 || strcmp(argv[i],
"/?") == 0) {
724 std::printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
725 " By default, all testfunctions will be run.\n\n"
726 "%s", argv[0], testOptions);
730 " QmlTest options:\n"
731 " -import dir : Specify an import directory.\n"
732 " -plugins dir : Specify a directory where to search for plugins.\n"
733 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
734 " -translation file : Specify the translation file.\n"
735 " -file-selector dir : Specify a file selector for the QML engine.\n");
739 " -help : This help\n");
741 }
else if (strcmp(argv[i],
"-functions") == 0) {
748 }
else if (strcmp(argv[i],
"-datatags") == 0) {
753 }
else if (strcmp(argv[i],
"-txt") == 0) {
754 logFormat = QTestLog::Plain;
755 }
else if (strcmp(argv[i],
"-csv") == 0) {
756 logFormat = QTestLog::CSV;
757 }
else if (strcmp(argv[i],
"-junitxml") == 0) {
758 logFormat = QTestLog::JUnitXML;
759 }
else if (strcmp(argv[i],
"-xunitxml") == 0) {
760 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
761 logFormat = QTestLog::JUnitXML;
762 }
else if (strcmp(argv[i],
"-xml") == 0) {
763 logFormat = QTestLog::XML;
764 }
else if (strcmp(argv[i],
"-lightxml") == 0) {
765 logFormat = QTestLog::LightXML;
766 }
else if (strcmp(argv[i],
"-teamcity") == 0) {
767 logFormat = QTestLog::TeamCity;
768 }
else if (strcmp(argv[i],
"-tap") == 0) {
769 logFormat = QTestLog::TAP;
770 }
else if (strcmp(argv[i],
"-silent") == 0) {
771 QTestLog::setVerboseLevel(-1);
772 }
else if (strcmp(argv[i],
"-v1") == 0) {
773 QTestLog::setVerboseLevel(1);
774 }
else if (strcmp(argv[i],
"-v2") == 0) {
775 QTestLog::setVerboseLevel(2);
776 }
else if (strcmp(argv[i],
"-vs") == 0) {
777 QSignalDumper::setEnabled(
true);
778 }
else if (strcmp(argv[i],
"-o") == 0) {
780 std::fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
785 char *filename =
new char[strlen(argv[i])+1];
786 char *format =
new char[strlen(argv[i])+1];
787 if (
std::sscanf(argv[i],
"%[^,],%s", filename, format) == 1) {
789 logFilename = argv[i];
792 if (strcmp(format,
"txt") == 0)
793 logFormat = QTestLog::Plain;
794 else if (strcmp(format,
"csv") == 0)
795 logFormat = QTestLog::CSV;
796 else if (strcmp(format,
"lightxml") == 0)
797 logFormat = QTestLog::LightXML;
798 else if (strcmp(format,
"xml") == 0)
799 logFormat = QTestLog::XML;
800 else if (strcmp(format,
"junitxml") == 0)
801 logFormat = QTestLog::JUnitXML;
802 else if (strcmp(format,
"xunitxml") == 0) {
803 std::fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
804 logFormat = QTestLog::JUnitXML;
805 }
else if (strcmp(format,
"teamcity") == 0)
806 logFormat = QTestLog::TeamCity;
807 else if (strcmp(format,
"tap") == 0)
808 logFormat = QTestLog::TAP;
810 std::fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
813 if (strcmp(filename,
"-") == 0 && QTestLog::loggerUsingStdout()) {
814 std::fprintf(stderr,
"only one logger can log to stdout\n");
817 QTestLog::addLogger(QTestLog::LogMode(logFormat), filename);
821 }
else if (strcmp(argv[i],
"-eventdelay") == 0) {
823 std::fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
828 }
else if (strcmp(argv[i],
"-keydelay") == 0) {
830 std::fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
835 }
else if (strcmp(argv[i],
"-mousedelay") == 0) {
837 std::fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
842 }
else if (strcmp(argv[i],
"-maxwarnings") == 0) {
844 std::fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
847 QTestLog::setMaxWarnings(qToInt(argv[++i]));
849 }
else if (strcmp(argv[i],
"-repeat") == 0) {
851 std::fprintf(stderr,
"-repeat needs an extra parameter for the number of repetitions\n");
856 }
else if (strcmp(argv[i],
"-nocrashhandler") == 0) {
858 }
else if (strcmp(argv[i],
"-skipblacklisted") == 0) {
860#if QT_CONFIG(valgrind)
861 }
else if (strcmp(argv[i],
"-callgrind") == 0) {
862 if (!QBenchmarkValgrindUtils::haveValgrind()) {
864 "WARNING: Valgrind not found or too old. "
865 "Make sure it is installed and in your path. "
866 "Using the walltime measurer.\n");
867 }
else if (QFileInfo(QDir::currentPath()).isWritable()) {
868 QBenchmarkGlobalData::current->setMode(
869 QBenchmarkGlobalData::CallgrindParentProcess);
872 "WARNING: Current directory not writable. "
873 "Using the walltime measurer.\n");
875 }
else if (strcmp(argv[i],
"-callgrindchild") == 0) {
876 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
877 QBenchmarkGlobalData::current->callgrindOutFileBase =
878 QBenchmarkValgrindUtils::outFileBase();
880#ifdef QTESTLIB_USE_PERF_EVENTS
881 }
else if (strcmp(argv[i],
"-perf") == 0) {
882 if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
884 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
886 std::fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
888 }
else if (strcmp(argv[i],
"-perfcounter") == 0) {
890 std::fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
893 QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
895 }
else if (strcmp(argv[i],
"-perfcounterlist") == 0) {
896 QBenchmarkPerfEventsMeasurer::listCounters();
899#ifdef HAVE_TICK_COUNTER
900 }
else if (strcmp(argv[i],
"-tickcounter") == 0) {
901 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
903 }
else if (strcmp(argv[i],
"-eventcounter") == 0) {
904 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
905 }
else if (strcmp(argv[i],
"-minimumvalue") == 0) {
907 std::fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
910 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
912 }
else if (strcmp(argv[i],
"-minimumtotal") == 0) {
914 std::fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
917 QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
919 }
else if (strcmp(argv[i],
"-iterations") == 0) {
921 std::fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
924 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
926 }
else if (strcmp(argv[i],
"-median") == 0) {
928 std::fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
931 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
934 }
else if (strcmp(argv[i],
"-vb") == 0) {
935 QBenchmarkGlobalData::current->verboseOutput =
true;
936#if defined(Q_OS_DARWIN)
937 }
else if (strncmp(argv[i],
"-Apple", 6) == 0) {
940# if defined(HAVE_XCTEST)
941 }
else if (
int skip = QXcodeTestLogger::parseCommandLineArgument(argv[i])) {
946 }
else if (argv[i][0] ==
'-') {
947 std::fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[i], testOptions);
949 std::fprintf(stderr,
"\nqmltest related options:\n"
950 " -import : Specify an import directory.\n"
951 " -plugins : Specify a directory where to search for plugins.\n"
952 " -input : Specify the root directory for test cases.\n");
955 std::fprintf(stderr,
"\n"
956 " -help : This help\n");
963 for (offset = 0; argv[i][offset]; ++offset) {
964 if (argv[i][offset] ==
':') {
965 if (argv[i][offset + 1] ==
':') {
976 QTest::testFunctions += QString::fromLatin1(argv[i]);
977 QTest::testTags += QString();
979 QTest::testFunctions +=
980 QString::fromLatin1(argv[i], colon);
982 QString::fromLatin1(argv[i] + colon + 1);
987 bool installedTestCoverage = installCoverageTool(QTestResult::currentAppName(), QTestResult::currentTestObjectName());
988 QTestLog::setInstalledTestCoverage(installedTestCoverage);
992 const bool explicitLoggerRequested = logFormat != -1;
993 if (!QTestLog::hasLoggers() && explicitLoggerRequested)
994 QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename);
996 bool addFallbackLogger = !explicitLoggerRequested;
998#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
1000 const bool safeToAddAppleLogger = !AppleUnifiedLogger::preventsStderrLogging() || !QTestLog::loggerUsingStdout();
1001 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1002 QTestLog::addLogger(QTestLog::Apple,
nullptr);
1003 if (AppleUnifiedLogger::preventsStderrLogging() && !logFilename)
1004 addFallbackLogger =
false;
1008 if (addFallbackLogger)
1009 QTestLog::addLogger(QTestLog::Plain, logFilename);
1011 if (repetitions != 1 && !QTestLog::isRepeatSupported()) {
1012 std::fprintf(stderr,
"-repeat is only supported with plain text logger\n");
1019 qtest_qParseArgs(argc,
const_cast<
const char *
const *>(argv), qml);
1024 const int count = container.size();
1029 return container.front();
1031 QList<QList<QBenchmarkResult>> containerCopy = container;
1032 std::sort(containerCopy.begin(), containerCopy.end(),
1033 [](
const QList<QBenchmarkResult> &a,
const QList<QBenchmarkResult> &b) {
1034 return a.first() < b.first();
1037 const int middle = count / 2;
1040 return containerCopy.at(middle);
1047 QTestResult::setCurrentTestData(data);
1051 QTestResult::setCurrentTestData(
nullptr);
1055void TestMethods::invokeTestOnData(
int index)
const
1059 bool isBenchmark =
false;
1060 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1062 QList<QList<QBenchmarkResult>> resultsList;
1063 bool minimumTotalReached =
false;
1065 QBenchmarkTestMethodData::current->beginDataRun();
1067 QBenchmarkTestMethodData::current->iterationCount = 1;
1073 invokeTestMethodIfValid(m_initMethod);
1075 const bool initQuit =
1076 QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
1078 QBenchmarkTestMethodData::current->results.clear();
1079 QBenchmarkTestMethodData::current->resultAccepted =
false;
1080 QBenchmarkTestMethodData::current->valid =
false;
1082 QBenchmarkGlobalData::current->context.tag = QLatin1StringView(
1083 QTestResult::currentDataTag() ? QTestResult::currentDataTag() :
"");
1085 invokeOk = invokeTestMethodIfValid(m_methods[index]);
1087 QTestResult::addFailure(
"Unable to execute slot", __FILE__, __LINE__);
1089 isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
1095 QTestResult::finishedCurrentTestData();
1098 invokeTestMethodIfValid(m_cleanupMethod);
1102 if (QCoreApplication::instance())
1103 QCoreApplication::sendPostedEvents(
nullptr, QEvent::DeferredDelete);
1108 QTestResult::finishedCurrentTestDataCleanup();
1114 }
while (invokeOk && isBenchmark
1115 && QBenchmarkTestMethodData::current->resultsAccepted() ==
false
1116 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1118 QBenchmarkTestMethodData::current->endDataRun();
1119 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1121 resultsList.append(QBenchmarkTestMethodData::current->results);
1123 if (isBenchmark && QBenchmarkGlobalData::current->verboseOutput &&
1124 !QBenchmarkTestMethodData::current->results.isEmpty()) {
1126 const QBenchmarkResult &first = QBenchmarkTestMethodData::current->results.constFirst();
1127 QString pattern = i < 0 ?
"warmup stage result : %1"_L1
1128 :
"accumulation stage result: %1"_L1;
1129 QTestLog::info(qPrintable(pattern.arg(first.measurement.value)),
nullptr, 0);
1135 if (QBenchmarkGlobalData::current->minimumTotal == -1) {
1136 minimumTotalReached =
true;
1138 auto addResult = [](qreal current,
const QList<QBenchmarkResult> &r) {
1140 current += r.first().measurement.value;
1143 const qreal total =
std::accumulate(resultsList.begin(), resultsList.end(), 0.0, addResult);
1144 minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
1146 }
while (isBenchmark
1147 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1148 && !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
1152 bool testPassed = !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed();
1153 QTestResult::finishedCurrentTestDataCleanup();
1155 if (testPassed && QBenchmarkTestMethodData::current->resultsAccepted())
1156 QTestLog::addBenchmarkResults(qMedian(resultsList));
1160#if QT_CONFIG(thread)
1257 qFatal(
"Test function timed out");
1280template <
typename Functor>
1284 watchDog->beginTest();
1289 watchDog->testFinished();
1293 const QTestTable &lTable,
const QTestTable &gTable)
1295 std::fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
1296 const int localDataCount = lTable.dataCount();
1297 if (localDataCount) {
1298 std::fputs(
"Available test-specific data tags:\n", stderr);
1299 for (
int i = 0; i < localDataCount; ++i)
1300 std::fprintf(stderr,
"\t%s\n", lTable.testData(i)->dataTag());
1302 const int globalDataCount = gTable.dataCount();
1303 if (globalDataCount) {
1304 std::fputs(
"Available global data tags:\n", stderr);
1305 for (
int i = 0; i < globalDataCount; ++i)
1306 std::fprintf(stderr,
"\t%s\n", gTable.testData(i)->dataTag());
1308 if (localDataCount == 0 && globalDataCount == 0)
1309 std::fputs(
"Function has no data tags\n", stderr);
1313
1314
1315
1316
1317
1318
1319
1320
1323 QBenchmarkTestMethodData benchmarkData;
1324 QBenchmarkTestMethodData::current = &benchmarkData;
1326 const QByteArray &name = m_methods[index].name();
1327 QBenchmarkGlobalData::current->context.slotName = QLatin1StringView(name) +
"()"_L1;
1332 QTestResult::setCurrentTestFunction(name.constData());
1334 const QTestTable *gTable = QTestTable::globalTestTable();
1335 const int globalDataCount = gTable->dataCount();
1336 int curGlobalDataIndex = 0;
1337 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1338 return globalDataCount ? gTable->testData(index)->dataTag() :
nullptr;
1341 const auto dataTagMatches = [](QLatin1StringView tag, QLatin1StringView local,
1342 QLatin1StringView global) {
1345 if (tag == local || tag == global)
1348 return tag.startsWith(global) && tag.endsWith(local) &&
1349 tag.size() == global.size() + 1 + local.size() &&
1350 tag[global.size()] ==
':';
1352 bool foundFunction =
false;
1353 bool blacklisted =
false;
1357 if (!gTable->isEmpty())
1358 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1360 if (curGlobalDataIndex == 0) {
1361 std::snprintf(member, 512,
"%s_data()", name.constData());
1362 runWithWatchdog(watchDog, [&member] {
1365 if (QTestResult::skipCurrentTest())
1369 int curDataIndex = 0;
1370 const int dataCount = table.dataCount();
1371 const auto dataTag = [&table, dataCount](
int index) {
1372 return dataCount ? table.testData(index)->dataTag() :
nullptr;
1377 QTestResult::setSkipCurrentTest(
false);
1378 QTestResult::setBlacklistCurrentTest(
false);
1379 if (dataTagMatches(tag, QLatin1StringView(dataTag(curDataIndex)),
1380 QLatin1StringView(globalDataTag(curGlobalDataIndex)))) {
1381 foundFunction =
true;
1382 blacklisted = QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
1383 globalDataTag(curGlobalDataIndex));
1385 QTestResult::setBlacklistCurrentTest(
true);
1388 QTest::qSkip(
"Skipping blacklisted test since -skipblacklisted option is set.",
1390 QTestResult::finishedCurrentTestData();
1391 QTestResult::finishedCurrentTestDataCleanup();
1394 curDataIndex >= dataCount ?
nullptr : table.testData(curDataIndex));
1396 QTestPrivate::qtestMouseButtons = Qt::NoButton;
1402 runWithWatchdog(watchDog, [
this, index] {
1403 invokeTestOnData(index);
1407 if (!tag.isEmpty() && !globalDataCount)
1411 }
while (curDataIndex < dataCount);
1413 QTestResult::setCurrentGlobalTestData(
nullptr);
1414 ++curGlobalDataIndex;
1415 }
while (curGlobalDataIndex < globalDataCount);
1417 if (!tag.isEmpty() && !foundFunction) {
1418 printUnknownDataTagError(QLatin1StringView(name), tag, table, *gTable);
1419 QTestResult::addFailure(qPrintable(
"Data tag not found: %1"_L1.arg(tag)));
1421 QTestResult::finishedCurrentTestFunction();
1422 QTestResult::setSkipCurrentTest(
false);
1423 QTestResult::setBlacklistCurrentTest(
false);
1428void *
fetchData(QTestData *data,
const char *tagName,
int typeId)
1430 QTEST_ASSERT(typeId);
1431 QTEST_ASSERT_X(data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1432 QTEST_ASSERT(data->parent());
1434 int idx = data->parent()->indexOf(tagName);
1436 if (Q_UNLIKELY(idx == -1 || idx >= data->dataCount())) {
1437 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1441 if (Q_UNLIKELY(typeId != data->parent()->elementTypeId(idx))) {
1442 qFatal(
"Requested type '%s' does not match available type '%s'.",
1443 QMetaType(typeId).name(),
1444 QMetaType(data->parent()->elementTypeId(idx)).name());
1447 return data->data(idx);
1451
1452
1453char *
formatString(
const char *prefix,
const char *suffix, size_t numArguments, ...)
1456 va_start(ap, numArguments);
1458 QByteArray arguments;
1459 arguments += prefix;
1461 if (numArguments > 0) {
1462 arguments += va_arg(ap,
const char *);
1464 for (size_t i = 1; i < numArguments; ++i) {
1466 arguments += va_arg(ap,
const char *);
1471 arguments += suffix;
1472 return qstrdup(arguments.constData());
1476
1477
1478
1479
1480
1481
1482
1483
1484
1491
1492
1493
1494
1495
1496
1497 const qsizetype maxLen = 50;
1498 const qsizetype len = qMin(maxLen, length);
1499 char *result =
nullptr;
1501 if (length > maxLen) {
1502 const qsizetype size = len * 3 + 4;
1503 result =
new char[size];
1505 char *
const forElipsis = result + size - 5;
1506 forElipsis[0] =
' ';
1507 forElipsis[1] =
'.';
1508 forElipsis[2] =
'.';
1509 forElipsis[3] =
'.';
1510 result[size - 1] =
'\0';
1513 const qsizetype size = len * 3;
1514 result =
new char[size];
1515 result[size - 1] =
'\0';
1522 const char at = ba[i];
1524 result[o] = toHexUpper(at >> 4);
1526 result[o] = toHexUpper(at);
1540
1541
1542
1543
1546 bool trimmed =
false;
1547 auto buffer =
std::make_unique<
char[]>(256);
1548 const char *end = p + length;
1549 char *dst = buffer.get();
1551 bool lastWasHexEscape =
false;
1553 for ( ; p != end; ++p) {
1559 if (dst - buffer.get() > 246) {
1566 if (Q_UNLIKELY(lastWasHexEscape)) {
1567 if (fromHex(*p) != -1) {
1572 lastWasHexEscape =
false;
1575 if (*p < 0x7f && *p >= 0x20 && *p !=
'\\' && *p !=
'"') {
1606 *dst++ = toHexUpper(uchar(*p) >> 4);
1607 *dst++ = toHexUpper(uchar(*p));
1608 lastWasHexEscape =
true;
1620 return buffer.release();
1624
1625
1626
1627
1628
1629
1630
1639 auto first = [&](
int n) { Q_ASSERT(dst - buffer == n);
return dst; };
1640 if (ch < 0x7f && ch >= 0x20 && ch !=
'\\' && ch !=
'"') {
1669 *dst++ = toHexUpper(ch >> 12);
1670 *dst++ = toHexUpper(ch >> 8);
1671 *dst++ = toHexUpper(ch >> 4);
1672 *dst++ = toHexUpper(ch);
1680 auto p = string.utf16();
1681 auto length = string.size();
1683 bool trimmed =
false;
1684 auto buffer =
std::make_unique<
char[]>(PrettyUnicodeMaxOutputSize);
1685 const auto end = p + length;
1686 char *dst = buffer.get();
1689 for ( ; p != end; ++p) {
1690 if (dst - buffer.get() > PrettyUnicodeMaxOutputSize - PrettyUnicodeMaxIncrement) {
1694 dst = writePrettyUnicodeChar(*p, dst);
1704 return buffer.release();
1709 const QMetaObject *metaObject = testObject->metaObject();
1710 QTEST_ASSERT(metaObject);
1713 if (!CrashHandler::alreadyDebugging()
1714#if QT_CONFIG(valgrind)
1715 && QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
1721 QTestResult::setCurrentTestFunction(
"initTestCase");
1722 runWithWatchdog(watchDog, [
this, testObject] {
1723 invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject);
1726 QSignalDumper::startDump();
1728 if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
1730 runWithWatchdog(watchDog, [
this, testObject] {
1731 invokeTestMethodIfValid(m_initTestCaseMethod, testObject);
1735 const bool previousFailed = QTestResult::currentTestFailed();
1736 QTestResult::finishedCurrentTestData();
1737 QTestResult::finishedCurrentTestDataCleanup();
1738 QTestResult::finishedCurrentTestFunction();
1740 if (!QTestResult::skipCurrentTest() && !previousFailed) {
1741 for (
int i = 0, count =
int(m_methods.size()); i < count; ++i) {
1742 const char *data =
nullptr;
1743 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
1744 data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
1745 const bool ok = invokeTest(i, QLatin1StringView(data), watchDog);
1752 const bool wasSkipped = QTestResult::skipCurrentTest();
1753 QTestResult::setSkipCurrentTest(
false);
1754 QTestResult::setBlacklistCurrentTest(
false);
1755 QTestResult::setCurrentTestFunction(
"cleanupTestCase");
1756 runWithWatchdog(watchDog, [
this, testObject] {
1757 invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject);
1760 QTestResult::finishedCurrentTestData();
1762 QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
1763 QTestResult::finishedCurrentTestDataCleanup();
1765 QTestResult::finishedCurrentTestFunction();
1766 QTestResult::setCurrentTestFunction(
nullptr);
1768 QSignalDumper::endDump();
1771#if QT_DEPRECATED_SINCE(6
, 8
)
1790 const char *(*lhsFormatter)(
const void*),
1791 const char *(*rhsFormatter)(
const void*),
1792 const char *lhsExpr,
const char *rhsExpr,
1793 ComparisonOperation op,
const char *file,
int line)
1795 return QTestResult::reportResult(success, lhs, rhs, lhsFormatter, rhsFormatter,
1796 lhsExpr, rhsExpr, op, file, line);
1802 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
1806static QFile androidExitCodeFile()
1808 const QString testHome = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1809 return QFile(testHome +
"/qtest_last_exit_code"_L1);
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1851int QTest::qExec(QObject *testObject,
int argc,
char **argv)
1857 qInit(testObject, argc, argv);
1861#if defined(Q_OS_WASM)
1863 if (
typeof Module !=
"undefined" &&
typeof Module.notifyTestFinished !=
"undefined")
1864 Module.notifyTestFinished($0);
1872
1873void QTest::qInit(QObject *testObject,
int argc,
char **argv)
1876 CrashHandler::maybeDisableCoreDump();
1877 QBenchmarkGlobalData::current =
new QBenchmarkGlobalData;
1879#if defined(Q_OS_MACOS)
1881 QTestPrivate::disableWindowRestore();
1884 QTestPrivate::AppNapDisabler appNapDisabler;
1886 if (qApp && (qstrcmp(qApp->metaObject()->className(),
"QApplication") == 0)) {
1887 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
1888 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
1889 &macPowerSavingDisabled);
1893 QTestPrivate::parseBlackList();
1894 QTestResult::reset();
1896 QTEST_ASSERT(testObject);
1897 QTEST_ASSERT(!currentTestObject);
1900 const QMetaObject *metaObject = testObject->metaObject();
1901 QTEST_ASSERT(metaObject);
1903 QTestResult::setCurrentTestObject(metaObject->className());
1905 QTestResult::setCurrentAppName(argv[0]);
1909#if QT_CONFIG(valgrind)
1910 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
1912 QTestLog::startLogging();
1915 androidExitCodeFile().remove();
1920
1923 QTEST_ASSERT(currentTestObject);
1925#if QT_CONFIG(valgrind)
1926 int callgrindChildExitCode = 0;
1929#ifndef QT_NO_EXCEPTIONS
1933#if QT_CONFIG(valgrind)
1934 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1935 if (Q_UNLIKELY(!qApp))
1936 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
1938 const QStringList origAppArgs(QCoreApplication::arguments());
1939 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1942 QBenchmarkValgrindUtils::cleanup();
1947 std::optional<CrashHandler::FatalSignalHandler> handler;
1948 CrashHandler::prepareStackTrace();
1952 bool seenBad =
false;
1953 TestMethods::MetaMethods commandLineMethods;
1954 commandLineMethods.reserve(
static_cast<size_t>(QTest::testFunctions.size()));
1955 for (
const QString &tf : std::as_const(QTest::testFunctions)) {
1956 const QByteArray tfB = tf.toLatin1();
1957 const QByteArray signature = tfB + QByteArrayLiteral(
"()");
1958 QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
1959 if (m.isValid() && isValidSlot(m)) {
1960 commandLineMethods.push_back(m);
1962 std::fprintf(stderr,
"Unknown test function: '%s'.", tfB.constData());
1963 if (!qPrintTestSlots(stderr, tfB.constData(),
" Possible matches:\n"))
1964 std::fputc(
'\n', stderr);
1965 QTestResult::setCurrentTestFunction(tfB.constData());
1966 QTestResult::addFailure(qPrintable(
"Function not found: %1"_L1.arg(tf)));
1967 QTestResult::finishedCurrentTestFunction();
1969 QTest::testTags.remove(commandLineMethods.size());
1975 std::fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
1976 QTestResult::currentAppName());
1977 if (commandLineMethods.empty())
1984 while (QTestLog::failCount() == 0 && (repeatForever || remainingRepetitions-- > 0)) {
1985 QTestTable::globalTestTable();
1986 test.invokeTests(currentTestObject);
1987 QTestTable::clearGlobalTestTable();
1991#ifndef QT_NO_EXCEPTIONS
1993 QTestResult::addFailure(
"Caught unhandled exception", __FILE__, __LINE__);
1994 if (QTestResult::currentTestFunction()) {
1995 QTestResult::finishedCurrentTestFunction();
1996 QTestResult::setCurrentTestFunction(
nullptr);
2007#if QT_CONFIG(valgrind)
2008 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
2009 return callgrindChildExitCode;
2013 const int exitCode = qMin(QTestLog::failCount(), 127);
2016 QFile exitCodeFile = androidExitCodeFile();
2017 if (exitCodeFile.open(QIODevice::WriteOnly)) {
2018 exitCodeFile.write(qPrintable(QString::number(exitCode)));
2020 qWarning(
"Failed to open %s for writing test exit code: %s",
2021 qPrintable(exitCodeFile.fileName()), qPrintable(exitCodeFile.errorString()));
2029
2034#if QT_CONFIG(valgrind)
2035 if (QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindParentProcess)
2037 QTestLog::stopLogging();
2039 delete QBenchmarkGlobalData::current;
2040 QBenchmarkGlobalData::current =
nullptr;
2042#if defined(Q_OS_MACOS)
2043 IOPMAssertionRelease(macPowerSavingDisabled);
2047#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058void QTest::qRegisterTestCase(
const QString &name, TestEntryFunction entryFunction)
2060 QTest::TestRegistry::instance()->registerTest(name, entryFunction);
2063QList<QString> QTest::qGetTestCaseNames()
2065 return QTest::TestRegistry::instance()->getAllTestNames();
2068QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString& name)
2070 return QTest::TestRegistry::instance()->getTestEntryFunction(name);
2076
2077
2078
2079
2080
2081
2082int QTest::qExec(QObject *testObject,
const QStringList &arguments)
2084 const int argc = arguments.size();
2085 QVarLengthArray<
char *> argv(argc);
2087 QList<QByteArray> args;
2090 for (
int i = 0; i < argc; ++i)
2092 args.append(arguments.at(i).toLocal8Bit().constData());
2093 argv[i] = args.last().data();
2096 return qExec(testObject, argc, argv.data());
2100
2101void QTest::
qFail(
const char *message,
const char *file,
int line)
2103 QTestResult::fail(message, file, line);
2107
2108bool QTest::
qVerify(
bool statement,
const char *statementStr,
const char *description,
2109 const char *file,
int line)
2111 return QTestResult::verify(statement, statementStr, description, file, line);
2115
2116
2117void QTest::
qSkip(
const char *message,
const char *file,
int line)
2119 QTestResult::addSkip(message, file, line);
2120 QTestResult::setSkipCurrentTest(
true);
2124
2125
2127 QTest::TestFailMode mode,
const char *file,
int line)
2129 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148void QTest::
qCaught(
const char *expected,
const char *what,
const char *file,
int line)
2150 auto message = [&] {
2151 const auto exType = what ?
"std::" :
"unknown ";
2152 const auto ofType = expected ?
" of type " :
"";
2153 const auto no = expected ?
"an" :
"no";
2154 const auto withMsg = what ?
" with message " :
"";
2155 const auto protect = [](
const char *s) {
return s ? s :
""; };
2157 return QString::asprintf(
"Expected %s exception%s%s to be thrown, "
2158 "but caught %sexception%s%s",
2159 no, ofType, protect(expected),
2160 exType, withMsg, protect(what));
2162 qFail(message().toUtf8().constData(), file, line);
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2188 std::rethrow_exception(
std::current_exception());
2189 }
catch (
const std::exception &e) {
2190 qCaught(expected, e.what(), file, line);
2192 qCaught(expected,
nullptr, file, line);
2199#if QT_DEPRECATED_SINCE(6
, 3
)
2201
2202
2203
2204void QTest::qWarn(
const char *message,
const char *file,
int line)
2206 QTestLog::warn(message, file, line);
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2230 QTestLog::ignoreMessage(type, message);
2233#if QT_CONFIG(regularexpression)
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249void QTest::ignoreMessage(QtMsgType type,
const QRegularExpression &messagePattern)
2251 QTestLog::ignoreMessage(type, messagePattern);
2256
2257
2259
2260
2261
2262
2265 return QTestLog::failOnWarning();
2269
2270
2272
2273
2274
2275
2278 return QTestLog::failOnWarning(message);
2281#if QT_CONFIG(regularexpression)
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
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
2334void QTest::failOnWarning(
const QRegularExpression &messagePattern)
2336 QTestLog::failOnWarning(messagePattern);
2341
2344static inline bool isWindowsBuildDirectory(
const QString &dirName)
2346 return dirName.compare(
"Debug"_L1, Qt::CaseInsensitive) == 0
2347 || dirName.compare(
"Release"_L1, Qt::CaseInsensitive) == 0;
2351#if QT_CONFIG(temporaryfile)
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362QSharedPointer<QTemporaryDir> QTest::qExtractTestData(
const QString &dirName)
2364 QSharedPointer<QTemporaryDir> result;
2366 QSharedPointer<QTemporaryDir> tempDir = QSharedPointer<QTemporaryDir>::create();
2368 tempDir->setAutoRemove(
true);
2370 if (!tempDir->isValid())
2373 const QString dataPath = tempDir->path();
2374 const QString resourcePath = u':' + dirName;
2375 const QFileInfo fileInfo(resourcePath);
2377 if (!fileInfo.isDir()) {
2378 qWarning(
"Resource path '%s' is not a directory.", qPrintable(resourcePath));
2382 bool isResourceDirEmpty =
true;
2383 for (
const auto &dirEntry : QDirListing(resourcePath, QDirListing::IteratorFlag::Recursive)) {
2384 isResourceDirEmpty =
false;
2385 if (!dirEntry.isDir()) {
2386 const QString &filePath = dirEntry.filePath();
2387 const QString destination =
2388 dataPath + u'/' + QStringView{filePath}.sliced(resourcePath.size());
2389 QFileInfo destinationFileInfo(destination);
2390 QDir().mkpath(destinationFileInfo.path());
2391 QFile file(filePath);
2392 if (!file.copy(destination)) {
2393 qWarning(
"Failed to copy '%ls': %ls.", qUtf16Printable(filePath),
2394 qUtf16Printable(file.errorString()));
2398 file.setFileName(destination);
2399 if (!file.setPermissions(QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup)) {
2400 qWarning(
"Failed to set permissions on '%ls': %ls.", qUtf16Printable(destination),
2401 qUtf16Printable(file.errorString()));
2407 if (isResourceDirEmpty) {
2408 qWarning(
"Resource directory '%s' is empty.", qPrintable(resourcePath));
2412 result = std::move(tempDir);
2419
2421QString
QTest::qFindTestData(
const QString& base,
const char *file,
int line,
const char *builddir,
2422 const char *sourcedir)
2430 QDir binDirectory(QCoreApplication::applicationDirPath());
2431 if (binDirectory.exists(base)) {
2432 found = binDirectory.absoluteFilePath(base);
2437 else if (isWindowsBuildDirectory(binDirectory.dirName())
2438 && binDirectory.cdUp() && binDirectory.exists(base)) {
2439 found = binDirectory.absoluteFilePath(base);
2442 else if (QTestLog::verboseLevel() >= 2) {
2443 const QString candidate = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + u'/' + base);
2444 QTestLog::info(qPrintable(
"testdata %1 not found relative to test binary [%2]; "
2445 "checking next location"_L1.arg(base, candidate)),
2451 if (found.isEmpty()) {
2452 const char *testObjectName = QTestResult::currentTestObjectName();
2453 if (testObjectName) {
2454 const QString testsPath = QLibraryInfo::path(QLibraryInfo::TestsPath);
2455 const QString candidate =
"%1/%2/%3"_L1
2456 .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
2457 if (QFileInfo::exists(candidate)) {
2459 }
else if (QTestLog::verboseLevel() >= 2) {
2460 QTestLog::info(qPrintable(
"testdata %1 not found in tests install path [%2]; "
2461 "checking next location"_L1
2462 .arg(base, QDir::toNativeSeparators(candidate))),
2469 if (found.isEmpty() && qstrncmp(file,
":/", 2) != 0) {
2471 QFileInfo srcdir(QFileInfo(QFile::decodeName(file)).path());
2475 if (!srcdir.isAbsolute() && builddir)
2476 srcdir.setFile(QFile::decodeName(builddir) + u'/' + srcdir.filePath());
2478 const QString canonicalPath = srcdir.canonicalFilePath();
2479 const QString candidate =
"%1/%2"_L1.arg(canonicalPath, base);
2480 if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
2482 }
else if (QTestLog::verboseLevel() >= 2) {
2483 QTestLog::info(qPrintable(
2484 "testdata %1 not found relative to source path [%2]"_L1
2485 .arg(base, QDir::toNativeSeparators(candidate))),
2491 if (found.isEmpty()) {
2492 const QString candidate =
":/%1"_L1.arg(base);
2493 if (QFileInfo::exists(candidate)) {
2495 }
else if (QTestLog::verboseLevel() >= 2) {
2496 QTestLog::info(qPrintable(
2497 "testdata %1 not found in resources [%2]"_L1
2498 .arg(base, QDir::toNativeSeparators(candidate))),
2504 if (found.isEmpty()) {
2505 const QString candidate = QDir::currentPath() + u'/' + base;
2506 if (QFileInfo::exists(candidate)) {
2508 }
else if (QTestLog::verboseLevel() >= 2) {
2509 QTestLog::info(qPrintable(
2510 "testdata %1 not found in current directory [%2]"_L1
2511 .arg(base, QDir::toNativeSeparators(candidate))),
2517 if (found.isEmpty()) {
2518 const QString candidate = QTest::mainSourcePath % u'/' % base;
2519 if (QFileInfo::exists(candidate)) {
2521 }
else if (QTestLog::verboseLevel() >= 2) {
2522 QTestLog::info(qPrintable(
2523 "testdata %1 not found in main source directory [%2]"_L1
2524 .arg(base, QDir::toNativeSeparators(candidate))),
2530 if (found.isEmpty() && sourcedir) {
2531 const QString candidate = QFile::decodeName(sourcedir) % u'/' % base;
2532 if (QFileInfo::exists(candidate)) {
2534 }
else if (QTestLog::verboseLevel() >= 2) {
2535 QTestLog::info(qPrintable(
2536 "testdata %1 not found in supplied source directory [%2]"_L1
2537 .arg(base, QDir::toNativeSeparators(candidate))),
2543 if (found.isEmpty()) {
2544 QTestLog::warn(qPrintable(
2545 "testdata %1 could not be located!"_L1.arg(base)),
2547 }
else if (QTestLog::verboseLevel() >= 1) {
2548 QTestLog::info(qPrintable(
2549 "testdata %1 was located at %2"_L1.arg(base, QDir::toNativeSeparators(found))),
2557
2558QString
QTest::qFindTestData(
const char *base,
const char *file,
int line,
const char *builddir,
2559 const char *sourcedir)
2561 return qFindTestData(QFile::decodeName(base), file, line, builddir, sourcedir);
2565
2568 return fetchData(QTestResult::currentTestData(), tagName, typeId);
2572
2575 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
2579
2582 QTEST_ASSERT(tagName);
2583 QTestData *data = QTestResult::currentTestData();
2585 QTEST_ASSERT(data->parent());
2587 int idx = data->parent()->indexOf(tagName);
2588 QTEST_ASSERT(idx != -1);
2589 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
2591 return data->data(data->parent()->indexOf(tagName));
2595
2598 QTestTable *tbl = QTestTable::currentTestTable();
2599 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2601 tbl->addColumn(id, name);
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624QTestData &
QTest::newRow(
const char *dataTag)
2626 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2627 QTestTable *tbl = QTestTable::currentTestTable();
2628 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2629 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::newRow()",
2630 "Must add columns before attempting to add rows.");
2632 return *tbl->newData(dataTag);
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662QTestData &
QTest::addRow(
const char *format, ...)
2664 QTEST_ASSERT_X(format,
"QTest::addRow()",
"Format string cannot be null");
2665 QTestTable *tbl = QTestTable::currentTestTable();
2666 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2667 QTEST_ASSERT_X(tbl->elementCount(),
"QTest::addRow()",
2668 "Must add columns before attempting to add rows.");
2673 va_start(va, format);
2676 std::vsnprintf(buf,
sizeof buf, format, va);
2679 return *tbl->newData(buf);
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2704
2705
2708 return QTestResult::currentAppName();
2712
2713
2714
2715
2716
2717
2720 return QTestResult::currentTestFunction();
2724
2725
2726
2729 return QTestResult::currentDataTag();
2733
2734
2735
2736
2737
2740 return QTestResult::currentGlobalDataTag();
2744
2745
2746
2747
2750 return QTestResult::currentTestFailed();
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2768 return QTestResult::currentTestFailed() || QTestResult::skipCurrentTest();
2772
2773
2774
2775
2776
2777
2778
2785
2788 return currentTestObject;
2792
2795 QString mainSourceFile = QFile::decodeName(file);
2798 fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
2800 fi.setFile(mainSourceFile);
2804#if QT_DEPRECATED_SINCE(6
, 4
)
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823bool QTest::compare_helper(
bool success,
const char *failureMsg,
2824 char *actualVal,
char *expectedVal,
2825 const char *actual,
const char *expected,
2826 const char *file,
int line)
2828 return QTestResult::compare(success, failureMsg, actualVal, expectedVal,
2829 actual, expected, file, line);
2833#if QT_DEPRECATED_SINCE(6
, 8
)
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847bool QTest::compare_helper(
bool success,
const char *failureMsg,
2848 qxp::function_ref<
const char *()> actualVal,
2849 qxp::function_ref<
const char *()> expectedVal,
2850 const char *actual,
const char *expected,
2851 const char *file,
int line)
2853 return QTestResult::reportResult(success, &actualVal, &expectedVal,
2854 QTest::functionRefFormatter,
2855 QTest::functionRefFormatter, actual, expected,
2856 QTest::ComparisonOperation::CustomCompare,
2857 file, line, failureMsg);
2862
2863
2864
2865
2866
2867
2868
2869
2872 const void *actualPtr,
const void *expectedPtr,
2873 const char *(*actualFormatter)(
const void *),
2874 const char *(*expectedFormatter)(
const void *),
2875 const char *actual,
const char *expected,
2876 const char *file,
int line)
2878 return QTestResult::reportResult(success, actualPtr, expectedPtr,
2879 actualFormatter, expectedFormatter,
2881 QTest::ComparisonOperation::CustomCompare,
2882 file, line, failureMsg);
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2914 const void *lhsPtr,
const void *rhsPtr,
2915 const char *(*lhsFormatter)(
const void*),
2916 const char *(*rhsFormatter)(
const void*),
2917 const char *lhsExpression,
const char *rhsExpression,
2918 const char *(*actualOrderFormatter)(
const void *),
2919 const char *(*expectedOrderFormatter)(
const void *),
2920 const void *actualOrderPtr,
const void *expectedOrderPtr,
2921 const char *expectedExpression,
2922 const char *file,
int line)
2924 return QTestResult::report3WayResult(success, failureMsg,
2926 lhsFormatter, rhsFormatter,
2927 lhsExpression, rhsExpression,
2928 actualOrderFormatter,
2929 expectedOrderFormatter,
2930 actualOrderPtr, expectedOrderPtr,
2936
2937
2938
2939
2940
2941
2942
2943
2944
2946 const char *expected,
const char *file,
int line)
2948 return QTestResult::compare(success, failureMsg, actual, expected, file, line);
2951template <
typename T>
2954 switch (qFpClassify(expected))
2957 return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
2959 return qFpClassify(actual) == FP_NAN;
2961 if (!qFuzzyIsNull(expected))
2962 return qFuzzyCompare(actual, expected);
2966 return qFuzzyIsNull(actual);
2971
2972
2973bool QTest::
qCompare(qfloat16
const &t1, qfloat16
const &t2,
const char *actual,
const char *expected,
2974 const char *file,
int line)
2976 auto formatter = Internal::genericToString<qfloat16>;
2977 return compare_helper(floatingCompare(t1, t2),
2978 "Compared qfloat16s are not the same (fuzzy compare)",
2979 &t1, &t2, formatter, formatter,
2980 actual, expected, file, line);
2984
2985
2986bool QTest::
qCompare(
float const &t1,
float const &t2,
const char *actual,
const char *expected,
2987 const char *file,
int line)
2989 return QTestResult::compare(floatingCompare(t1, t2),
2990 "Compared floats are not the same (fuzzy compare)",
2991 t1, t2, actual, expected, file, line);
2995
2996
2997bool QTest::
qCompare(
double const &t1,
double const &t2,
const char *actual,
const char *expected,
2998 const char *file,
int line)
3000 return QTestResult::compare(floatingCompare(t1, t2),
3001 "Compared doubles are not the same (fuzzy compare)",
3002 t1, t2, actual, expected, file, line);
3006
3007
3008
3010 const char *file,
int line)
3012 return QTestResult::compare(t1 == t2,
3013 "Compared values are not the same",
3014 t1, t2, actual, expected, file, line);
3017#if QT_POINTER_SIZE == 8
3019
3020
3021
3023bool QTest::qCompare(qsizetype t1, qsizetype t2,
const char *actual,
const char *expected,
3024 const char *file,
int line)
3026 return QTestResult::compare(t1 == t2,
3027 "Compared values are not the same",
3028 t1, t2, actual, expected, file, line);
3033
3034
3035
3036bool QTest::
qCompare(
unsigned t1,
unsigned t2,
const char *actual,
const char *expected,
3037 const char *file,
int line)
3039 return QTestResult::compare(t1 == t2,
3040 "Compared values are not the same",
3041 t1, t2, actual, expected, file, line);
3045
3046
3047
3048bool QTest::
qCompare(QStringView t1, QStringView t2,
const char *actual,
const char *expected,
3049 const char *file,
int line)
3051 return QTestResult::compare(t1 == t2,
3052 "Compared values are not the same",
3053 t1, t2, actual, expected, file, line);
3057
3058
3059
3060bool QTest::
qCompare(QStringView t1,
const QLatin1StringView &t2,
const char *actual,
const char *expected,
3061 const char *file,
int line)
3063 return QTestResult::compare(t1 == t2,
3064 "Compared values are not the same",
3065 t1, t2, actual, expected, file, line);
3069
3070
3071
3072bool QTest::
qCompare(
const QLatin1StringView &t1, QStringView t2,
const char *actual,
const char *expected,
3073 const char *file,
int line)
3075 return QTestResult::compare(t1 == t2,
3076 "Compared values are not the same",
3077 t1, t2, actual, expected, file, line);
3081
3082
3083
3086
3087
3088
3091
3092
3093
3096
3097
3100
3101
3103#define TO_STRING_IMPL(TYPE, FORMAT) template
3104 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3105{
3106 char *msg = new char[128
];
3107 std::snprintf(msg, 128
, #FORMAT, t);
3109}
3126 constexpr int Digits =
std::numeric_limits<T>::digits;
3127 constexpr quint64 MantissaMask = (Q_UINT64_C(1) << (Digits - 1)) - 1;
3128 constexpr quint64 IsQuietBit = quint64(QT_CONFIG(signaling_nan)) << (Digits - 2);
3129 constexpr quint64 PayloadMask = MantissaMask & ~IsQuietBit;
3135 Q_ASSERT(qIsNaN(t));
3136 quint64 u = qFromUnaligned<
typename QIntegerForSizeof<T>::Unsigned>(&t);
3137 r.payload = u & PayloadMask;
3138 r.isQuiet = !QT_CONFIG(signaling_nan) || (u & IsQuietBit);
3142static bool signbit(qfloat16 f) {
return f.signBit(); }
3150 char *msg =
new char[128];
3151 bool negative = signbit(t);
3153 switch (qFpClassify(t)) {
3155 qstrncpy(msg, (negative ?
"-inf" :
"inf"), 128);
3158 if (
auto r = decodeNanPayload(t); r.payload) {
3159 std::snprintf(msg, 128,
"%s%snan(%#llx)",
3160 negative ?
"-" :
"", r.isQuiet ?
"" :
"s", r.payload);
3162 Q_ASSERT(r.isQuiet);
3163 qstrncpy(msg, (negative ?
"-nan" :
"nan"), 128);
3167 qstrncpy(msg, (negative ?
"-0 (-0x0p+0)" :
"0 (0x0p+0)"), 128);
3170 std::snprintf(msg, 128,
"%.*g (%a)",
std::numeric_limits<T>::digits10 + 1,
double(t),
3177#define TO_STRING_FLOAT(TYPE) template
3178 <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3179{
3180 return toStringFp(t); \
3181}
3188 unsigned char c =
static_cast<
unsigned char>(t);
3189 char *msg =
new char[16];
3192 qstrcpy(msg,
"'\\0'");
3195 qstrcpy(msg,
"'\\a'");
3198 qstrcpy(msg,
"'\\b'");
3201 qstrcpy(msg,
"'\\t'");
3204 qstrcpy(msg,
"'\\n'");
3207 qstrcpy(msg,
"'\\v'");
3210 qstrcpy(msg,
"'\\f'");
3213 qstrcpy(msg,
"'\\r'");
3216 qstrcpy(msg,
"'\\\"'");
3219 qstrcpy(msg,
"'\\\''");
3222 qstrcpy(msg,
"'\\\\'");
3225 if (c < 0x20 || c >= 0x7F)
3226 std::snprintf(msg, 16,
"'\\x%02x'", c);
3228 std::snprintf(msg, 16,
"'%c'" , c);
3234
3238 char *msg =
new char[1];
3242 char *msg =
new char[strlen(str) + 1];
3243 return qstrcpy(msg, str);
3247
3250 char *msg =
new char[128];
3251 std::snprintf(msg, 128,
"%p", p);
3256
3260 return qstrdup(
"<null>");
3262 return QTest::toString(
const_cast<
const QObject*>(vo));
3266
3270 return qstrdup(
"<null>");
3272 const QString &name = o->objectName();
3273 const char *className = o->metaObject()->className();
3274 char *msg =
new char[256];
3276 std::snprintf(msg, 256,
"%s/%p", className, o);
3278 std::snprintf(msg, 256,
"%s/\"%s\"", className, qPrintable(name));
3284
3285
3288
3289
3292
3293
3296
3297
3300
3301
3304
3305
3308
3310 const char *expected,
const char *file,
int line)
3312 auto formatter = Internal::genericToString<
const char *>;
3313 return compare_helper(qstrcmp(t1, t2) == 0,
"Compared strings are not the same",
3314 &t1, &t2, formatter, formatter,
3315 actual, expected, file, line);
3319
3320
3321
3324
3325
3328
3329
3332
3333
3336
3337
3340
3341
3344
3345
3348
3349
3352
3353
3356
3357
3360
3361
3364
3365
3368
3369
3372
3373
3376
3377
3380
3381
3384
3385
3388
3389
3392
3393
3396
3397
3400
3401
3404
3405
3408
3409
3412
3413
3416
3417
3420
3421
3424
3425
3428
3429
3432
3433
3436
3437
3440
3441
3444
3445
3448
3449
3452
3453
3456
3457
3460
3461
3464
3465
3468
3469
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)
static bool signbit(qfloat16 f)
#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)