1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTESTCASE_H
5#define QTESTCASE_H
6
7#include <QtTest/qttestglobal.h>
8
9#include <QtCore/qstring.h>
10#include <QtCore/qnamespace.h>
11#include <QtCore/qmetatype.h>
12#include <QtCore/qmetaobject.h>
13#include <QtCore/qsharedpointer.h>
14#include <QtCore/qtemporarydir.h>
15#include <QtCore/qthread.h>
16#include <QtCore/qxpfunctional.h>
17
18#include <string.h>
19
20#ifndef QT_NO_EXCEPTIONS
21# include <exception>
22#endif // QT_NO_EXCEPTIONS
23
24QT_BEGIN_NAMESPACE
25
26class qfloat16;
27class QRegularExpression;
28
29#define QVERIFY(statement) \
30do {\
31 if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\
32 return;\
33} while (false)
34
35#define QFAIL(message) \
36do {\
37 QTest::qFail(static_cast<const char *>(message), __FILE__, __LINE__);\
38 return;\
39} while (false)
40
41#define QVERIFY2(statement, description) \
42do {\
43 if (statement) {\
44 if (!QTest::qVerify(true, #statement, static_cast<const char *>(description), __FILE__, __LINE__))\
45 return;\
46 } else {\
47 if (!QTest::qVerify(false, #statement, static_cast<const char *>(description), __FILE__, __LINE__))\
48 return;\
49 }\
50} while (false)
51
52#define QCOMPARE(actual, expected) \
53do {\
54 if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
55 return;\
56} while (false)
57
58// A wrapper lambda is introduced to extend the lifetime of lhs and rhs in
59// case they are temporary objects.
60// We also use IILE to prevent potential name clashes and shadowing of variables
61// from user code. A drawback of the approach is that it looks ugly :(
62#define QCOMPARE_OP_IMPL(lhs, rhs, op, opId) \
63do { \
64 if (![](auto &&qt_lhs_arg, auto &&qt_rhs_arg) { \
65 /* assumes that op does not actually move from qt_{lhs, rhs}_arg */ \
66 return QTest::reportResult(std::forward<decltype(qt_lhs_arg)>(qt_lhs_arg) \
67 op \
68 std::forward<decltype(qt_rhs_arg)>(qt_rhs_arg), \
69 [&qt_lhs_arg] { return QTest::toString(qt_lhs_arg); }, \
70 [&qt_rhs_arg] { return QTest::toString(qt_rhs_arg); }, \
71 #lhs, #rhs, QTest::ComparisonOperation::opId, \
72 __FILE__, __LINE__); \
73 }(lhs, rhs)) { \
74 return; \
75 } \
76} while (false)
77
78#define QCOMPARE_EQ(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, ==, Equal)
79#define QCOMPARE_NE(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, !=, NotEqual)
80#define QCOMPARE_LT(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, <, LessThan)
81#define QCOMPARE_LE(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, <=, LessThanOrEqual)
82#define QCOMPARE_GT(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, >, GreaterThan)
83#define QCOMPARE_GE(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, >=, GreaterThanOrEqual)
84
85#ifndef QT_NO_EXCEPTIONS
86
87# define QVERIFY_THROWS_NO_EXCEPTION(...) \
88 do { \
89 QT_TRY { \
90 __VA_ARGS__; \
91 /* success */ \
92 } QT_CATCH (const std::exception &e) { \
93 QTest::qCaught(nullptr, e.what(), __FILE__, __LINE__); \
94 return; \
95 } QT_CATCH (...) { \
96 QTest::qCaught(nullptr, nullptr, __FILE__, __LINE__); \
97 QT_RETHROW; \
98 } \
99 } while (false) \
100 /* end */
101
102#if QT_DEPRECATED_SINCE(6, 3)
103namespace QTest {
104QT_DEPRECATED_VERSION_X_6_3("Don't use QVERIFY_EXCEPTION_THROWN(expr, type) anymore, "
105 "use QVERIFY_THROWS_EXCEPTION(type, expr...) instead")
106inline void useVerifyThrowsException() {}
107} // namespace QTest
108# define QVERIFY_EXCEPTION_THROWN(expression, exceptiontype) \
109 QVERIFY_THROWS_EXCEPTION(exceptiontype, QTest::useVerifyThrowsException(); expression)
110#endif
111
112# define QVERIFY_THROWS_EXCEPTION(exceptiontype, ...) \
113 do {\
114 QT_TRY {\
115 QT_TRY {\
116 __VA_ARGS__;\
117 QTest::qFail("Expected exception of type " #exceptiontype " to be thrown" \
118 " but no exception caught", __FILE__, __LINE__);\
119 return;\
120 } QT_CATCH (const exceptiontype &) {\
121 /* success */\
122 }\
123 } QT_CATCH (const std::exception &e) {\
124 QTest::qCaught(#exceptiontype, e.what(), __FILE__, __LINE__);\
125 return;\
126 } QT_CATCH (...) {\
127 QTest::qCaught(#exceptiontype, nullptr, __FILE__, __LINE__);\
128 QT_RETHROW;\
129 }\
130 } while (false)
131
132#else // QT_NO_EXCEPTIONS
133
134/*
135 * These macros check whether the expression passed throws exceptions, but we can't
136 * catch them to check because Qt has been compiled without exception support. We can't
137 * skip the expression because it may have side effects and must be executed.
138 * So, users must use Qt with exception support enabled if they use exceptions
139 * in their code.
140 */
141# define QVERIFY_THROWS_EXCEPTION(...) \
142 static_assert(false, "Support for exceptions is disabled")
143# define QVERIFY_THROWS_NO_EXCEPTION(...) \
144 static_assert(false, "Support for exceptions is disabled")
145
146#endif // !QT_NO_EXCEPTIONS
147
148/* Ideally we would adapt qWaitFor(), or a variant on it, to implement roughly
149 * what the following provides as QTRY_LOOP_IMPL(); however, for now, the
150 * reporting of how much to increase the timeout to (if within a factor of two)
151 * on failure and the check for (QTest::runningTest() &&
152 * QTest::currentTestResolved()) go beyond qWaitFor(). (We no longer care about
153 * the bug in MSVC < 2017 that precluded using qWaitFor() in the implementation
154 * here, see QTBUG-59096.)
155 */
156
157// NB: not do {...} while (0) wrapped, as qt_test_i is accessed after it
158#define QTRY_LOOP_IMPL(expr, timeoutValue, step) \
159 if (!(expr)) { \
160 QTest::qWait(0); \
161 } \
162 int qt_test_i = 0; \
163 for (; qt_test_i < timeoutValue && !(QTest::runningTest() && QTest::currentTestResolved()) \
164 && !(expr); qt_test_i += step) { \
165 QTest::qWait(step); \
166 }
167// Ends in a for-block, so doesn't want a following semicolon.
168
169#define QTRY_TIMEOUT_DEBUG_IMPL(expr, timeoutValue, step) \
170 if (!(QTest::runningTest() && QTest::currentTestResolved()) && !(expr)) { \
171 QTRY_LOOP_IMPL(expr, 2 * (timeoutValue), step) \
172 if ((expr)) { \
173 QFAIL(qPrintable(QTest::Internal::formatTryTimeoutDebugMessage(\
174 u8"" #expr, timeoutValue, timeoutValue + qt_test_i))); \
175 } \
176 }
177
178#define QTRY_IMPL(expr, timeout)\
179 const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; \
180 const int qt_test_timeoutValue = timeout; \
181 { QTRY_LOOP_IMPL(expr, qt_test_timeoutValue, qt_test_step) } \
182 QTRY_TIMEOUT_DEBUG_IMPL(expr, qt_test_timeoutValue, qt_test_step)
183// Ends with an if-block, so doesn't want a following semicolon.
184
185// Will try to wait for the expression to become true while allowing event processing
186#define QTRY_VERIFY_WITH_TIMEOUT(expr, timeout) \
187do { \
188 QTRY_IMPL(expr, timeout) \
189 QVERIFY(expr); \
190} while (false)
191
192#define QTRY_VERIFY(expr) QTRY_VERIFY_WITH_TIMEOUT(expr, 5000)
193
194// Will try to wait for the expression to become true while allowing event processing
195#define QTRY_VERIFY2_WITH_TIMEOUT(expr, messageExpression, timeout) \
196do { \
197 QTRY_IMPL(expr, timeout) \
198 QVERIFY2(expr, messageExpression); \
199} while (false)
200
201#define QTRY_VERIFY2(expr, messageExpression) QTRY_VERIFY2_WITH_TIMEOUT(expr, messageExpression, 5000)
202
203// Will try to wait for the comparison to become successful while allowing event processing
204#define QTRY_COMPARE_WITH_TIMEOUT(expr, expected, timeout) \
205do { \
206 QTRY_IMPL((expr) == (expected), timeout) \
207 QCOMPARE(expr, expected); \
208} while (false)
209
210#define QTRY_COMPARE(expr, expected) QTRY_COMPARE_WITH_TIMEOUT(expr, expected, 5000)
211
212#define QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, op, opId, timeout) \
213do { \
214 QTRY_IMPL(((computed) op (baseline)), timeout) \
215 QCOMPARE_OP_IMPL(computed, baseline, op, opId); \
216} while (false)
217
218#define QTRY_COMPARE_EQ_WITH_TIMEOUT(computed, baseline, timeout) \
219 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, ==, Equal, timeout)
220
221#define QTRY_COMPARE_EQ(computed, baseline) QTRY_COMPARE_EQ_WITH_TIMEOUT(computed, baseline, 5000)
222
223#define QTRY_COMPARE_NE_WITH_TIMEOUT(computed, baseline, timeout) \
224 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, !=, NotEqual, timeout)
225
226#define QTRY_COMPARE_NE(computed, baseline) QTRY_COMPARE_NE_WITH_TIMEOUT(computed, baseline, 5000)
227
228#define QTRY_COMPARE_LT_WITH_TIMEOUT(computed, baseline, timeout) \
229 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, <, LessThan, timeout)
230
231#define QTRY_COMPARE_LT(computed, baseline) QTRY_COMPARE_LT_WITH_TIMEOUT(computed, baseline, 5000)
232
233#define QTRY_COMPARE_LE_WITH_TIMEOUT(computed, baseline, timeout) \
234 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, <=, LessThanOrEqual, timeout)
235
236#define QTRY_COMPARE_LE(computed, baseline) QTRY_COMPARE_LE_WITH_TIMEOUT(computed, baseline, 5000)
237
238#define QTRY_COMPARE_GT_WITH_TIMEOUT(computed, baseline, timeout) \
239 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, >, GreaterThan, timeout)
240
241#define QTRY_COMPARE_GT(computed, baseline) QTRY_COMPARE_GT_WITH_TIMEOUT(computed, baseline, 5000)
242
243#define QTRY_COMPARE_GE_WITH_TIMEOUT(computed, baseline, timeout) \
244 QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, >=, GreaterThanOrEqual, timeout)
245
246#define QTRY_COMPARE_GE(computed, baseline) QTRY_COMPARE_GE_WITH_TIMEOUT(computed, baseline, 5000)
247
248#define QSKIP_INTERNAL(statement) \
249do {\
250 QTest::qSkip(static_cast<const char *>(statement), __FILE__, __LINE__);\
251 return;\
252} while (false)
253
254#define QSKIP(statement, ...) QSKIP_INTERNAL(statement)
255
256#define QEXPECT_FAIL(dataIndex, comment, mode)\
257do {\
258 if (!QTest::qExpectFail(dataIndex, static_cast<const char *>(comment), QTest::mode, __FILE__, __LINE__))\
259 return;\
260} while (false)
261
262#define QFETCH(Type, name)\
263 Type name = *static_cast<Type *>(QTest::qData(#name, ::qMetaTypeId<typename std::remove_cv<Type >::type>()))
264
265#define QFETCH_GLOBAL(Type, name)\
266 Type name = *static_cast<Type *>(QTest::qGlobalData(#name, ::qMetaTypeId<typename std::remove_cv<Type >::type>()))
267
268#define QTEST(actual, testElement)\
269do {\
270 if (!QTest::qTest(actual, testElement, #actual, #testElement, __FILE__, __LINE__))\
271 return;\
272} while (false)
273
274#ifdef QT_TESTCASE_BUILDDIR
275
276#ifndef QT_TESTCASE_SOURCEDIR
277#define QT_TESTCASE_SOURCEDIR nullptr
278#endif
279
280# define QFINDTESTDATA(basepath)\
281 QTest::qFindTestData(basepath, __FILE__, __LINE__, QT_TESTCASE_BUILDDIR, QT_TESTCASE_SOURCEDIR)
282#else
283# define QFINDTESTDATA(basepath)\
284 QTest::qFindTestData(basepath, __FILE__, __LINE__)
285#endif
286
287# define QEXTRACTTESTDATA(resourcePath) \
288 QTest::qExtractTestData(resourcePath)
289
290class QObject;
291class QTestData;
292
293#define QTEST_COMPARE_DECL(KLASS)\
294 template<> Q_TESTLIB_EXPORT char *toString<KLASS >(const KLASS &);
295
296namespace QTest
297{
298 namespace Internal {
299
300 Q_TESTLIB_EXPORT QString formatTryTimeoutDebugMessage(q_no_char8_t::QUtf8StringView expr, int timeout, int actual);
301
302 template<typename T> // Output registered enums
303 inline typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(T e)
304 {
305 QMetaEnum me = QMetaEnum::fromType<T>();
306 return qstrdup(me.valueToKey(value: int(e))); // int cast is necessary to support enum classes
307 }
308
309 template <typename T>
310 inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value && std::is_enum_v<T>, char*>::type toString(const T &e)
311 {
312 return qstrdup(QByteArray::number(static_cast<std::underlying_type_t<T>>(e)).constData());
313 }
314
315 template <typename T> // Fallback; for built-in types debug streaming must be possible
316 inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value && !std::is_enum_v<T>, char *>::type toString(const T &t)
317 {
318 char *result = nullptr;
319#ifndef QT_NO_DEBUG_STREAM
320 if constexpr (QTypeTraits::has_ostream_operator_v<QDebug, T>) {
321 result = qstrdup(QDebug::toString(t).toUtf8().constData());
322 } else {
323 static_assert(!QMetaTypeId2<T>::IsBuiltIn,
324 "Built-in type must implement debug streaming operator "
325 "or provide QTest::toString specialization");
326 }
327#endif
328 return result;
329 }
330
331 template<typename F> // Output QFlags of registered enumerations
332 inline typename std::enable_if<QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f)
333 {
334 const QMetaEnum me = QMetaEnum::fromType<F>();
335 return qstrdup(me.valueToKeys(value: int(f.toInt())).constData());
336 }
337
338 template <typename F> // Fallback: Output hex value
339 inline typename std::enable_if<!QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f)
340 {
341 const size_t space = 3 + 2 * sizeof(unsigned); // 2 for 0x, two hex digits per byte, 1 for '\0'
342 char *msg = new char[space];
343 qsnprintf(str: msg, n: space, fmt: "0x%x", unsigned(f.toInt()));
344 return msg;
345 }
346
347 } // namespace Internal
348
349 template<typename T>
350 inline char *toString(const T &t)
351 {
352 return Internal::toString(t);
353 }
354
355 template <typename T1, typename T2>
356 inline char *toString(const QPair<T1, T2> &pair);
357
358 template <typename T1, typename T2>
359 inline char *toString(const std::pair<T1, T2> &pair);
360
361 template <class... Types>
362 inline char *toString(const std::tuple<Types...> &tuple);
363
364 template <typename Rep, typename Period>
365 inline char *toString(std::chrono::duration<Rep, Period> duration);
366
367 Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, qsizetype length);
368 Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, qsizetype length);
369 Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
370 Q_TESTLIB_EXPORT char *toString(const char *);
371 Q_TESTLIB_EXPORT char *toString(const volatile void *);
372 Q_TESTLIB_EXPORT char *toString(const void *); // ### FIXME: Qt 7: Remove
373 Q_TESTLIB_EXPORT char *toString(const volatile QObject *);
374
375 Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc = 0, char **argv = nullptr);
376 Q_TESTLIB_EXPORT int qRun();
377 Q_TESTLIB_EXPORT void qCleanup();
378
379 Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = nullptr);
380 Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
381
382#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
383 using TestEntryFunction = int (*)(int, char **);
384 Q_TESTLIB_EXPORT void qRegisterTestCase(const QString &name, TestEntryFunction entryFunction);
385#endif // QT_CONFIG(batch_test_support)
386
387 Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = nullptr);
388
389 Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description,
390 const char *file, int line);
391 Q_DECL_COLD_FUNCTION
392 Q_TESTLIB_EXPORT void qFail(const char *message, const char *file, int line);
393 Q_TESTLIB_EXPORT void qSkip(const char *message, const char *file, int line);
394 Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode,
395 const char *file, int line);
396 Q_DECL_COLD_FUNCTION
397 Q_TESTLIB_EXPORT void qCaught(const char *expected, const char *what, const char *file, int line);
398#if QT_DEPRECATED_SINCE(6, 3)
399 QT_DEPRECATED_VERSION_X_6_3("Use qWarning() instead")
400 Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = nullptr, int line = 0);
401#endif
402 Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message);
403#if QT_CONFIG(regularexpression)
404 Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern);
405#endif
406 Q_TESTLIB_EXPORT void failOnWarning(const char *message);
407#if QT_CONFIG(regularexpression)
408 Q_TESTLIB_EXPORT void failOnWarning(const QRegularExpression &messagePattern);
409#endif
410
411#if QT_CONFIG(temporaryfile)
412 Q_TESTLIB_EXPORT QSharedPointer<QTemporaryDir> qExtractTestData(const QString &dirName);
413#endif
414 Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr, const char* sourcedir = nullptr);
415 Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr, const char *sourcedir = nullptr);
416
417 Q_TESTLIB_EXPORT void *qData(const char *tagName, int typeId);
418 Q_TESTLIB_EXPORT void *qGlobalData(const char *tagName, int typeId);
419 Q_TESTLIB_EXPORT void *qElementData(const char *elementName, int metaTypeId);
420 Q_TESTLIB_EXPORT QObject *testObject();
421
422 Q_TESTLIB_EXPORT const char *currentAppName();
423
424 Q_TESTLIB_EXPORT const char *currentTestFunction();
425 Q_TESTLIB_EXPORT const char *currentDataTag();
426 Q_TESTLIB_EXPORT bool currentTestFailed();
427 Q_TESTLIB_EXPORT bool currentTestResolved();
428 Q_TESTLIB_EXPORT bool runningTest(); // Internal, for use by macros and QTestEventLoop.
429
430 Q_TESTLIB_EXPORT Qt::Key asciiToKey(char ascii);
431 Q_TESTLIB_EXPORT char keyToAscii(Qt::Key key);
432
433 // ### TODO: remove QTestResult::compare() overload that takes char * values
434 // when this overload is removed.
435#if QT_DEPRECATED_SINCE(6, 4)
436 QT_DEPRECATED_VERSION_X_6_4("use an overload that takes function_ref as parameters, "
437 "or an overload that takes only failure message, if you "
438 "do not need to stringify the values")
439 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
440 char *actualVal, char *expectedVal,
441 const char *actual, const char *expected,
442 const char *file, int line);
443#endif // QT_DEPRECATED_SINCE(6, 4)
444 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
445 qxp::function_ref<const char*()> actualVal,
446 qxp::function_ref<const char*()> expectedVal,
447 const char *actual, const char *expected,
448 const char *file, int line);
449 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
450 const char *actual, const char *expected,
451 const char *file, int line);
452
453 Q_TESTLIB_EXPORT void addColumnInternal(int id, const char *name);
454
455 template <typename T>
456 inline void addColumn(const char *name, T * = nullptr)
457 {
458 using QIsSameTConstChar = std::is_same<T, const char*>;
459 static_assert(!QIsSameTConstChar::value, "const char* is not allowed as a test data format.");
460 addColumnInternal(qMetaTypeId<T>(), name);
461 }
462 Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag);
463 Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
464
465 Q_TESTLIB_EXPORT bool qCompare(qfloat16 const &t1, qfloat16 const &t2,
466 const char *actual, const char *expected, const char *file, int line);
467
468 Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
469 const char *actual, const char *expected, const char *file, int line);
470
471 Q_TESTLIB_EXPORT bool qCompare(double const &t1, double const &t2,
472 const char *actual, const char *expected, const char *file, int line);
473
474 Q_TESTLIB_EXPORT bool qCompare(int t1, int t2, const char *actual, const char *expected,
475 const char *file, int line);
476
477#if QT_POINTER_SIZE == 8
478 Q_TESTLIB_EXPORT bool qCompare(qsizetype t1, qsizetype t2, const char *actual, const char *expected,
479 const char *file, int line);
480#endif
481
482 Q_TESTLIB_EXPORT bool qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected,
483 const char *file, int line);
484
485 Q_TESTLIB_EXPORT bool qCompare(QStringView t1, QStringView t2,
486 const char *actual, const char *expected,
487 const char *file, int line);
488 Q_TESTLIB_EXPORT bool qCompare(QStringView t1, const QLatin1StringView &t2,
489 const char *actual, const char *expected,
490 const char *file, int line);
491 Q_TESTLIB_EXPORT bool qCompare(const QLatin1StringView &t1, QStringView t2,
492 const char *actual, const char *expected,
493 const char *file, int line);
494 inline bool qCompare(const QString &t1, const QString &t2,
495 const char *actual, const char *expected,
496 const char *file, int line)
497 {
498 return qCompare(t1: QStringView(t1), t2: QStringView(t2), actual, expected, file, line);
499 }
500 inline bool qCompare(const QString &t1, const QLatin1StringView &t2,
501 const char *actual, const char *expected,
502 const char *file, int line)
503 {
504 return qCompare(t1: QStringView(t1), t2, actual, expected, file, line);
505 }
506 inline bool qCompare(const QLatin1StringView &t1, const QString &t2,
507 const char *actual, const char *expected,
508 const char *file, int line)
509 {
510 return qCompare(t1, t2: QStringView(t2), actual, expected, file, line);
511 }
512
513 inline bool compare_ptr_helper(const volatile void *t1, const volatile void *t2, const char *actual,
514 const char *expected, const char *file, int line)
515 {
516 return compare_helper(success: t1 == t2, failureMsg: "Compared pointers are not the same",
517 actualVal: [t1] { return toString(t1); }, expectedVal: [t2] { return toString(t2); },
518 actual, expected, file, line);
519 }
520
521 inline bool compare_ptr_helper(const volatile QObject *t1, const volatile QObject *t2, const char *actual,
522 const char *expected, const char *file, int line)
523 {
524 return compare_helper(success: t1 == t2, failureMsg: "Compared QObject pointers are not the same",
525 actualVal: [t1] { return toString(t1); }, expectedVal: [t2] { return toString(t2); },
526 actual, expected, file, line);
527 }
528
529 inline bool compare_ptr_helper(const volatile QObject *t1, std::nullptr_t, const char *actual,
530 const char *expected, const char *file, int line)
531 {
532 return compare_helper(success: t1 == nullptr, failureMsg: "Compared QObject pointers are not the same",
533 actualVal: [t1] { return toString(t1); }, expectedVal: [] { return toString(t: nullptr); },
534 actual, expected, file, line);
535 }
536
537 inline bool compare_ptr_helper(std::nullptr_t, const volatile QObject *t2, const char *actual,
538 const char *expected, const char *file, int line)
539 {
540 return compare_helper(success: nullptr == t2, failureMsg: "Compared QObject pointers are not the same",
541 actualVal: [] { return toString(t: nullptr); }, expectedVal: [t2] { return toString(t2); },
542 actual, expected, file, line);
543 }
544
545 inline bool compare_ptr_helper(const volatile void *t1, std::nullptr_t, const char *actual,
546 const char *expected, const char *file, int line)
547 {
548 return compare_helper(success: t1 == nullptr, failureMsg: "Compared pointers are not the same",
549 actualVal: [t1] { return toString(t1); }, expectedVal: [] { return toString(t: nullptr); },
550 actual, expected, file, line);
551 }
552
553 inline bool compare_ptr_helper(std::nullptr_t, const volatile void *t2, const char *actual,
554 const char *expected, const char *file, int line)
555 {
556 return compare_helper(success: nullptr == t2, failureMsg: "Compared pointers are not the same",
557 actualVal: [] { return toString(t: nullptr); }, expectedVal: [t2] { return toString(t2); },
558 actual, expected, file, line);
559 }
560
561 Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual,
562 const char *expected, const char *file, int line);
563
564 Q_TESTLIB_EXPORT char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...);
565
566#ifndef Q_QDOC
567 QTEST_COMPARE_DECL(short)
568 QTEST_COMPARE_DECL(ushort)
569 QTEST_COMPARE_DECL(int)
570 QTEST_COMPARE_DECL(uint)
571 QTEST_COMPARE_DECL(long)
572 QTEST_COMPARE_DECL(ulong)
573 QTEST_COMPARE_DECL(qint64)
574 QTEST_COMPARE_DECL(quint64)
575
576 QTEST_COMPARE_DECL(float)
577 QTEST_COMPARE_DECL(double)
578 QTEST_COMPARE_DECL(qfloat16)
579 QTEST_COMPARE_DECL(char)
580 QTEST_COMPARE_DECL(signed char)
581 QTEST_COMPARE_DECL(unsigned char)
582 QTEST_COMPARE_DECL(bool)
583#endif
584
585 template <typename T1, typename T2 = T1>
586 inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected,
587 const char *file, int line)
588 {
589 return compare_helper(t1 == t2, "Compared values are not the same",
590 [&t1] { return toString(t1); }, [&t2] { return toString(t2); },
591 actual, expected, file, line);
592 }
593
594 inline bool qCompare(double const &t1, float const &t2, const char *actual,
595 const char *expected, const char *file, int line)
596 {
597 return qCompare(t1: qreal(t1), t2: qreal(t2), actual, expected, file, line);
598 }
599
600 inline bool qCompare(float const &t1, double const &t2, const char *actual,
601 const char *expected, const char *file, int line)
602 {
603 return qCompare(t1: qreal(t1), t2: qreal(t2), actual, expected, file, line);
604 }
605
606 template <typename T>
607 inline bool qCompare(const T *t1, const T *t2, const char *actual, const char *expected,
608 const char *file, int line)
609 {
610 return compare_ptr_helper(t1, t2, actual, expected, file, line);
611 }
612 template <typename T>
613 inline bool qCompare(T *t1, T *t2, const char *actual, const char *expected,
614 const char *file, int line)
615 {
616 return compare_ptr_helper(t1, t2, actual, expected, file, line);
617 }
618
619 template <typename T>
620 inline bool qCompare(T *t1, std::nullptr_t, const char *actual, const char *expected,
621 const char *file, int line)
622 {
623 return compare_ptr_helper(t1, nullptr, actual, expected, file, line);
624 }
625 template <typename T>
626 inline bool qCompare(std::nullptr_t, T *t2, const char *actual, const char *expected,
627 const char *file, int line)
628 {
629 return compare_ptr_helper(nullptr, t2, actual, expected, file, line);
630 }
631
632 template <typename T1, typename T2>
633 inline bool qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected,
634 const char *file, int line)
635 {
636 return compare_ptr_helper(t1, static_cast<const T1 *>(t2), actual, expected, file, line);
637 }
638 template <typename T1, typename T2>
639 inline bool qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected,
640 const char *file, int line)
641 {
642 return compare_ptr_helper(const_cast<const T1 *>(t1),
643 static_cast<const T1 *>(const_cast<const T2 *>(t2)), actual, expected, file, line);
644 }
645 inline bool qCompare(const char *t1, const char *t2, const char *actual,
646 const char *expected, const char *file, int line)
647 {
648 return compare_string_helper(t1, t2, actual, expected, file, line);
649 }
650 inline bool qCompare(char *t1, char *t2, const char *actual, const char *expected,
651 const char *file, int line)
652 {
653 return compare_string_helper(t1, t2, actual, expected, file, line);
654 }
655
656 /* The next two overloads are for MSVC that shows problems with implicit
657 conversions
658 */
659 inline bool qCompare(char *t1, const char *t2, const char *actual,
660 const char *expected, const char *file, int line)
661 {
662 return compare_string_helper(t1, t2, actual, expected, file, line);
663 }
664 inline bool qCompare(const char *t1, char *t2, const char *actual,
665 const char *expected, const char *file, int line)
666 {
667 return compare_string_helper(t1, t2, actual, expected, file, line);
668 }
669
670 template <class T>
671 inline bool qTest(const T& actual, const char *elementName, const char *actualStr,
672 const char *expected, const char *file, int line)
673 {
674 return qCompare(actual, *static_cast<const T *>(QTest::qElementData(elementName,
675 metaTypeId: qMetaTypeId<T>())), actualStr, expected, file, line);
676 }
677
678 Q_TESTLIB_EXPORT bool reportResult(bool success, qxp::function_ref<const char*()> lhs,
679 qxp::function_ref<const char*()> rhs,
680 const char *lhsExpr, const char *rhsExpr,
681 ComparisonOperation op, const char *file, int line);
682}
683
684#undef QTEST_COMPARE_DECL
685
686#define QWARN(msg) QTest::qWarn(static_cast<const char *>(msg), __FILE__, __LINE__)
687
688QT_END_NAMESPACE
689
690#endif
691

source code of qtbase/src/testlib/qtestcase.h