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 <> inline const char *genericToString<std::nullptr_t>(const void *)
371 {
372 return QTest::toString(nullptr);
373 }
374
375 template <typename T> const char *pointerToString(const void *arg)
376 {
377 using QTest::toString;
378 return toString(static_cast<const T *>(arg));
379 }
380
381 // Exported so Qt Quick Test can also use it for generating backtraces upon crashes.
382 Q_TESTLIB_EXPORT extern bool noCrashHandler;
383
384 } // namespace Internal
385
386 Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc = 0, char **argv = nullptr);
387 Q_TESTLIB_EXPORT int qRun();
388 Q_TESTLIB_EXPORT void qCleanup();
389
390 Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = nullptr);
391 Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
392
393#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
394 using TestEntryFunction = int (*)(int, char **);
395 Q_TESTLIB_EXPORT void qRegisterTestCase(const QString &name, TestEntryFunction entryFunction);
396#endif // QT_CONFIG(batch_test_support)
397
398 Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = nullptr);
399 Q_TESTLIB_EXPORT void setThrowOnFail(bool enable) noexcept;
400 Q_TESTLIB_EXPORT void setThrowOnSkip(bool enable) noexcept;
401
402 class ThrowOnFailEnabler {
403 Q_DISABLE_COPY_MOVE(ThrowOnFailEnabler)
404 public:
405 ThrowOnFailEnabler() { setThrowOnFail(true); }
406 ~ThrowOnFailEnabler() { setThrowOnFail(false); }
407 };
408
409 class ThrowOnSkipEnabler {
410 Q_DISABLE_COPY_MOVE(ThrowOnSkipEnabler)
411 public:
412 ThrowOnSkipEnabler() { setThrowOnSkip(true); }
413 ~ThrowOnSkipEnabler() { setThrowOnSkip(false); }
414 };
415
416 class ThrowOnFailDisabler {
417 Q_DISABLE_COPY_MOVE(ThrowOnFailDisabler)
418 public:
419 ThrowOnFailDisabler() { setThrowOnFail(false); }
420 ~ThrowOnFailDisabler() { setThrowOnFail(true); }
421 };
422
423 class ThrowOnSkipDisabler {
424 Q_DISABLE_COPY_MOVE(ThrowOnSkipDisabler)
425 public:
426 ThrowOnSkipDisabler() { setThrowOnSkip(false); }
427 ~ThrowOnSkipDisabler() { setThrowOnSkip(true); }
428 };
429
430 Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description,
431 const char *file, int line);
432 Q_DECL_COLD_FUNCTION
433 Q_TESTLIB_EXPORT void qFail(const char *message, const char *file, int line);
434 Q_TESTLIB_EXPORT void qSkip(const char *message, const char *file, int line);
435 Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode,
436 const char *file, int line);
437 Q_DECL_COLD_FUNCTION
438 Q_TESTLIB_EXPORT void qCaught(const char *expected, const char *what, const char *file, int line);
439 Q_DECL_COLD_FUNCTION
440 Q_TESTLIB_EXPORT void qCaught(const char *expected, const char *file, int line);
441#if QT_DEPRECATED_SINCE(6, 3)
442 QT_DEPRECATED_VERSION_X_6_3("Use qWarning() instead")
443 Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = nullptr, int line = 0);
444#endif
445 Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message);
446#if QT_CONFIG(regularexpression)
447 Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern);
448#endif
449 Q_TESTLIB_EXPORT void failOnWarning();
450 Q_TESTLIB_EXPORT void failOnWarning(const char *message);
451#if QT_CONFIG(regularexpression)
452 Q_TESTLIB_EXPORT void failOnWarning(const QRegularExpression &messagePattern);
453#endif
454
455#if QT_CONFIG(temporaryfile)
456 Q_TESTLIB_EXPORT QSharedPointer<QTemporaryDir> qExtractTestData(const QString &dirName);
457#endif
458 Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr, const char* sourcedir = nullptr);
459 Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr, const char *sourcedir = nullptr);
460
461 Q_TESTLIB_EXPORT void *qData(const char *tagName, int typeId);
462 Q_TESTLIB_EXPORT void *qGlobalData(const char *tagName, int typeId);
463 Q_TESTLIB_EXPORT void *qElementData(const char *elementName, int metaTypeId);
464 Q_TESTLIB_EXPORT QObject *testObject();
465
466 Q_TESTLIB_EXPORT const char *currentAppName();
467
468 Q_TESTLIB_EXPORT const char *currentTestFunction();
469 Q_TESTLIB_EXPORT const char *currentDataTag();
470 Q_TESTLIB_EXPORT bool currentTestFailed();
471 Q_TESTLIB_EXPORT bool currentTestResolved();
472 Q_TESTLIB_EXPORT bool runningTest(); // Internal, for use by macros and QTestEventLoop.
473
474 Q_TESTLIB_EXPORT Qt::Key asciiToKey(char ascii);
475 Q_TESTLIB_EXPORT char keyToAscii(Qt::Key key);
476
477#if QT_DEPRECATED_SINCE(6, 4)
478 QT_DEPRECATED_VERSION_X_6_4("use an overload that takes a formatter callback, "
479 "or an overload that takes only failure message, if you "
480 "do not need to stringify the values")
481 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
482 char *actualVal, char *expectedVal,
483 const char *actual, const char *expected,
484 const char *file, int line);
485#endif // QT_DEPRECATED_SINCE(6, 4)
486#if QT_DEPRECATED_SINCE(6, 8)
487 QT_DEPRECATED_VERSION_X_6_8("use an overload that takes a formatter callback, "
488 "or an overload that takes only failure message, if you "
489 "do not need to stringify the values")
490 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
491 qxp::function_ref<const char*()> actualVal,
492 qxp::function_ref<const char*()> expectedVal,
493 const char *actual, const char *expected,
494 const char *file, int line);
495#endif // QT_DEPRECATED_SINCE(6, 8)
496 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
497 const void *actualPtr, const void *expectedPtr,
498 const char *(*actualFormatter)(const void *),
499 const char *(*expectedFormatter)(const void *),
500 const char *actual, const char *expected,
501 const char *file, int line);
502 Q_TESTLIB_EXPORT bool compare_helper(bool success, const char *failureMsg,
503 const char *actual, const char *expected,
504 const char *file, int line);
505
506 Q_TESTLIB_EXPORT void addColumnInternal(int id, const char *name);
507
508 template <typename T>
509 inline void addColumn(const char *name, T * = nullptr)
510 {
511 using QIsSameTConstChar = std::is_same<T, const char*>;
512 static_assert(!QIsSameTConstChar::value, "const char* is not allowed as a test data format.");
513 addColumnInternal(qMetaTypeId<T>(), name);
514 }
515 Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag);
516 Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
517
518 Q_TESTLIB_EXPORT bool qCompare(qfloat16 const &t1, qfloat16 const &t2,
519 const char *actual, const char *expected, const char *file, int line);
520
521 Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
522 const char *actual, const char *expected, const char *file, int line);
523
524 Q_TESTLIB_EXPORT bool qCompare(double const &t1, double const &t2,
525 const char *actual, const char *expected, const char *file, int line);
526
527 Q_TESTLIB_EXPORT bool qCompare(int t1, int t2, const char *actual, const char *expected,
528 const char *file, int line);
529
530#if QT_POINTER_SIZE == 8
531 Q_TESTLIB_EXPORT bool qCompare(qsizetype t1, qsizetype t2, const char *actual, const char *expected,
532 const char *file, int line);
533#endif
534
535 Q_TESTLIB_EXPORT bool qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected,
536 const char *file, int line);
537
538 Q_TESTLIB_EXPORT bool qCompare(QStringView t1, QStringView t2,
539 const char *actual, const char *expected,
540 const char *file, int line);
541 Q_TESTLIB_EXPORT bool qCompare(QStringView t1, const QLatin1StringView &t2,
542 const char *actual, const char *expected,
543 const char *file, int line);
544 Q_TESTLIB_EXPORT bool qCompare(const QLatin1StringView &t1, QStringView t2,
545 const char *actual, const char *expected,
546 const char *file, int line);
547 inline bool qCompare(const QString &t1, const QString &t2,
548 const char *actual, const char *expected,
549 const char *file, int line)
550 {
551 return qCompare(t1: QStringView(t1), t2: QStringView(t2), actual, expected, file, line);
552 }
553 inline bool qCompare(const QString &t1, const QLatin1StringView &t2,
554 const char *actual, const char *expected,
555 const char *file, int line)
556 {
557 return qCompare(t1: QStringView(t1), t2, actual, expected, file, line);
558 }
559 inline bool qCompare(const QLatin1StringView &t1, const QString &t2,
560 const char *actual, const char *expected,
561 const char *file, int line)
562 {
563 return qCompare(t1, t2: QStringView(t2), actual, expected, file, line);
564 }
565
566 inline bool compare_ptr_helper(const volatile void *t1, const volatile void *t2, const char *actual,
567 const char *expected, const char *file, int line)
568 {
569 auto formatter = Internal::pointerToString<void>;
570 return compare_helper(success: t1 == t2, failureMsg: "Compared pointers are not the same",
571 actualPtr: const_cast<const void *>(t1), expectedPtr: const_cast<const void *>(t2),
572 actualFormatter: formatter, expectedFormatter: formatter, actual, expected, file, line);
573 }
574
575 inline bool compare_ptr_helper(const volatile QObject *t1, const volatile QObject *t2, const char *actual,
576 const char *expected, const char *file, int line)
577 {
578 auto formatter = Internal::pointerToString<QObject>;
579 return compare_helper(success: t1 == t2, failureMsg: "Compared QObject pointers are not the same",
580 actualPtr: const_cast<const QObject *>(t1), expectedPtr: const_cast<const QObject *>(t2),
581 actualFormatter: formatter, expectedFormatter: formatter, actual, expected, file, line);
582 }
583
584 inline bool compare_ptr_helper(const volatile QObject *t1, std::nullptr_t, const char *actual,
585 const char *expected, const char *file, int line)
586 {
587 auto lhsFormatter = Internal::pointerToString<QObject>;
588 auto rhsFormatter = Internal::genericToString<std::nullptr_t>;
589 return compare_helper(success: t1 == nullptr, failureMsg: "Compared QObject pointers are not the same",
590 actualPtr: const_cast<const QObject *>(t1), expectedPtr: nullptr,
591 actualFormatter: lhsFormatter, expectedFormatter: rhsFormatter, actual, expected, file, line);
592 }
593
594 inline bool compare_ptr_helper(std::nullptr_t, const volatile QObject *t2, const char *actual,
595 const char *expected, const char *file, int line)
596 {
597 auto lhsFormatter = Internal::genericToString<std::nullptr_t>;
598 auto rhsFormatter = Internal::pointerToString<QObject>;
599 return compare_helper(success: nullptr == t2, failureMsg: "Compared QObject pointers are not the same",
600 actualPtr: nullptr, expectedPtr: const_cast<const QObject *>(t2),
601 actualFormatter: lhsFormatter, expectedFormatter: rhsFormatter, actual, expected, file, line);
602 }
603
604 inline bool compare_ptr_helper(const volatile void *t1, std::nullptr_t, const char *actual,
605 const char *expected, const char *file, int line)
606 {
607 auto lhsFormatter = Internal::pointerToString<void>;
608 auto rhsFormatter = Internal::genericToString<std::nullptr_t>;
609 return compare_helper(success: t1 == nullptr, failureMsg: "Compared pointers are not the same",
610 actualPtr: const_cast<const void *>(t1), expectedPtr: nullptr,
611 actualFormatter: lhsFormatter, expectedFormatter: rhsFormatter, actual, expected, file, line);
612 }
613
614 inline bool compare_ptr_helper(std::nullptr_t, const volatile void *t2, const char *actual,
615 const char *expected, const char *file, int line)
616 {
617 auto lhsFormatter = Internal::genericToString<std::nullptr_t>;
618 auto rhsFormatter = Internal::pointerToString<void>;
619 return compare_helper(success: nullptr == t2, failureMsg: "Compared pointers are not the same",
620 actualPtr: nullptr, expectedPtr: const_cast<const void *>(t2),
621 actualFormatter: lhsFormatter, expectedFormatter: rhsFormatter, actual, expected, file, line);
622 }
623
624 template <typename T1, typename T2 = T1>
625 inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected,
626 const char *file, int line)
627 {
628 using D1 = std::decay_t<T1>;
629 using D2 = std::decay_t<T2>;
630 using Internal::genericToString;
631 return compare_helper(t1 == t2, "Compared values are not the same",
632 std::addressof(t1), std::addressof(t2),
633 genericToString<D1>, genericToString<D2>,
634 actual, expected, file, line);
635 }
636
637 inline bool qCompare(double const &t1, float const &t2, const char *actual,
638 const char *expected, const char *file, int line)
639 {
640 return qCompare(t1: qreal(t1), t2: qreal(t2), actual, expected, file, line);
641 }
642
643 inline bool qCompare(float const &t1, double const &t2, const char *actual,
644 const char *expected, const char *file, int line)
645 {
646 return qCompare(t1: qreal(t1), t2: qreal(t2), actual, expected, file, line);
647 }
648
649 template <typename T>
650 inline bool qCompare(const T *t1, const T *t2, const char *actual, const char *expected,
651 const char *file, int line)
652 {
653 return compare_ptr_helper(t1, t2, actual, expected, file, line);
654 }
655 template <typename T>
656 inline bool qCompare(T *t1, T *t2, const char *actual, const char *expected,
657 const char *file, int line)
658 {
659 return compare_ptr_helper(t1, t2, actual, expected, file, line);
660 }
661
662 template <typename T>
663 inline bool qCompare(T *t1, std::nullptr_t, const char *actual, const char *expected,
664 const char *file, int line)
665 {
666 return compare_ptr_helper(t1, nullptr, actual, expected, file, line);
667 }
668 template <typename T>
669 inline bool qCompare(std::nullptr_t, T *t2, const char *actual, const char *expected,
670 const char *file, int line)
671 {
672 return compare_ptr_helper(nullptr, t2, actual, expected, file, line);
673 }
674
675 template <typename T1, typename T2>
676 inline bool qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected,
677 const char *file, int line)
678 {
679 return compare_ptr_helper(t1, static_cast<const T1 *>(t2), actual, expected, file, line);
680 }
681 template <typename T1, typename T2>
682 inline bool qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected,
683 const char *file, int line)
684 {
685 return compare_ptr_helper(const_cast<const T1 *>(t1),
686 static_cast<const T1 *>(const_cast<const T2 *>(t2)), actual, expected, file, line);
687 }
688 inline bool qCompare(const char *t1, const char *t2, const char *actual,
689 const char *expected, const char *file, int line)
690 {
691 return compare_string_helper(t1, t2, actual, expected, file, line);
692 }
693 inline bool qCompare(char *t1, char *t2, const char *actual, const char *expected,
694 const char *file, int line)
695 {
696 return compare_string_helper(t1, t2, actual, expected, file, line);
697 }
698
699 /* The next two overloads are for MSVC that shows problems with implicit
700 conversions
701 */
702 inline bool qCompare(char *t1, const 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 inline bool qCompare(const char *t1, char *t2, const char *actual,
708 const char *expected, const char *file, int line)
709 {
710 return compare_string_helper(t1, t2, actual, expected, file, line);
711 }
712
713 template <class T>
714 inline bool qTest(const T& actual, const char *elementName, const char *actualStr,
715 const char *expected, const char *file, int line)
716 {
717 return qCompare(actual, *static_cast<const T *>(QTest::qElementData(elementName,
718 metaTypeId: qMetaTypeId<T>())), actualStr, expected, file, line);
719 }
720
721#if QT_DEPRECATED_SINCE(6, 8)
722 QT_DEPRECATED_VERSION_X_6_8("use the overload without qxp::function_ref")
723 Q_TESTLIB_EXPORT bool reportResult(bool success, qxp::function_ref<const char*()> lhs,
724 qxp::function_ref<const char*()> rhs,
725 const char *lhsExpr, const char *rhsExpr,
726 ComparisonOperation op, const char *file, int line);
727#endif // QT_DEPRECATED_SINCE(6, 8)
728
729 Q_TESTLIB_EXPORT bool reportResult(bool success, const void *lhs, const void *rhs,
730 const char *(*lhsFormatter)(const void*),
731 const char *(*rhsFormatter)(const void*),
732 const char *lhsExpr, const char *rhsExpr,
733 ComparisonOperation op, const char *file, int line);
734
735 template <ComparisonOperation op, typename T1, typename T2 = T1>
736 inline bool qCompareOp(T1 &&lhs, T2 &&rhs, const char *lhsExpr, const char *rhsExpr,
737 const char *file, int line)
738 {
739 using D1 = std::decay_t<T1>;
740 using D2 = std::decay_t<T2>;
741 using Internal::genericToString;
742 using Comparator = Internal::Compare<op>;
743
744 /* assumes that op does not actually move from lhs and rhs */
745 bool result = Comparator::compare(std::forward<T1>(lhs), std::forward<T2>(rhs));
746 return reportResult(result, std::addressof(lhs), std::addressof(rhs),
747 genericToString<D1>, genericToString<D2>,
748 lhsExpr, rhsExpr, op, file, line);
749
750 }
751}
752
753
754#define QWARN(msg) QTest::qWarn(static_cast<const char *>(msg), __FILE__, __LINE__)
755
756QT_END_NAMESPACE
757
758#endif
759

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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