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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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