File: testobject.h

package info (click to toggle)
qcoro 0.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,688 kB
  • sloc: cpp: 8,620; python: 32; xml: 26; makefile: 23; sh: 15
file content (108 lines) | stat: -rw-r--r-- 3,050 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-FileCopyrightText: 2021 Daniel Vrátil <dvratil@kde.org>
//
// SPDX-License-Identifier: MIT

#pragma once

#include <QEventLoop>
#include <QObject>
#include <QTest>
#include <QTimer>
#include <QVariant>

#include "qcorotask.h"
#include "qcorotest.h"
#include "testmacros.h"
#include "testloop.h"

#include <chrono>

using namespace std::chrono_literals;

namespace QCoro {

class TestContext {
public:
    TestContext(QEventLoop &el);
    TestContext(TestContext &&) noexcept;
    TestContext(const TestContext &) = delete;

    ~TestContext();

    TestContext &operator=(TestContext &&) noexcept;
    TestContext &operator=(const TestContext &) = delete;

    void setShouldNotSuspend();

private:
    QEventLoop *mEventLoop = {};
};

class EventLoopChecker : public QTimer {
    Q_OBJECT
public:
    explicit EventLoopChecker(int minTicks = 10, std::chrono::milliseconds interval = 5ms)
        : mMinTicks{minTicks} {
        connect(this, &EventLoopChecker::timeout, this, [this]() { ++mTick; });
        setInterval(interval);
        start();
    }

    operator bool() const {
        if (mTick < mMinTicks) {
            qDebug() << "EventLoopChecker failed: ticks=" << mTick << ", minTicks=" << mMinTicks;
        }
        return mTick >= mMinTicks;
    }

private:
    int mTick = 0;
    int mMinTicks = 10;
};

template<typename TestClass>
class TestObject : public QObject {
protected:
    explicit TestObject(QObject *parent = nullptr)
        : QObject(parent)
    {}

    void coroWrapper(QCoro::Task<> (TestClass::*testFunction)(TestContext)) {
        QEventLoop el;
        QTimer::singleShot(5s, &el, [&el]() mutable { el.exit(1); });

        (static_cast<TestClass *>(this)->*testFunction)(el);

        bool testFinished = el.property("testFinished").toBool();
        const bool shouldNotSuspend = el.property("shouldNotSuspend").toBool();
        if (testFinished) {
            QVERIFY(shouldNotSuspend);
        } else {
            QVERIFY(!shouldNotSuspend);

            const auto result = el.exec();
            QVERIFY2(result == 0, "Test function has timed out");

            testFinished = el.property("testFinished").toBool();
            QVERIFY(testFinished);
        }
    }
};

#define addTest(name)                                                                              \
    void test##name() {                                                                            \
        coroWrapper(&std::remove_cvref_t<decltype(*this)>::test##name##_coro);                     \
    }


#define addThenTest(name)                                                                          \
    void testThen##name() {                                                                        \
        TestLoop loop;                                                                             \
        testThen##name##_coro(loop);                                                               \
    }

#define addCoroAndThenTests(name) \
    addTest(name) \
    addThenTest(name)

} // namespace QCoro