1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2020 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QTEST_H
6#define QTEST_H
7
8#if 0
9#pragma qt_class(QTest)
10#endif
11
12#include <QtTest/qttestglobal.h>
13#include <QtTest/qtestcase.h>
14#include <QtTest/qtestdata.h>
15#include <QtTest/qtesttostring.h>
16#include <QtTest/qbenchmark.h>
17
18#if defined(TESTCASE_LOWDPI)
19#include <QtCore/qcoreapplication.h>
20#endif
21
22#include <cstdio>
23#include <initializer_list>
24#include <memory>
25
26QT_BEGIN_NAMESPACE
27
28namespace QTest
29{
30
31template<>
32inline bool qCompare(QString const &t1, QLatin1StringView const &t2, const char *actual,
33 const char *expected, const char *file, int line)
34{
35 return qCompare(t1, t2: QString(t2), actual, expected, file, line);
36}
37template<>
38inline bool qCompare(QLatin1StringView const &t1, QString const &t2, const char *actual,
39 const char *expected, const char *file, int line)
40{
41 return qCompare(t1: QString(t1), t2, actual, expected, file, line);
42}
43
44// Compare sequences of equal size
45template <typename ActualIterator, typename ExpectedIterator>
46bool _q_compareSequence(ActualIterator actualIt, ActualIterator actualEnd,
47 ExpectedIterator expectedBegin, ExpectedIterator expectedEnd,
48 const char *actual, const char *expected,
49 const char *file, int line)
50{
51 char msg[1024];
52 msg[0] = '\0';
53
54 const qsizetype actualSize = actualEnd - actualIt;
55 const qsizetype expectedSize = expectedEnd - expectedBegin;
56 bool isOk = actualSize == expectedSize;
57
58 if (!isOk) {
59 std::snprintf(s: msg, maxlen: sizeof(msg), format: "Compared lists have different sizes.\n"
60 " Actual (%s) size: %lld\n"
61 " Expected (%s) size: %lld",
62 actual, qlonglong(actualSize),
63 expected, qlonglong(expectedSize));
64 }
65
66 for (auto expectedIt = expectedBegin; isOk && expectedIt < expectedEnd; ++actualIt, ++expectedIt) {
67 if (!(*actualIt == *expectedIt)) {
68 const qsizetype i = qsizetype(expectedIt - expectedBegin);
69 char *val1 = toString(*actualIt);
70 char *val2 = toString(*expectedIt);
71
72 std::snprintf(s: msg, maxlen: sizeof(msg), format: "Compared lists differ at index %lld.\n"
73 " Actual (%s): %s\n"
74 " Expected (%s): %s",
75 qlonglong(i), actual, val1 ? val1 : "<null>",
76 expected, val2 ? val2 : "<null>");
77 isOk = false;
78
79 delete [] val1;
80 delete [] val2;
81 }
82 }
83 return compare_helper(success: isOk, failureMsg: msg, actual, expected, file, line);
84}
85
86namespace Internal {
87
88#if defined(TESTCASE_LOWDPI)
89void disableHighDpi()
90{
91 qputenv("QT_ENABLE_HIGHDPI_SCALING", "0");
92}
93Q_CONSTRUCTOR_FUNCTION(disableHighDpi);
94#endif
95
96} // namespace Internal
97
98template <typename T>
99inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, const char *expected,
100 const char *file, int line)
101{
102 return _q_compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(),
103 actual, expected, file, line);
104}
105
106template <typename T, int N>
107bool qCompare(QList<T> const &t1, std::initializer_list<T> t2,
108 const char *actual, const char *expected,
109 const char *file, int line)
110{
111 return _q_compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(),
112 actual, expected, file, line);
113}
114
115// Compare QList against array
116template <typename T, int N>
117bool qCompare(QList<T> const &t1, const T (& t2)[N],
118 const char *actual, const char *expected,
119 const char *file, int line)
120{
121 return _q_compareSequence(t1.cbegin(), t1.cend(), t2, t2 + N,
122 actual, expected, file, line);
123}
124
125template <typename T>
126inline bool qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected,
127 const char *file, int line)
128{
129 using Int = typename QFlags<T>::Int;
130 return qCompare(Int(t1), Int(t2), actual, expected, file, line);
131}
132
133template <typename T>
134inline bool qCompare(QFlags<T> const &t1, int const &t2, const char *actual, const char *expected,
135 const char *file, int line)
136{
137 using Int = typename QFlags<T>::Int;
138 return qCompare(Int(t1), Int(t2), actual, expected, file, line);
139}
140
141template<>
142inline bool qCompare(qint64 const &t1, qint32 const &t2, const char *actual,
143 const char *expected, const char *file, int line)
144{
145 return qCompare(t1, t2: static_cast<qint64>(t2), actual, expected, file, line);
146}
147
148template<>
149inline bool qCompare(qint64 const &t1, quint32 const &t2, const char *actual,
150 const char *expected, const char *file, int line)
151{
152 return qCompare(t1, t2: static_cast<qint64>(t2), actual, expected, file, line);
153}
154
155template<>
156inline bool qCompare(quint64 const &t1, quint32 const &t2, const char *actual,
157 const char *expected, const char *file, int line)
158{
159 return qCompare(t1, t2: static_cast<quint64>(t2), actual, expected, file, line);
160}
161
162template<>
163inline bool qCompare(qint32 const &t1, qint64 const &t2, const char *actual,
164 const char *expected, const char *file, int line)
165{
166 return qCompare(t1: static_cast<qint64>(t1), t2, actual, expected, file, line);
167}
168
169template<>
170inline bool qCompare(quint32 const &t1, qint64 const &t2, const char *actual,
171 const char *expected, const char *file, int line)
172{
173 return qCompare(t1: static_cast<qint64>(t1), t2, actual, expected, file, line);
174}
175
176template<>
177inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
178 const char *expected, const char *file, int line)
179{
180 return qCompare(t1: static_cast<quint64>(t1), t2, actual, expected, file, line);
181}
182namespace Internal {
183
184template <typename T>
185class HasInitMain // SFINAE test for the presence of initMain()
186{
187private:
188 using YesType = char[1];
189 using NoType = char[2];
190
191 template <typename C> static YesType& test( decltype(&C::initMain) ) ;
192 template <typename C> static NoType& test(...);
193
194public:
195 enum { value = sizeof(test<T>(nullptr)) == sizeof(YesType) };
196};
197
198template<typename T>
199typename std::enable_if<HasInitMain<T>::value, void>::type callInitMain()
200{
201 T::initMain();
202}
203
204template<typename T>
205typename std::enable_if<!HasInitMain<T>::value, void>::type callInitMain()
206{
207}
208
209} // namespace Internal
210
211} // namespace QTest
212QT_END_NAMESPACE
213
214#ifdef QT_TESTCASE_BUILDDIR
215# define QTEST_SET_MAIN_SOURCE_PATH QTest::setMainSourcePath(__FILE__, QT_TESTCASE_BUILDDIR);
216#else
217# define QTEST_SET_MAIN_SOURCE_PATH QTest::setMainSourcePath(__FILE__);
218#endif
219
220// Hooks for coverage-testing of QTestLib itself:
221#if QT_CONFIG(testlib_selfcover) && defined(__COVERAGESCANNER__)
222struct QtCoverageScanner
223{
224 QtCoverageScanner(const char *name)
225 {
226 __coveragescanner_clear();
227 __coveragescanner_testname(name);
228 }
229 ~QtCoverageScanner()
230 {
231 __coveragescanner_save();
232 __coveragescanner_testname("");
233 }
234};
235#define TESTLIB_SELFCOVERAGE_START(name) QtCoverageScanner _qtCoverageScanner(name);
236#else
237#define TESTLIB_SELFCOVERAGE_START(name)
238#endif
239
240#if !defined(QTEST_BATCH_TESTS)
241// Internal (but used by some testlib selftests to hack argc and argv).
242// Tests should normally implement initMain() if they have set-up to do before
243// instantiating the test class.
244#define QTEST_MAIN_WRAPPER(TestObject, ...) \
245int main(int argc, char *argv[]) \
246{ \
247 TESTLIB_SELFCOVERAGE_START(#TestObject) \
248 QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \
249 __VA_ARGS__ \
250 TestObject tc; \
251 QTEST_SET_MAIN_SOURCE_PATH \
252 return QTest::qExec(&tc, argc, argv); \
253}
254#else
255// BATCHED_TEST_NAME is defined for each test in a batch in cmake. Some odd
256// targets, like snippets, don't define it though. Play safe by providing a
257// default value.
258#if !defined(BATCHED_TEST_NAME)
259#define BATCHED_TEST_NAME "other"
260#endif
261#define QTEST_MAIN_WRAPPER(TestObject, ...) \
262\
263void qRegister##TestObject() \
264{ \
265 auto runTest = [](int argc, char** argv) -> int { \
266 TESTLIB_SELFCOVERAGE_START(TestObject) \
267 QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \
268 __VA_ARGS__ \
269 TestObject tc; \
270 QTEST_SET_MAIN_SOURCE_PATH \
271 return QTest::qExec(&tc, argc, argv); \
272 }; \
273 QTest::qRegisterTestCase(QStringLiteral(BATCHED_TEST_NAME), runTest); \
274} \
275\
276Q_CONSTRUCTOR_FUNCTION(qRegister##TestObject)
277#endif
278
279// For when you don't even want a QApplication:
280#define QTEST_APPLESS_MAIN(TestObject) QTEST_MAIN_WRAPPER(TestObject)
281
282#include <QtTest/qtestsystem.h>
283
284#if defined(QT_NETWORK_LIB)
285# include <QtTest/qtest_network.h>
286#endif
287
288// Internal
289#define QTEST_QAPP_SETUP(klaz) \
290 klaz app(argc, argv); \
291 app.setAttribute(Qt::AA_Use96Dpi, true);
292
293#if defined(QT_WIDGETS_LIB)
294# include <QtTest/qtest_widgets.h>
295# ifdef QT_KEYPAD_NAVIGATION
296# define QTEST_DISABLE_KEYPAD_NAVIGATION QApplication::setNavigationMode(Qt::NavigationModeNone);
297# else
298# define QTEST_DISABLE_KEYPAD_NAVIGATION
299# endif
300// Internal
301# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QApplication) QTEST_DISABLE_KEYPAD_NAVIGATION
302#elif defined(QT_GUI_LIB)
303# include <QtTest/qtest_gui.h>
304// Internal
305# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QGuiApplication)
306#else
307// Internal
308# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QCoreApplication)
309#endif // QT_GUI_LIB
310
311// For most tests:
312#define QTEST_MAIN(TestObject) QTEST_MAIN_WRAPPER(TestObject, QTEST_MAIN_SETUP())
313
314// For command-line tests
315#define QTEST_GUILESS_MAIN(TestObject) \
316 QTEST_MAIN_WRAPPER(TestObject, QTEST_QAPP_SETUP(QCoreApplication))
317
318#endif
319

Provided by KDAB

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

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