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 <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 | |
751 | QT_END_NAMESPACE |
752 | |
753 | #endif |
754 |
Definitions
- useVerifyThrowsException
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- Compare
- compare
- 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
Start learning QML with our Intro Training
Find out more