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/qdiriterator.h>
14#include <QtCore/qfile.h>
15#include <QtCore/qfileinfo.h>
16#include <QtCore/qfloat16.h>
17#include <QtCore/qlibraryinfo.h>
18#include <QtCore/qlist.h>
19#include <QtCore/qmetaobject.h>
20#include <QtCore/qobject.h>
21#include <QtCore/qstringlist.h>
22#include <QtCore/qtemporarydir.h>
23#include <QtCore/qthread.h>
24#include <QtCore/qvarlengtharray.h>
25#include <QtCore/private/qlocking_p.h>
26#include <QtCore/private/qtools_p.h>
27#include <QtCore/private/qwaitcondition_p.h>
29#include <QtCore/qtestsupport_core.h>
31#include <QtTest/private/qtestlog_p.h>
32#include <QtTest/private/qtesttable_p.h>
33#include <QtTest/qtestdata.h>
34#include <QtTest/private/qtestresult_p.h>
35#include <QtTest/private/qsignaldumper_p.h>
36#include <QtTest/private/qbenchmark_p.h>
37#if QT_CONFIG(batch_test_support)
38#include <QtTest/private/qtestregistry_p.h>
40#include <QtTest/private/cycle_p.h>
41#include <QtTest/private/qtestblacklist_p.h>
42#if defined(HAVE_XCTEST)
43#include <QtTest/private/qxctestlogger_p.h>
46#include <QtTest/private/qtestutil_macos_p.h>
49#if defined(Q_OS_DARWIN)
50#include <QtTest/private/qappletestlogger_p.h>
55#if !defined(Q_OS_INTEGRITY) || __GHS_VERSION_NUMBER > 202014
59# undef __cpp_lib_to_chars
72#if defined(Q_OS_LINUX)
79# if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR))
85#include <QtCore/private/qcore_unix_p.h>
88#if __has_include(<paths.h>)
97# if !defined(Q_OS_INTEGRITY)
98# include <sys/resource.h>
100# ifndef _PATH_DEFPATH
101# define _PATH_DEFPATH "/usr/bin:/bin"
107# define SA_RESETHAND 0
111#if defined(Q_OS_MACOS)
112#include <IOKit/pwr_mgt/IOPMLib.h>
113#include <mach/task.h>
114#include <mach/mach_init.h>
115#include <CoreFoundation/CFPreferences.h>
128enum DebuggerProgram {
None, Gdb, Lldb };
130#if defined(Q_OS_UNIX) && (!defined(Q_OS_WASM) || QT_CONFIG(thread))
131static struct iovec IoVec(struct iovec vec)
135static struct iovec IoVec(const char *
str)
138 r.iov_base =
const_cast<char *
>(
str);
139 r.iov_len = strlen(
str);
143template <
typename... Args>
static ssize_t writeToStderr(Args &&...
args)
145 struct iovec vec[] = { IoVec(std::forward<Args>(
args))... };
146 return ::writev(STDERR_FILENO, vec, std::size(vec));
150struct AsyncSafeIntBuffer
155 static constexpr int Digits10 = std::numeric_limits<int>::digits10 + 3;
156 std::array<char, Digits10>
array;
157 constexpr AsyncSafeIntBuffer() :
array{} {}
165#ifdef __cpp_lib_to_chars
166 }
else if (
auto r = std::to_chars(
ptr,
ptr +
result.array.size(),
n, 10);
r.ec == std::errc{}) {
177 static constexpr int StartingDivider = ([]() {
179 for (
int i = 0; i < std::numeric_limits<int>::digits10; ++
i)
183 int divider = StartingDivider;
184 while (divider &&
n < divider)
188 while (divider > 1) {
189 int quot =
n / divider;
202 r.iov_base =
result.array.data();
206#elif defined(Q_OS_WIN)
208template <
typename... Args>
static void writeToStderr(Args &&...
args)
210 (std::cerr << ... <<
args);
213static std::string asyncSafeToString(
int n)
215 return std::to_string(
n);
222#if defined(Q_OS_LINUX)
223 int fd =
open(
"/proc/self/status", O_RDONLY);
233 const char tracerPidToken[] =
"\nTracerPid:";
234 char *tracerPid = strstr(
buffer, tracerPidToken);
239 tracerPid +=
sizeof(tracerPidToken);
240 long int pid = strtol(tracerPid, &tracerPid, 10);
243#elif defined(Q_OS_WIN)
244 return IsDebuggerPresent();
245#elif defined(Q_OS_MACOS)
247 mach_msg_type_number_t portCount = 0;
248 exception_mask_t masks[EXC_TYPES_COUNT];
249 mach_port_t
ports[EXC_TYPES_COUNT];
250 exception_behavior_t behaviors[EXC_TYPES_COUNT];
251 thread_state_flavor_t flavors[EXC_TYPES_COUNT];
252 exception_mask_t
mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD);
253 kern_return_t
result = task_get_exception_ports(mach_task_self(),
mask, masks, &portCount,
254 ports, behaviors, flavors);
255 if (
result == KERN_SUCCESS) {
256 for (mach_msg_type_number_t portIndex = 0; portIndex < portCount; ++portIndex) {
257 if (MACH_PORT_VALID(
ports[portIndex])) {
271#if defined(Q_OS_MACOS)
283 if (
ok && disableCoreDump) {
287 if (setrlimit(RLIMIT_CORE, &
limit) != 0)
288 qWarning(
"Failed to disable core dumps: %d", errno);
299 if (
ok && disableStackDump)
305#if defined(Q_OS_MACOS)
306 #define CSR_ALLOW_UNRESTRICTED_FS (1 << 1)
307 std::optional<uint32_t> sipConfiguration = qt_mac_sipConfiguration();
308 if (!sipConfiguration || !(*sipConfiguration & CSR_ALLOW_UNRESTRICTED_FS))
314 auto hasExecutable = [](
const char *execname) {
315 std::string candidate;
317 if (
const char *
p = getenv(
"PATH");
p && *
p)
320 path = _PATH_DEFPATH;
321 for (
const char *
p = std::strtok(&
path[0],
":'");
p;
p = std::strtok(
nullptr,
":")) {
324 candidate += execname;
325 if (QT_ACCESS(candidate.data(), X_OK) == 0)
331 static constexpr DebuggerProgram debuggerSearchOrder[] = {
332# if defined(Q_OS_QNX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
338 for (DebuggerProgram candidate : debuggerSearchOrder) {
344 if (hasExecutable(
"gdb")) {
350 if (hasExecutable(
"lldb")) {
360#if !defined(Q_OS_WASM) || QT_CONFIG(thread)
366 writeToStderr(
"\n ",
name ?
name :
"[Non-test]",
367 " function time: ", asyncSafeToString(msecsFunctionTime),
368 "ms, total time: ", asyncSafeToString(msecsTotalTime),
"ms\n");
376# if defined(Q_OS_UNIX) && !defined(Q_OS_WASM) && !defined(Q_OS_INTEGRITY)
377 writeToStderr(
"\n=== Stack trace ===\n");
380 AsyncSafeIntBuffer pidbuffer;
381 asyncSafeToString(getpid(), std::move(pidbuffer));
389 (
void) dup2(STDERR_FILENO, STDOUT_FILENO);
396 execlp(
"gdb",
"gdb",
"--nx",
"--batch",
"-ex",
"thread apply all bt",
397 "--pid", pidbuffer.array.data(),
nullptr);
400 execlp(
"lldb",
"lldb",
"--no-lldbinit",
"--batch",
"-o",
"bt all",
401 "--attach-pid", pidbuffer.array.data(),
nullptr);
405 }
else if (pid < 0) {
406 writeToStderr(
"Failed to start debugger.\n");
412 writeToStderr(
"=== End of stack trace ===\n");
419#if defined(__COVERAGESCANNER__) && !QT_CONFIG(testlib_selfcover)
424 qputenv(
"QT_TESTCOCOON_ACTIVE",
"1");
427 __coveragescanner_install(appname);
428 __coveragescanner_testname(testname);
429 __coveragescanner_clear();
444 return !(
name.isEmpty() ||
name.endsWith(
"_data")
445 ||
name ==
"initTestCase" ||
name ==
"cleanupTestCase"
446 ||
name ==
"init" ||
name ==
"cleanup");
459 return "QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) "
460 "was too short, %3 ms would have been sufficient this time."_L1
473#if defined(Q_OS_MACOS)
474static IOPMAssertionID macPowerSavingDisabled = 0;
491 void invokeTestOnData(
int index)
const;
503 : m_initTestCaseMethod(
TestMethods::findMethod(
o,
"initTestCase()"))
504 , m_initTestCaseDataMethod(
TestMethods::findMethod(
o,
"initTestCase_data()"))
505 , m_cleanupTestCaseMethod(
TestMethods::findMethod(
o,
"cleanupTestCase()"))
507 , m_cleanupMethod(
TestMethods::findMethod(
o,
"cleanup()"))
508 , m_methods(
std::move(
m))
510 if (m_methods.empty()) {
513 m_methods.reserve(
count);
517 m_methods.push_back(me);
525 const int funcIndex =
metaObject->indexOfMethod(signature);
544 if (funcIndex >= 0) {
586static std::chrono::milliseconds defaultTimeout()
595 return std::chrono::milliseconds{
timeout};
609 bool matched =
false;
646 slot[strlen(slot) - 2] =
'\0';
651 const int dataCount =
table.dataCount();
652 localTags.reserve(dataCount);
653 for (
int j = 0;
j < dataCount; ++
j)
658 if (localTags.size() == 0) {
663 for (
int k = 0; k < localTags.size(); ++k)
666 currTestMetaObj->
className(), slot, localTags.at(k).toLatin1().data());
670 if (localTags.size() == 0) {
673 stream,
"%s %s __global__ %s\n",
678 for (
int k = 0; k < localTags.size(); ++k)
680 stream,
"%s %s %s __global__ %s\n", currTestMetaObj->
className(), slot,
694 int l =
static_cast<int>(strtol(
str, &pEnd, 10));
696 fprintf(stderr,
"Invalid numeric parameter: '%s'\n",
str);
705 const char *logFilename =
nullptr;
710#if defined(Q_OS_DARWIN) && defined(HAVE_XCTEST)
712 logFormat = QTestLog::XCTest;
715 const char *testOptions =
716 " New-style logging options:\n"
717 " -o filename,format : Output results to file in the specified format\n"
718 " Use - to output to stdout\n"
719 " Valid formats are:\n"
720 " txt : Plain text\n"
721 " csv : CSV format (suitable for benchmarks)\n"
722 " junitxml : XML JUnit document\n"
723 " xml : XML document\n"
724 " lightxml : A stream of XML tags\n"
725 " teamcity : TeamCity format\n"
726 " tap : Test Anything Protocol\n"
728 " *** Multiple loggers can be specified, but at most one can log to stdout.\n"
730 " Old-style logging options:\n"
731 " -o filename : Write the output into file\n"
732 " -txt : Output results in Plain Text\n"
733 " -csv : Output results in a CSV format (suitable for benchmarks)\n"
734 " -junitxml : Output results as XML JUnit document\n"
735 " -xml : Output results as XML document\n"
736 " -lightxml : Output results as stream of XML tags\n"
737 " -teamcity : Output results in TeamCity format\n"
738 " -tap : Output results in Test Anything Protocol format\n"
740 " *** If no output file is specified, stdout is assumed.\n"
741 " *** If no output format is specified, -txt is assumed.\n"
743 " Test log detail options:\n"
744 " -silent : Log failures and fatal errors only\n"
745 " -v1 : Log the start of each testfunction\n"
746 " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n"
747 " -vs : Log every signal emission and resulting slot invocations\n"
749 " *** The -silent and -v1 options only affect plain text output.\n"
751 " Testing options:\n"
752 " -functions : Returns a list of current testfunctions\n"
753 " -datatags : Returns a list of current data tags.\n"
754 " A global data tag is preceded by ' __global__ '.\n"
755 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
756 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
757 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
758 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
759 " 0 means unlimited, default: 2000\n"
760 " -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
762 " Benchmarking options:\n"
763#if QT_CONFIG(valgrind)
764 " -callgrind : Use callgrind to time benchmarks\n"
766#ifdef QTESTLIB_USE_PERF_EVENTS
767 " -perf : Use Linux perf events to time benchmarks\n"
768 " -perfcounter name : Use the counter named 'name'\n"
769 " -perfcounterlist : Lists the counters available\n"
771#ifdef HAVE_TICK_COUNTER
772 " -tickcounter : Use CPU tick counters to time benchmarks\n"
774 " -eventcounter : Counts events received during benchmarks\n"
775 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
776 " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
777 " -iterations n : Sets the number of accumulation iterations.\n"
778 " -median n : Sets the number of median iterations.\n"
779 " -vb : Print out verbose benchmarking information.\n";
781 for (
int i = 1;
i < argc; ++
i) {
782 if (strcmp(argv[
i],
"-help") == 0 || strcmp(argv[
i],
"--help") == 0
783 || strcmp(argv[
i],
"/?") == 0) {
784 printf(
" Usage: %s [options] [testfunction[:testdata]]...\n"
785 " By default, all testfunctions will be run.\n\n"
786 "%s", argv[0], testOptions);
790 " QmlTest options:\n"
791 " -import dir : Specify an import directory.\n"
792 " -plugins dir : Specify a directory where to search for plugins.\n"
793 " -input dir/file : Specify the root directory for test cases or a single test case file.\n"
794 " -translation file : Specify the translation file.\n"
795 " -file-selector dir : Specify a file selector for the QML engine.\n"
800 " -help : This help\n");
802 }
else if (strcmp(argv[
i],
"-functions") == 0) {
809 }
else if (strcmp(argv[
i],
"-datatags") == 0) {
814 }
else if (strcmp(argv[
i],
"-txt") == 0) {
816 }
else if (strcmp(argv[
i],
"-csv") == 0) {
818 }
else if (strcmp(argv[
i],
"-junitxml") == 0) {
820 }
else if (strcmp(argv[
i],
"-xunitxml") == 0) {
821 fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
823 }
else if (strcmp(argv[
i],
"-xml") == 0) {
825 }
else if (strcmp(argv[
i],
"-lightxml") == 0) {
827 }
else if (strcmp(argv[
i],
"-teamcity") == 0) {
829 }
else if (strcmp(argv[
i],
"-tap") == 0) {
831 }
else if (strcmp(argv[
i],
"-silent") == 0) {
833 }
else if (strcmp(argv[
i],
"-v1") == 0) {
835 }
else if (strcmp(argv[
i],
"-v2") == 0) {
837 }
else if (strcmp(argv[
i],
"-vs") == 0) {
839 }
else if (strcmp(argv[
i],
"-o") == 0) {
841 fprintf(stderr,
"-o needs an extra parameter specifying the filename and optional format\n");
846 char *filename =
new char[strlen(argv[
i])+1];
847 char *
format =
new char[strlen(argv[
i])+1];
848 if (sscanf(argv[
i],
"%[^,],%s", filename,
format) == 1) {
850 logFilename = argv[
i];
853 if (strcmp(
format,
"txt") == 0)
855 else if (strcmp(
format,
"csv") == 0)
857 else if (strcmp(
format,
"lightxml") == 0)
859 else if (strcmp(
format,
"xml") == 0)
861 else if (strcmp(
format,
"junitxml") == 0)
863 else if (strcmp(
format,
"xunitxml") == 0) {
864 fprintf(stderr,
"WARNING: xunitxml is deprecated. Please use junitxml.\n");
866 }
else if (strcmp(
format,
"teamcity") == 0)
868 else if (strcmp(
format,
"tap") == 0)
871 fprintf(stderr,
"output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
875 fprintf(stderr,
"only one logger can log to stdout\n");
882 }
else if (strcmp(argv[
i],
"-eventdelay") == 0) {
884 fprintf(stderr,
"-eventdelay needs an extra parameter to indicate the delay(ms)\n");
889 }
else if (strcmp(argv[
i],
"-keydelay") == 0) {
891 fprintf(stderr,
"-keydelay needs an extra parameter to indicate the delay(ms)\n");
896 }
else if (strcmp(argv[
i],
"-mousedelay") == 0) {
898 fprintf(stderr,
"-mousedelay needs an extra parameter to indicate the delay(ms)\n");
903 }
else if (strcmp(argv[
i],
"-maxwarnings") == 0) {
905 fprintf(stderr,
"-maxwarnings needs an extra parameter with the amount of warnings\n");
910 }
else if (strcmp(argv[
i],
"-nocrashhandler") == 0) {
912#if QT_CONFIG(valgrind)
913 }
else if (strcmp(argv[
i],
"-callgrind") == 0) {
916 "WARNING: Valgrind not found or too old. "
917 "Make sure it is installed and in your path. "
918 "Using the walltime measurer.\n");
924 "WARNING: Current directory not writable. "
925 "Using the walltime measurer.\n");
927 }
else if (strcmp(argv[
i],
"-callgrindchild") == 0) {
932#ifdef QTESTLIB_USE_PERF_EVENTS
933 }
else if (strcmp(argv[
i],
"-perf") == 0) {
938 fprintf(stderr,
"WARNING: Linux perf events not available. Using the walltime measurer.\n");
940 }
else if (strcmp(argv[
i],
"-perfcounter") == 0) {
942 fprintf(stderr,
"-perfcounter needs an extra parameter with the name of the counter\n");
947 }
else if (strcmp(argv[
i],
"-perfcounterlist") == 0) {
951#ifdef HAVE_TICK_COUNTER
952 }
else if (strcmp(argv[
i],
"-tickcounter") == 0) {
955 }
else if (strcmp(argv[
i],
"-eventcounter") == 0) {
957 }
else if (strcmp(argv[
i],
"-minimumvalue") == 0) {
959 fprintf(stderr,
"-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
964 }
else if (strcmp(argv[
i],
"-minimumtotal") == 0) {
966 fprintf(stderr,
"-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
971 }
else if (strcmp(argv[
i],
"-iterations") == 0) {
973 fprintf(stderr,
"-iterations needs an extra parameter to indicate the number of iterations\n");
978 }
else if (strcmp(argv[
i],
"-median") == 0) {
980 fprintf(stderr,
"-median needs an extra parameter to indicate the number of median iterations\n");
986 }
else if (strcmp(argv[
i],
"-vb") == 0) {
988#if defined(Q_OS_DARWIN)
989 }
else if (strncmp(argv[
i],
"-Apple", 6) == 0) {
992# if defined(HAVE_XCTEST)
998 }
else if (argv[
i][0] ==
'-') {
999 fprintf(stderr,
"Unknown option: '%s'\n\n%s", argv[
i], testOptions);
1001 fprintf(stderr,
"\nqmltest related options:\n"
1002 " -import : Specify an import directory.\n"
1003 " -plugins : Specify a directory where to search for plugins.\n"
1004 " -input : Specify the root directory for test cases.\n"
1008 fprintf(stderr,
"\n"
1009 " -help : This help\n");
1018 if (argv[
i][
offset + 1] ==
':') {
1045 const bool explicitLoggerRequested = logFormat != -1;
1049 bool addFallbackLogger = !explicitLoggerRequested;
1051#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
1054 if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) {
1057 addFallbackLogger =
false;
1061 if (addFallbackLogger)
1077 return container.front();
1080 std::sort(containerCopy.
begin(), containerCopy.
end(),
1082 return a.first() < b.first();
1085 const int middle =
count / 2;
1088 return containerCopy.
at(middle);
1103void TestMethods::invokeTestOnData(
int index)
const
1107 bool isBenchmark =
false;
1111 bool minimumTotalReached =
false;
1124 const bool initQuit =
1147 if (m_cleanupMethod.
isValid())
1164 }
while (invokeOk && isBenchmark
1178 :
"accumulation stage result: %1"_L1;
1186 minimumTotalReached =
true;
1190 current +=
r.first().measurement.value;
1193 const qreal total = std::accumulate(resultsList.
begin(), resultsList.
end(), 0.0, addResult);
1196 }
while (isBenchmark
1197 && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
1210#if QT_CONFIG(thread)
1212class WatchDog :
public QThread
1214 enum Expectation : std::size_t {
1223 static constexpr auto ExpectationMask = Expectation{ThreadStart | TestFunctionStart | TestFunctionEnd | ThreadEnd};
1224 static_assert(size_t(ExpectationMask) == 0x3);
1225 static constexpr size_t GenerationShift = 2;
1227 static constexpr Expectation
state(Expectation
e)
noexcept
1228 {
return Expectation{
e & ExpectationMask}; }
1229 static constexpr size_t generation(Expectation
e)
noexcept
1230 {
return e >> GenerationShift; }
1231 static constexpr Expectation combine(Expectation
e,
size_t gen)
noexcept
1232 {
return Expectation{
e | (gen << GenerationShift)}; }
1234 bool waitFor(std::unique_lock<std::mutex> &
m, Expectation
e)
1236 auto expectationChanged = [
this,
e] {
return expecting.load(std::memory_order_relaxed) !=
e; };
1238 case TestFunctionEnd:
1239 return waitCondition.wait_for(
m, defaultTimeout(), expectationChanged);
1242 case TestFunctionStart:
1243 waitCondition.wait(
m, expectationChanged);
1246 Q_UNREACHABLE_RETURN(
false);
1249 void setExpectation(Expectation
e)
1253 auto cur = expecting.load(std::memory_order_relaxed);
1254 auto gen = generation(cur);
1255 if (
e == TestFunctionStart)
1257 e = combine(
e, gen);
1258 expecting.store(
e, std::memory_order_relaxed);
1259 waitCondition.notify_all();
1267 expecting.store(ThreadStart, std::memory_order_relaxed);
1269 waitFor(locker, ThreadStart);
1274 setExpectation(ThreadEnd);
1280 setExpectation(TestFunctionEnd);
1285 setExpectation(TestFunctionStart);
1291 expecting.store(TestFunctionStart, std::memory_order_release);
1292 waitCondition.notify_all();
1294 Expectation
e = expecting.load(std::memory_order_acquire);
1300 case TestFunctionStart:
1301 case TestFunctionEnd:
1306 qFatal(
"Test function timed out");
1314 std::condition_variable waitCondition;
1315 std::atomic<Expectation> expecting;
1333 fprintf(stderr,
"Unknown testdata for function %s(): '%s'\n",
name.constData(),
tag.data());
1334 const int localDataCount = lTable.
dataCount();
1335 if (localDataCount) {
1336 fputs(
"Available test-specific data tags:\n", stderr);
1337 for (
int i = 0;
i < localDataCount; ++
i)
1340 const int globalDataCount = gTable.
dataCount();
1341 if (globalDataCount) {
1342 fputs(
"Available global data tags:\n", stderr);
1343 for (
int i = 0;
i < globalDataCount; ++
i)
1346 if (localDataCount == 0 && globalDataCount == 0)
1347 fputs(
"Function has no data tags\n", stderr);
1373 const int globalDataCount = gTable->
dataCount();
1374 int curGlobalDataIndex = 0;
1375 const auto globalDataTag = [gTable, globalDataCount](
int index) {
1386 return tag.startsWith(
global) &&
tag.endsWith(local) &&
1387 tag.size() ==
global.size() + 1 + local.size() &&
1390 bool foundFunction =
false;
1397 if (curGlobalDataIndex == 0) {
1404 int curDataIndex = 0;
1405 const int dataCount =
table.dataCount();
1406 const auto dataTag = [&
table, dataCount](
int index) {
1407 return dataCount ?
table.testData(
index)->dataTag() :
nullptr;
1416 foundFunction =
true;
1418 globalDataTag(curGlobalDataIndex));
1420 QTestDataSetter
s(curDataIndex >= dataCount ?
nullptr :
table.testData(curDataIndex));
1426 invokeTestOnData(
index);
1430 if (!
tag.isEmpty() && !globalDataCount)
1434 }
while (curDataIndex < dataCount);
1437 ++curGlobalDataIndex;
1438 }
while (curGlobalDataIndex < globalDataCount);
1440 if (!
tag.isEmpty() && !foundFunction) {
1454 QTEST_ASSERT_X(
data,
"QTest::fetchData()",
"Test data requested, but no testdata available.");
1457 int idx =
data->parent()->indexOf(tagName);
1460 qFatal(
"QFETCH: Requested testdata '%s' not available, check your _data function.",
1465 qFatal(
"Requested type '%s' does not match available type '%s'.",
1470 return data->data(idx);
1476char *
formatString(
const char *prefix,
const char *suffix,
size_t numArguments, ...)
1479 va_start(ap, numArguments);
1484 if (numArguments > 0) {
1487 for (
size_t i = 1;
i < numArguments; ++
i) {
1529 forElipsis[0] =
' ';
1530 forElipsis[1] =
'.';
1531 forElipsis[2] =
'.';
1532 forElipsis[3] =
'.';
1545 const char at =
ba[
i];
1569 bool trimmed =
false;
1570 auto buffer = std::make_unique<char[]>(256);
1574 bool lastWasHexEscape =
false;
1576 for ( ;
p !=
end; ++
p) {
1590 if (fromHex(*
p) != -1) {
1595 lastWasHexEscape =
false;
1598 if (*p < 0x7f && *p >= 0x20 && *
p !=
'\\' && *
p !=
'"') {
1631 lastWasHexEscape =
true;
1655 auto p =
string.utf16();
1656 auto length =
string.size();
1658 bool trimmed =
false;
1659 auto buffer = std::make_unique<char[]>(256);
1664 for ( ;
p !=
end; ++
p) {
1671 if (*p < 0x7f && *p >= 0x20 && *
p !=
'\\' && *
p !=
'"') {
1701 *
dst++ = toHexUpper(*
p >> 12);
1702 *
dst++ = toHexUpper(*
p >> 8);
1703 *
dst++ = toHexUpper(*
p >> 4);
1704 *
dst++ = toHexUpper(*
p);
1723 if (m_initTestCaseDataMethod.
isValid())
1738 if (m_initTestCaseMethod.
isValid())
1748 for (
int i = 0,
count =
int(m_methods.size());
i <
count; ++
i) {
1749 const char *
data =
nullptr;
1763 if (m_cleanupTestCaseMethod.
isValid())
1778 const char *lhsExpr,
const char *rhsExpr,
1787#if defined(Q_OS_WIN)
1790class DebugSymbolResolver
1792 Q_DISABLE_COPY_MOVE(DebugSymbolResolver)
1801 explicit DebugSymbolResolver(
HANDLE process);
1802 ~DebugSymbolResolver() { cleanup(); }
1804 bool isValid()
const {
return m_symFromAddr; }
1810 struct DBGHELP_SYMBOL_INFO {
1813 ULONG64 Reserved[2];
1828 typedef BOOL (__stdcall *SymInitializeType)(
HANDLE, PCSTR, BOOL);
1829 typedef BOOL (__stdcall *SymFromAddrType)(
HANDLE, DWORD64, PDWORD64, DBGHELP_SYMBOL_INFO *);
1835 SymFromAddrType m_symFromAddr;
1838void DebugSymbolResolver::cleanup()
1841 FreeLibrary(m_dbgHelpLib);
1843 m_symFromAddr =
nullptr;
1846DebugSymbolResolver::DebugSymbolResolver(
HANDLE process)
1847 : m_process(process), m_dbgHelpLib(0), m_symFromAddr(
nullptr)
1849 bool success =
false;
1850 m_dbgHelpLib = LoadLibraryW(L
"dbghelp.dll");
1852 SymInitializeType symInitialize =
reinterpret_cast<SymInitializeType
>(
1853 reinterpret_cast<QFunctionPointer
>(GetProcAddress(m_dbgHelpLib,
"SymInitialize")));
1854 m_symFromAddr =
reinterpret_cast<SymFromAddrType
>(
1855 reinterpret_cast<QFunctionPointer
>(GetProcAddress(m_dbgHelpLib,
"SymFromAddr")));
1856 success = symInitialize && m_symFromAddr && symInitialize(process, NULL, TRUE);
1862DebugSymbolResolver::Symbol DebugSymbolResolver::resolveSymbol(DWORD64
address)
const
1865 struct NamedSymbolInfo :
public DBGHELP_SYMBOL_INFO {
1866 enum { symbolNameLength = 255 };
1868 char name[symbolNameLength + 1];
1874 NamedSymbolInfo symbolBuffer;
1875 memset(&symbolBuffer, 0,
sizeof(NamedSymbolInfo));
1876 symbolBuffer.MaxNameLen = NamedSymbolInfo::symbolNameLength;
1877 symbolBuffer.SizeOfStruct =
sizeof(DBGHELP_SYMBOL_INFO);
1878 if (!m_symFromAddr(m_process,
address, 0, &symbolBuffer))
1881 result.address = symbolBuffer.Address;
1885class WindowsFaultHandler
1888 WindowsFaultHandler()
1890# if !defined(Q_CC_MINGW)
1891 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
1893 SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
1894 SetUnhandledExceptionFilter(windowsFaultHandler);
1898 static LONG WINAPI windowsFaultHandler(
struct _EXCEPTION_POINTERS *exInfo)
1900 enum { maxStackFrames = 100 };
1902 if (!GetModuleFileNameA(NULL, appName,
MAX_PATH))
1906 const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress;
1907 fprintf(stderr,
"A crash occurred in %s.\n", appName);
1909 fprintf(stderr,
"While testing %s\n",
name);
1910 fprintf(stderr,
"Function time: %dms Total time: %dms\n\n"
1911 "Exception address: 0x%p\n"
1912 "Exception code : 0x%lx\n",
1913 msecsFunctionTime, msecsTotalTime, exceptionAddress,
1914 exInfo->ExceptionRecord->ExceptionCode);
1916 DebugSymbolResolver resolver(GetCurrentProcess());
1917 if (resolver.isValid()) {
1918 DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress));
1919 if (exceptionSymbol.name) {
1920 fprintf(stderr,
"Nearby symbol : %s\n", exceptionSymbol.name);
1921 delete [] exceptionSymbol.name;
1923 void *stack[maxStackFrames];
1924 fputs(
"\nStack:\n", stderr);
1925 const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL);
1926 for (
unsigned f = 0;
f < frameCount; ++
f) {
1927 DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[
f]));
1929 fprintf(stderr,
"#%3u: %s() - 0x%p\n",
f + 1, symbol.name, (
const void *)symbol.address);
1930 delete [] symbol.name;
1932 fprintf(stderr,
"#%3u: Unable to obtain symbol\n",
f + 1);
1937 fputc(
'\n', stderr);
1939 return EXCEPTION_EXECUTE_HANDLER;
1942using FatalSignalHandler = WindowsFaultHandler;
1944#elif defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
1945class FatalSignalHandler
1948# define OUR_SIGNALS(F) \
1960# define CASE_LABEL(S) case SIG ## S: return QT_STRINGIFY(S);
1961# define ENUMERATE_SIGNALS(S) SIG ## S,
1962 static const char *signalName(
int signum)
noexcept
1965 OUR_SIGNALS(CASE_LABEL)
1968# if defined(__GLIBC_MINOR__) && (__GLIBC_MINOR__ >= 32 || __GLIBC__ > 2)
1971 if (
const char *
p = sigabbrev_np(signum))
1976 static constexpr std::array fatalSignals = {
1977 OUR_SIGNALS(ENUMERATE_SIGNALS)
1980# undef ENUMERATE_SIGNALS
1982 static constexpr std::array crashingSignals = {
1989 SIGILL, SIGBUS, SIGFPE, SIGSEGV
1991 using OldActionsArray = std::array<
struct sigaction, fatalSignals.
size()>;
1993 FatalSignalHandler()
1996 struct sigaction act;
1997 memset(&act, 0,
sizeof(act));
1998 act.sa_handler = SIG_DFL;
1999 oldActions().fill(act);
2002 act.sa_flags = SA_RESETHAND | setupAlternateStack();
2005 act.sa_flags |= SA_SIGINFO;
2006 act.sa_sigaction = FatalSignalHandler::actionHandler;
2008 act.sa_handler = FatalSignalHandler::regularHandler;
2013 sigemptyset(&act.sa_mask);
2014 for (
int signal : fatalSignals)
2015 sigaddset(&act.sa_mask,
signal);
2017 for (
size_t i = 0;
i < fatalSignals.size(); ++
i)
2018 sigaction(fatalSignals[
i], &act, &oldActions()[
i]);
2021 ~FatalSignalHandler()
2025 auto isOurs = [](
const struct sigaction &old) {
2027 return (old.sa_flags & SA_SIGINFO) && old.sa_sigaction == FatalSignalHandler::actionHandler;
2029 return old.sa_handler == FatalSignalHandler::regularHandler;
2032 struct sigaction action;
2034 for (
size_t i = 0;
i < fatalSignals.size(); ++
i) {
2035 struct sigaction &act = oldActions()[
i];
2036 if (act.sa_flags == 0 && act.sa_handler == SIG_DFL)
2038 if (sigaction(fatalSignals[
i],
nullptr, &action))
2041 sigaction(fatalSignals[
i], &act,
nullptr);
2044 freeAlternateStack();
2048 Q_DISABLE_COPY_MOVE(FatalSignalHandler)
2050 static OldActionsArray &oldActions()
2052 Q_CONSTINIT
static OldActionsArray oldActions {};
2056 auto alternateStackSize()
2058 struct R {
size_t size, pageSize; };
2059 static constexpr size_t MinStackSize = 32 * 1024;
2060 size_t pageSize = sysconf(_SC_PAGESIZE);
2061 size_t size = SIGSTKSZ;
2062 if (
size < MinStackSize) {
2063 size = MinStackSize;
2066 size = (
size + pageSize - 1) & -pageSize;
2069 return R{
size + pageSize, pageSize };
2072 int setupAlternateStack()
2076# if defined(SA_ONSTACK) && !defined(Q_OS_TVOS) && !defined(Q_OS_WATCHOS)
2079 auto r = alternateStackSize();
2080 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
2084 alternateStackBase = mmap(
nullptr,
r.size, PROT_READ | PROT_WRITE,
flags, -1, 0);
2089 (
void) mprotect(alternateStackBase,
r.pageSize, PROT_NONE);
2093 stack.ss_size =
r.size -
r.pageSize;
2094 stack.ss_sp =
static_cast<char *
>(alternateStackBase) +
r.pageSize;
2095 sigaltstack(&stack,
nullptr);
2102 void freeAlternateStack()
2104# if defined(SA_ONSTACK) && !defined(Q_OS_TVOS) && !defined(Q_OS_WATCHOS)
2107 stack.ss_flags = SS_DISABLE;
2108 sigaltstack(&stack,
nullptr);
2109 munmap(alternateStackBase, alternateStackSize().
size);
2114 template <
typename T>
static
2115 std::enable_if_t<sizeof(std::declval<T>().si_pid) +
sizeof(std::declval<T>().si_uid) >= 1>
2116 printSentSignalInfo(T *
info)
2118 writeToStderr(
" sent by PID ", asyncSafeToString(
info->si_pid),
2119 " UID ", asyncSafeToString(
info->si_uid));
2121 static void printSentSignalInfo(...) {}
2123 template <
typename T>
static
2124 std::enable_if_t<sizeof(std::declval<T>().si_addr) >= 1> printCrashingSignalInfo(T *
info)
2132 vec.iov_base =
r.data();
2133 vec.iov_len =
r.size();
2136 writeToStderr(
", code ", asyncSafeToString(
info->si_code),
2137 ", for address 0x", toHexString(
quintptr(
info->si_addr)));
2139 static void printCrashingSignalInfo(...) {}
2141 static void actionHandler(
int signum, siginfo_t *
info,
void * )
2143 writeToStderr(
"Received signal ", asyncSafeToString(signum),
2144 " (SIG", signalName(signum),
")");
2146 bool isCrashingSignal =
2147 std::find(crashingSignals.begin(), crashingSignals.end(), signum) != crashingSignals.end();
2148 if (isCrashingSignal && (!
info ||
info->si_code <= 0))
2149 isCrashingSignal =
false;
2150 if (isCrashingSignal)
2151 printCrashingSignalInfo(
info);
2152 else if (
info && (
info->si_code == SI_USER ||
info->si_code == SI_QUEUE))
2153 printSentSignalInfo(
info);
2156 if (signum != SIGINT) {
2159 writeToStderr(
"Pausing process ", asyncSafeToString(getpid()),
2160 " for debugging\n");
2166 for (
size_t i = 0;
i < fatalSignals.size(); ++
i) {
2167 struct sigaction &act = oldActions()[
i];
2168 if (signum != fatalSignals[
i])
2172 if (SA_RESETHAND == 0 || act.sa_handler != SIG_DFL || act.sa_flags)
2173 (
void) sigaction(signum, &act,
nullptr);
2175 if (!isCrashingSignal)
2186 [[maybe_unused]]
static void regularHandler(
int signum)
2188 actionHandler(signum,
nullptr,
nullptr);
2192 static bool pauseOnCrash;
2194bool FatalSignalHandler::pauseOnCrash =
false;
2196class FatalSignalHandler {};
2203 qputenv(
"QT_QTESTLIB_RUNNING",
"1");
2264#if defined(Q_OS_MACOS)
2271 if (
qApp && (
qstrcmp(
qApp->metaObject()->className(),
"QApplication") == 0)) {
2272 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
2273 kIOPMAssertionLevelOn, CFSTR(
"QtTest running tests"),
2274 &macPowerSavingDisabled);
2294#if QT_CONFIG(valgrind)
2309#if QT_CONFIG(valgrind)
2310 int callgrindChildExitCode = 0;
2313#ifndef QT_NO_EXCEPTIONS
2317#if QT_CONFIG(valgrind)
2320 qFatal(
"QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
2331 std::optional<FatalSignalHandler> handler;
2336 bool seenBad =
false;
2344 commandLineMethods.push_back(
m);
2346 fprintf(stderr,
"Unknown test function: '%s'.", tfB.
constData());
2348 fputc(
'\n', stderr);
2359 fprintf(stderr,
"\n%s -functions\nlists all available test functions.\n\n",
2361 if (commandLineMethods.empty())
2368#ifndef QT_NO_EXCEPTIONS
2384#if QT_CONFIG(valgrind)
2386 return callgrindChildExitCode;
2399#if QT_CONFIG(valgrind)
2410#if defined(Q_OS_MACOS)
2411 IOPMAssertionRelease(macPowerSavingDisabled);
2415#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
2426void QTest::qRegisterTestCase(
const QString &
name, TestEntryFunction entryFunction)
2436QTest::TestEntryFunction QTest::qGetTestCaseEntryFunction(
const QString&
name)
2458 for (
int i = 0;
i < argc; ++
i)
2476bool QTest::qVerify(
bool statement,
const char *statementStr,
const char *description,
2519 const auto exType = what ?
"std::" :
"unknown ";
2520 const auto ofType =
expected ?
" of type " :
"";
2521 const auto no =
expected ?
"an" :
"no";
2522 const auto withMsg = what ?
" with message " :
"";
2523 const auto protect = [](
const char *
s) {
return s ?
s :
""; };
2526 "but caught %sexception%s%s",
2528 exType, withMsg, protect(what));
2534#if QT_DEPRECATED_SINCE(6, 3)
2566#if QT_CONFIG(regularexpression)
2601#if QT_CONFIG(regularexpression)
2654static inline bool isWindowsBuildDirectory(
const QString &dirName)
2661#if QT_CONFIG(temporaryfile)
2678 tempDir->setAutoRemove(
true);
2680 if (!tempDir->isValid())
2683 const QString dataPath = tempDir->path();
2684 const QString resourcePath = u
':' + dirName;
2687 if (!fileInfo.isDir()) {
2693 if (!
it.hasNext()) {
2698 while (
it.hasNext()) {
2701 if (!fileInfo.
isDir()) {
2716 result = std::move(tempDir);
2726 const char *sourcedir)
2741 else if (isWindowsBuildDirectory(binDirectory.
dirName())
2749 "checking next location"_L1.arg(
base, candidate)),
2757 if (testObjectName) {
2759 const QString candidate =
"%1/%2/%3"_L1
2765 "checking next location"_L1
2788 "testdata %1 not found relative to source path [%2]"_L1
2801 "testdata %1 not found in resources [%2]"_L1
2814 "testdata %1 not found in current directory [%2]"_L1
2827 "testdata %1 not found in main source directory [%2]"_L1
2834 if (found.
isEmpty() && sourcedir) {
2840 "testdata %1 not found in supplied source directory [%2]"_L1
2849 "testdata %1 could not be located!"_L1.arg(
base)),
2863 const char *sourcedir)
2891 int idx =
data->parent()->indexOf(tagName);
2895 return data->data(
data->parent()->indexOf(tagName));
2903 QTEST_ASSERT_X(tbl,
"QTest::addColumn()",
"Cannot add testdata outside of a _data slot.");
2930 QTEST_ASSERT_X(dataTag,
"QTest::newRow()",
"Data tag cannot be null");
2932 QTEST_ASSERT_X(tbl,
"QTest::newRow()",
"Cannot add testdata outside of a _data slot.");
2934 "Must add columns before attempting to add rows.");
2936 return *tbl->
newData(dataTag);
2969 QTEST_ASSERT_X(tbl,
"QTest::addRow()",
"Cannot add testdata outside of a _data slot.");
2971 "Must add columns before attempting to add rows.");
2980 buf[
sizeof buf - 1] =
'\0';
3100#if QT_DEPRECATED_SINCE(6, 4)
3120 char *actualVal,
char *expectedVal,
3121 const char *actual,
const char *
expected,
3145 const char *actual,
const char *
expected,
3169template <
typename T>
3195 "Compared qfloat16s are not the same (fuzzy compare)",
3207 "Compared floats are not the same (fuzzy compare)",
3218 "Compared doubles are not the same (fuzzy compare)",
3230 "Compared values are not the same",
3234#if QT_POINTER_SIZE == 8
3244 "Compared values are not the same",
3257 "Compared values are not the same",
3269 "Compared values are not the same",
3281 "Compared values are not the same",
3293 "Compared values are not the same",
3320#define TO_STRING_IMPL(TYPE, FORMAT) \
3321template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3323 char *msg = new char[128]; \
3324 qsnprintf(msg, 128, #FORMAT, t); \
3334#if defined(Q_OS_WIN)
3357 char *
p = strchr(
text,
'e');
3360 const char *
const end =
p + strlen(
p);
3361 p += (
p[1] ==
'-' ||
p[1] ==
'+') ? 2 : 1;
3362 if (
p[0] !=
'0' ||
end - 2 <=
p)
3365 const char *
n =
p + 1;
3366 while (
end - 2 >
n &&
n[0] ==
'0')
3368 memmove(
p,
n,
end + 1 -
n);
3374#define TO_STRING_FLOAT(TYPE, FORMAT) \
3375template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
3377 char *msg = new char[128]; \
3378 switch (qFpClassify(t)) { \
3380 qstrncpy(msg, (t < 0 ? "-inf" : "inf"), 128); \
3383 qstrncpy(msg, "nan", 128); \
3386 qsnprintf(msg, 128, #FORMAT, double(t)); \
3387 massageExponent(msg); \
3397template <> Q_TESTLIB_EXPORT
char *QTest::toString<char>(
const char &
t)
3399 unsigned char c =
static_cast<unsigned char>(
t);
3400 char *msg =
new char[16];
3436 if (c < 0x20 || c >= 0x7F)
3449 char *msg =
new char[1];
3453 char *msg =
new char[strlen(
str) + 1];
3466 char *msg =
new char[128];
3478 auto *
o =
const_cast<const QObject*
>(vo);
3480 const char *
className =
o->metaObject()->className();
3481 char *msg =
new char[256];
std::unique_ptr< QTimer > watchDog
static bool preventsStderrLogging()
QBenchmarkContext context
QBenchmarkMeasurerBase * measurer
static QBenchmarkGlobalData * current
QString callgrindOutFileBase
virtual bool needsWarmupIteration()
static void listCounters()
static bool isAvailable()
static void setCounter(const char *name)
static QBenchmarkTestMethodData * current
QList< QBenchmarkResult > results
static QString outFileBase(qint64 pid=-1)
static bool rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode)
static bool haveValgrind()
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static QString applicationDirPath()
Returns the directory that contains the application executable.
static QStringList arguments()
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
The QDirIterator class provides an iterator for directory entrylists.
bool cdUp()
Changes directory by moving one directory up from the QDir's current directory.
QString dirName() const
Returns the name of the directory; this is not the same as the path, e.g.
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
static QString toNativeSeparators(const QString &pathName)
QString absoluteFilePath(const QString &fileName) const
Returns the absolute path name of a file in the directory.
static QString currentPath()
Returns the absolute path of the application's current directory.
\inmodule QtCore \reentrant
void setFile(const QString &file)
Sets the file that the QFileInfo provides information about to file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QString absolutePath() const
Returns a file's path absolute path.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
bool isAbsolute() const
Returns true if the file path is absolute, otherwise returns false (i.e.
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
bool exists() const
Returns true if the file exists; otherwise returns false.
bool setPermissions(Permissions permissionSpec) override
Sets the permissions for the file to the permissions specified.
bool copy(const QString &newName)
Copies the file named fileName() to newName.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
bool contains(QStringView s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
static QString path(LibraryPath p)
qsizetype size() const noexcept
const_pointer constData() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
const T & constFirst() const noexcept
void reserve(qsizetype size)
void append(parameter_type t)
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
\inmodule QtCore \reentrant
static QSharedPointer create(Args &&...arguments)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static void setEnabled(bool)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype size() const
Returns the number of characters in this string.
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
const char * dataTag() const
static int verboseLevel()
static void startLogging()
static qreal msecsFunctionTime()
static void setInstalledTestCoverage(bool installed)
static void setVerboseLevel(int level)
static bool loggerUsingStdout()
static void setMaxWarnings(int max)
static void info(const char *msg, const char *file, int line)
static void setPrintAvailableTagsMode()
static void addBenchmarkResults(const QList< QBenchmarkResult > &result)
static void stopLogging()
static void warn(const char *msg, const char *file, int line)
static qreal msecsTotalTime()
static void addLogger(LogMode mode, const char *filename)
static void ignoreMessage(QtMsgType type, const char *msg)
Disables App Nap by registering a background activity.
static const char * currentTestObjectName()
static void fail(const char *message, const char *file, int line)
static const char * currentAppName()
static void finishedCurrentTestDataCleanup()
This function is called after completing each test function, including test functions that are not da...
static void finishedCurrentTestData()
This function is called after completing each test function, including test functions that are not da...
static bool expectFail(const char *dataIndex, const char *comment, QTest::TestFailMode mode, const char *file, int line)
static bool verify(bool statement, const char *statementStr, const char *extraInfo, const char *file, int line)
static bool currentTestFailed()
static void setSkipCurrentTest(bool value)
static void setCurrentAppName(const char *appName)
static void setCurrentTestFunction(const char *func)
static void setBlacklistCurrentTest(bool b)
static void setCurrentTestObject(const char *name)
static const char * currentDataTag()
static bool compare(bool success, const char *failureMsg, char *val1, char *val2, const char *actual, const char *expected, const char *file, int line)
static void addFailure(const char *message, const char *file=nullptr, int line=0)
static bool skipCurrentTest()
static bool reportResult(bool success, qxp::function_ref< const char *()> lhs, qxp::function_ref< const char *()> rhs, const char *lhsExpr, const char *rhsExpr, QTest::ComparisonOperation op, const char *file, int line, const char *failureMessage=nullptr)
static void setCurrentGlobalTestData(QTestData *data)
static void finishedCurrentTestFunction()
This function is called after completing each test function, including test functions that are data-d...
static void setCurrentTestData(QTestData *data)
static void addSkip(const char *message, const char *file, int line)
static QTestData * currentGlobalTestData()
static QTestData * currentTestData()
static const char * currentTestFunction()
static QTestTable * currentTestTable()
QTestData * testData(int index) const
QTestData * newData(const char *tag)
static void clearGlobalTestTable()
void addColumn(int elementType, const char *elementName)
static QTestTable * globalTestTable()
static QMetaMethod findMethod(const QObject *obj, const char *signature)
TestMethods(const QObject *o, MetaMethods m={})
void invokeTests(QObject *testObject) const
std::vector< QMetaMethod > MetaMethods
TestEntryFunction getTestEntryFunction(const QString &name) const
static TestRegistry * instance()
void registerTest(const QString &name, TestEntryFunction data)
QStringList getAllTestNames() const
const void * constData() const
static int parseCommandLineArgument(const char *argument)
static bool canLogTestProgress()
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
QSet< QString >::iterator it
QList< QVariant > arguments
std::list< QString >::iterator Name
Combined button and popup list for selecting options.
Lock qt_scoped_lock(Mutex &mutex)
Lock qt_unique_lock(Mutex &mutex)
Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons
void disableWindowRestore()
bool macCrashReporterWillShowDialog()
void checkBlackLists(const char *slot, const char *data, const char *global)
Q_TESTLIB_EXPORT QString formatTryTimeoutDebugMessage(q_no_char8_t::QUtf8StringView expr, int timeout, int actual)
Q_TESTLIB_EXPORT int lastMouseTimestamp
static bool noCrashHandler
Q_TESTLIB_EXPORT int qRun()
Q_TESTLIB_EXPORT bool currentTestResolved()
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Appends a new row to the current test data.
Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool qml)
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 QObject * testObject()
int Q_TESTLIB_EXPORT defaultMouseDelay()
Q_TESTLIB_EXPORT bool runningTest()
static Q_CONSTINIT QBasicMutex mutex
Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir=nullptr)
static void qPrintDataTags(FILE *stream)
Q_TESTLIB_EXPORT void * qElementData(const char *elementName, int metaTypeId)
static void invokeMethod(QObject *obj, const char *methodName)
int Q_TESTLIB_EXPORT defaultKeyDelay()
Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, const char *file, int line)
char * toString(const MyPoint &point)
Q_TESTLIB_EXPORT QStringList testFunctions
static bool qPrintTestSlots(FILE *stream, const char *filter=nullptr, const char *preamble="")
Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg, qxp::function_ref< const char *()> actualVal, qxp::function_ref< const char *()> expectedVal, const char *actual, const char *expected, const char *file, int line)
Q_TESTLIB_EXPORT void * qData(const char *tagName, int typeId)
Q_TESTLIB_EXPORT bool currentTestFailed()
Returns true if the current test function has failed, otherwise false.
static bool installedTestCoverage
Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc=0, char **argv=nullptr)
Q_TESTLIB_EXPORT QStringList testTags
char * formatString(const char *prefix, const char *suffix, size_t numArguments,...)
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_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 QString qFindTestData(const char *basepath, const char *file=nullptr, int line=0, const char *builddir=nullptr, const char *sourcedir=nullptr)
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Ignores messages created by qDebug(), qInfo() or qWarning().
bool reportResult(bool success, qxp::function_ref< const char *()> lhs, qxp::function_ref< const char *()> rhs, const char *lhsExpr, const char *rhsExpr, ComparisonOperation op, const char *file, int line)
Q_TESTLIB_EXPORT void failOnWarning(const char *message)
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)
char * toPrettyUnicode(QStringView string)
Q_TESTLIB_EXPORT const char * currentDataTag()
Returns the name of the current test data.
Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc=0, char **argv=nullptr)
Executes tests declared in testObject.
Q_TESTLIB_EXPORT QTestData & addRow(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Q_TESTLIB_EXPORT void qCleanup()
Q_TESTLIB_EXPORT void addColumnInternal(int id, const char *name)
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)
static QObject * currentTestObject
Q_TESTLIB_EXPORT const char * currentAppName()
Returns the name of the binary that is currently executed.
static bool inTestFunction
static QString mainSourcePath
auto run(QThreadPool *pool, Function &&f, Args &&...args)
constexpr char toHexUpper(char32_t value) noexcept
constexpr char toHexLower(char32_t value) noexcept
constexpr int fromHex(char32_t c) noexcept
constexpr Initialization Uninitialized
static QT_WARNING_DISABLE_FLOAT_COMPARE ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
#define QByteArrayLiteral(str)
size_t qstrlen(const char *str)
int qstrncmp(const char *str1, const char *str2, size_t len)
Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
Q_CORE_EXPORT char * qstrdup(const char *)
Q_CORE_EXPORT char * qstrcpy(char *dst, const char *src)
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
#define EINTR_LOOP(var, cmd)
AudioChannelLayoutTag tag
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char * destination
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QString methodName(const QDBusIntrospection::Method &method)
const EGLAttrib EGLOutputPortEXT * ports
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
bool qFuzzyIsNull(qfloat16 f) noexcept
int qFpClassify(qfloat16 f) noexcept
int qRound(qfloat16 d) noexcept
static void installCoverageTool(QLibraryPrivate *libPrivate)
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMin(const T &a, const T &b)
static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease, const QOpenGLConfig::Gpu &gpu)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLbitfield GLuint64 timeout
[4]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLuint GLuint64EXT address
GLsizei const GLchar *const * path
GLenum GLenum GLsizei void * table
static void qInit(QSqlQuery *q, const QString &query, const QSqlDatabase &db)
static QString canonicalPath(const QString &rootPath)
#define qPrintable(string)
#define QT_CONFIG(feature)
bool qputenv(const char *varName, QByteArrayView raw)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define QTEST_ASSERT(cond)
#define QTEST_ASSERT_X(cond, where, what)
static bool alreadyDebugging()
static DebuggerProgram debugger
static bool floatingCompare(const T &actual, const T &expected)
#define TO_STRING_FLOAT(TYPE, FORMAT)
static void maybeDisableCoreDump()
static void prepareStackTrace()
static bool hasSystemCrashReporter()
#define TO_STRING_IMPL(TYPE, FORMAT)
static bool installCoverageTool(const char *appname, const char *testname)
static bool isValidSlot(const QMetaMethod &sl)
static void initEnvironment()
static void generateStackTrace()
static void massageExponent(char *text)
static void printTestRunTime()
unsigned long long quint64
ReturnedValue read(const char *data)
const char className[16]
[1]
file open(QIODevice::ReadOnly)
QFileInfo info(fileName)
[8]
QFileInfo fi("c:/temp/foo")
[newstuff]
obj metaObject() -> className()
char * toString(const MyType &t)
[31]
QTestDataSetter(QTestData *data)