File: qcoroqmltask.cpp

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 (141 lines) | stat: -rw-r--r-- 3,705 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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-FileCopyrightText: 2022 Jonah BrĂ¼chert <jbb@kaidan.im>
//
// SPDX-License-Identifier: MIT

#include "qcoroqml.h"
#include "qcorotask.h"
#include "qcorotimer.h"
#include "qcoroqmltask.h"
#include "qcorofuture.h"

#include <QTest>
#include <QTimer>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <chrono>

using namespace std::chrono_literals;

class QmlObject : public QObject {
    Q_OBJECT

public:
    Q_INVOKABLE QCoro::QmlTask startTimer() {
        auto *timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(1s);
        return [timer]() -> QCoro::Task<> {
            co_await timer;
        }();
    }

    Q_INVOKABLE QCoro::QmlTask qmlTaskFromTimer() {
        auto *timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(1s);
        return timer;
    }

    Q_INVOKABLE QCoro::QmlTask qmlTaskFromFuture() {
        QFutureInterface<QString> interface;
        interface.reportResult(QStringLiteral("Success"));
        interface.reportFinished();
        return interface.future();
    }

    Q_INVOKABLE void reportTestSuccess() {
        numTestsPassed++;

        if (numTestsPassed == 4) { // Number of java script functions that call reportTestSuccess
            Q_EMIT success();
        }
    }

    Q_SIGNAL void success();

private:
    int numTestsPassed = 0;
};

class QCoroQmlTaskTest : public QObject {
    Q_OBJECT

private:
    Q_SLOT void testQmlCallback() {
        QQmlApplicationEngine engine;
        qmlRegisterSingletonType<QmlObject>("qcoro.test", 0, 1, "QmlObject", [](QQmlEngine *, QJSEngine *) {
            return new QmlObject();
        });

        QCoro::Qml::registerTypes();

        engine.loadData(R"(
import qcoro.test 0.1
import QCoro 0
import QtQuick 2.7

QtObject {
    property string value: QmlObject.qmlTaskFromFuture().await("Loading...").value

    property string valueWithoutIntermediate: QmlObject.qmlTaskFromFuture().await().value

    onValueChanged: {
        if (value == "Success") {
            console.log("awaiting finished")
            QmlObject.reportTestSuccess()
        }
    }

    Component.onCompleted: {
        QmlObject.startTimer().then(() => {
            console.log("QCoro::Task JavaScript callback called")
            QmlObject.reportTestSuccess()
        })

        QmlObject.qmlTaskFromTimer().then(() => {
            console.log("QTimer JavaScript callback called")
            QmlObject.reportTestSuccess()
        })

        QmlObject.qmlTaskFromFuture().then(() => {
            console.log("QFuture JavaScript callback called")
            QmlObject.reportTestSuccess()
        })
    }
}
)");
        auto *object = engine.singletonInstance<QmlObject *>(qmlTypeId("qcoro.test", 0, 1, "QmlObject"));

        auto *timeout = new QTimer(this);
        timeout->setSingleShot(true);
        timeout->setInterval(2s);
        timeout->start();

        bool running = true;
        // End the event loop normally
        connect(object, &QmlObject::success, this, [&]() {
            timeout->stop();
            running = false;
        });

        // Crash the test in case the timeout was reachaed without the callback being called
        connect(timeout, &QTimer::timeout, this, [&]() {
#if defined(Q_CC_CLANG) && defined(Q_OS_WINDOWS)
            running = false;
            QEXPECT_FAIL("", "QTBUG-91768", Abort);
            QVERIFY(false);
            return;
#else
            QFAIL("Timeout waiting for QML continuation to be called");
#endif
        });
        while (running) {
            QCoreApplication::processEvents();
        }
    }
};

QTEST_GUILESS_MAIN(QCoroQmlTaskTest)

#include "qcoroqmltask.moc"