File indexing completed on 2024-11-24 05:00:11

0001 /*
0002     SPDX-FileCopyrightText: 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef COMMON_TEST_H
0008 #define COMMON_TEST_H
0009 
0010 #include <QCoreApplication>
0011 #include <QDate>
0012 #include <QFuture>
0013 #include <QFutureWatcher>
0014 #include <QObject>
0015 #include <QTest>
0016 
0017 class Test : public QObject
0018 {
0019     Q_OBJECT
0020 public:
0021     Test(QObject *parent = nullptr);
0022 
0023 protected:
0024     enum WhenToFail {
0025         DontFail = 0,
0026         FailIfTrue = 1,
0027         FailIfFalse = 2,
0028     };
0029 
0030     template<typename _ReturnType, typename _Continuation>
0031     void continue_future(const QFuture<_ReturnType> &future, _Continuation &&continuation)
0032     {
0033         if (!future.isFinished()) {
0034             auto watcher = new QFutureWatcher<decltype(future.result())>();
0035             QObject::connect(
0036                 watcher,
0037                 &QFutureWatcherBase::finished,
0038                 watcher,
0039                 [=] {
0040                     continuation(watcher->result());
0041                     watcher->deleteLater();
0042                 },
0043                 Qt::QueuedConnection);
0044 
0045             watcher->setFuture(future);
0046 
0047         } else {
0048             continuation(future.result());
0049         }
0050     }
0051 
0052     template<typename _Continuation>
0053     void continue_future(const QFuture<void> &future, _Continuation &&continuation)
0054     {
0055         if (!future.isFinished()) {
0056             auto watcher = new QFutureWatcher<void>();
0057             QObject::connect(
0058                 watcher,
0059                 &QFutureWatcherBase::finished,
0060                 watcher,
0061                 [=] {
0062                     continuation();
0063                     watcher->deleteLater();
0064                 },
0065                 Qt::QueuedConnection);
0066 
0067             watcher->setFuture(future);
0068 
0069         } else {
0070             continuation();
0071         }
0072     }
0073 
0074     template<typename T>
0075     static inline void wait_until(T condition, const char *msg, int msecs = 300)
0076     {
0077         auto start = QTime::currentTime();
0078 
0079         while (!condition()) {
0080             QCoreApplication::processEvents();
0081 
0082             auto now = QTime::currentTime();
0083             QVERIFY2(start.msecsTo(now) < msecs, msg);
0084             if (start.msecsTo(now) >= msecs)
0085                 break;
0086         }
0087     }
0088 
0089 #define TEST_WAIT_UNTIL(C)                                                                                                                                     \
0090     wait_until(                                                                                                                                                \
0091         [&]() -> bool {                                                                                                                                        \
0092             return C;                                                                                                                                          \
0093         },                                                                                                                                                     \
0094         "Timeout waiting for: " #C);
0095 #define TEST_WAIT_UNTIL_WITH_TIMEOUT(C, T)                                                                                                                     \
0096     wait_until(                                                                                                                                                \
0097         [&]() -> bool {                                                                                                                                        \
0098             return C;                                                                                                                                          \
0099         },                                                                                                                                                     \
0100         "Timeout waiting for: " #C,                                                                                                                            \
0101         T);
0102 
0103     template<typename T>
0104     static bool check(T what, WhenToFail wtf = DontFail, const char *msg = nullptr)
0105     {
0106         bool result = what();
0107 
0108         if ((wtf == FailIfTrue && result) || (wtf == FailIfFalse && !result)) {
0109             qFatal(
0110                 "\n"
0111                 "\n"
0112                 "!!! > \n"
0113                 "!!! > %s\n"
0114                 "!!! > \n",
0115                 msg);
0116         }
0117 
0118         return result;
0119     }
0120 
0121     static bool inEmptySession();
0122     static bool isActivityManagerRunning();
0123 
0124 Q_SIGNALS:
0125     void testFinished();
0126 };
0127 
0128 #define CHECK_CONDITION(A, B) check(A, B, #A " raised " #B)
0129 
0130 // Pretty print
0131 #include <iostream>
0132 
0133 #if defined(Q_NO_DEBUG) || !defined(Q_OS_LINUX)
0134 #define TEST_CHUNK(Name)
0135 #else
0136 inline void _test_chunk(const QString &message)
0137 {
0138     std::cerr << '\n' << message.toStdString() << "\n" << std::string(message.length(), '-') << '\n';
0139 }
0140 #define TEST_CHUNK(Name) _test_chunk(Name);
0141 #endif
0142 
0143 #endif /* TEST_H */