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 | |
25 | QT_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 | |
55 | class qfloat16; |
56 | class QRegularExpression; |
57 | |
58 | #define QVERIFY(statement) \ |
59 | do {\ |
60 | if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\ |
61 | QTEST_FAIL_ACTION; \ |
62 | } while (false) |
63 | |
64 | #define QFAIL(message) \ |
65 | do {\ |
66 | QTest::qFail(static_cast<const char *>(message), __FILE__, __LINE__);\ |
67 | QTEST_FAIL_ACTION; \ |
68 | } while (false) |
69 | |
70 | #define QVERIFY2(statement, description) \ |
71 | do {\ |
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) \ |
82 | do {\ |
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) \ |
88 | do { \ |
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) |
115 | namespace QTest { |
116 | QT_DEPRECATED_VERSION_X_6_3("Don't use QVERIFY_EXCEPTION_THROWN(expr, type) anymore, " |
117 | "use QVERIFY_THROWS_EXCEPTION(type, expr...) instead") |
118 | inline 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) \ |
202 | do { \ |
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) \ |
211 | do { \ |
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) \ |
220 | do { \ |
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) \ |
228 | do { \ |
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) \ |
265 | do {\ |
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)\ |
273 | do {\ |
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)\ |
285 | do {\ |
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 | |
306 | class QObject; |
307 | class QTestData; |
308 | |
309 | namespace 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 | |
756 | QT_END_NAMESPACE |
757 | |
758 | #endif |
759 |
Definitions
- useVerifyThrowsException
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- genericToString
- genericToString
- genericToString
- pointerToString
- ThrowOnFailEnabler
- ThrowOnFailEnabler
- ThrowOnFailEnabler
- ~ThrowOnFailEnabler
- ThrowOnSkipEnabler
- ThrowOnSkipEnabler
- ThrowOnSkipEnabler
- ~ThrowOnSkipEnabler
- ThrowOnFailDisabler
- ThrowOnFailDisabler
- ThrowOnFailDisabler
- ~ThrowOnFailDisabler
- ThrowOnSkipDisabler
- ThrowOnSkipDisabler
- ThrowOnSkipDisabler
- ~ThrowOnSkipDisabler
- addColumn
- qCompare
- qCompare
- qCompare
- compare_ptr_helper
- compare_ptr_helper
- compare_ptr_helper
- compare_ptr_helper
- compare_ptr_helper
- compare_ptr_helper
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qCompare
- qTest
Learn Advanced QML with KDAB
Find out more