File: qcorowebsocketserver.cpp

package info (click to toggle)
qcoro 0.12.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,700 kB
  • sloc: cpp: 8,573; python: 32; xml: 26; makefile: 23; sh: 15
file content (137 lines) | stat: -rw-r--r-- 5,068 bytes parent folder | download | duplicates (3)
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
// SPDX-FileCopyrightText: 2022 Daniel Vrátil <dvratil@kde.org>
//
// SPDX-License-Identifier: MIT

#include "websockets/qcorowebsocketserver.h"
#include "websockets/qcorowebsocket.h"
#include "testobject.h"

#include <QWebSocketServer>
#include <QWebSocket>

#include <QTest>

class QCoroWebSocketServerTest : public QCoro::TestObject<QCoroWebSocketServerTest> {
    Q_OBJECT
public:
    QCoroWebSocketServerTest(QObject *parent = nullptr)
        : QCoro::TestObject<QCoroWebSocketServerTest>(parent)
    {
        // On Windows, constructing QWebSocket for the first time takes some time
        // (most likely due to loading OpenSSL), which causes the first test to
        // time out on the CI.
        QWebSocket socket;
    }

private:
    QCoro::Task<> testNextPendingConnection_coro(QCoro::TestContext) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QCORO_VERIFY(server.listen(QHostAddress::LocalHost));

        QWebSocket socket;
        QCORO_DELAY(socket.open(server.serverUrl()));
        const auto serverSocket = std::unique_ptr<QWebSocket>(co_await qCoro(server).nextPendingConnection());
        QCORO_VERIFY(serverSocket != nullptr);
    }

    void testThenNextPendingConnection_coro(TestLoop &el) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QVERIFY(server.listen(QHostAddress::LocalHost));

        QWebSocket socket;
        QCORO_DELAY(socket.open(server.serverUrl()));

        bool called = false;
        qCoro(server).nextPendingConnection().then([&el, &called](QWebSocket *socket) {
            el.quit();
            called = true;
            QVERIFY(socket != nullptr);
            socket->deleteLater();
        });
        el.exec();
        QVERIFY(called);
    }

    QCoro::Task<> testNextPendingConnectionTimeout_coro(QCoro::TestContext) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QCORO_VERIFY(server.listen(QHostAddress::LocalHost));

        const auto *socket = co_await qCoro(server).nextPendingConnection(10ms);
        QCORO_COMPARE(socket, nullptr);
    }

    void testThenNextPendingConnectionTimeout_coro(TestLoop &el) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QVERIFY(server.listen(QHostAddress::LocalHost));

        bool called = false;
        qCoro(server).nextPendingConnection(100ms).then([&el, &called](QWebSocket *socket) {
            el.quit();
            called = true;
            QCOMPARE(socket, nullptr);
        });
        el.exec();
        QVERIFY(called);
    }

    QCoro::Task<> testClosingServerResumesAwaiters_coro(QCoro::TestContext) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QCORO_VERIFY(server.listen(QHostAddress::LocalHost));
        QCORO_DELAY(server.close());

        auto *socket = co_await qCoro(server).nextPendingConnection();
        QCORO_COMPARE(socket, nullptr);
    }

    void testThenClosingServerResumesAwaiters_coro(TestLoop &el) {
        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QVERIFY(server.listen(QHostAddress::LocalHost));
        QCORO_DELAY(server.close());

        bool called = false;
        qCoro(server).nextPendingConnection().then([&el, &called](QWebSocket *socket) {
            el.quit();
            called = true;
            QCOMPARE(socket, nullptr);
        });
        el.exec();
        QVERIFY(called);
    }

    QCoro::Task<> testDoesntCoawaitNonlisteningServer_coro(QCoro::TestContext ctx) {
        ctx.setShouldNotSuspend();

        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);

        const auto *socket = co_await qCoro(server).nextPendingConnection();
        QCORO_COMPARE(socket, nullptr);
    }

    QCoro::Task<> testDoesntCoawaitWithPendingConnection_coro(QCoro::TestContext ctx) {
        ctx.setShouldNotSuspend();

        QWebSocketServer server(QStringLiteral("TestWSServer"), QWebSocketServer::NonSecureMode);
        QCORO_VERIFY(server.listen(QHostAddress::LocalHost));

        QWebSocket socket;
        QCORO_VERIFY(QCoro::waitFor(qCoro(socket).open(server.serverUrl())));
        QCORO_COMPARE(socket.state(), QAbstractSocket::ConnectedState);

        QTest::qWait(100); // give the server time to register the incoming connection
        QCORO_VERIFY(server.hasPendingConnections());

        const auto serverSocket = std::unique_ptr<QWebSocket>(co_await qCoro(server).nextPendingConnection());
        QCORO_VERIFY(serverSocket);
    }

private Q_SLOTS:
    addCoroAndThenTests(NextPendingConnection)
    addCoroAndThenTests(NextPendingConnectionTimeout)
    addCoroAndThenTests(ClosingServerResumesAwaiters)
    addTest(DoesntCoawaitNonlisteningServer)
    addTest(DoesntCoawaitWithPendingConnection)
};

QTEST_GUILESS_MAIN(QCoroWebSocketServerTest)

#include "qcorowebsocketserver.moc"