1 /*
2    SPDX-FileCopyrightText: 2008 Omat Holding B.V. <info@omat.nl>
3    SPDX-FileCopyrightText: 2009 Thomas McGuire <mcguire@kde.org>
4 
5    SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #pragma once
9 
10 #include <QMutex>
11 #include <QThread>
12 
13 class QTcpServer;
14 class QTcpSocket;
15 class FakeServer : public QObject
16 {
17     Q_OBJECT
18 
19 public:
20     FakeServer(QObject *parent = nullptr);
21     ~FakeServer() override;
22 
23     void setNextConversation(const QString &conversation, const QList<int> &exceptions = QList<int>());
24     void setAllowedDeletions(const QString &deleteIds);
25     void setAllowedRetrieves(const QString &retrieveIds);
26     void setMails(const QList<QByteArray> &mails);
27 
28     // This is kind of a hack: The POP3 test needs to know when the POP3 client
29     // disconnects from the server. Normally, we could just use a QSignalSpy on the
30     // disconnected() signal, but that is not thread-safe. Therefore this hack with the
31     // state variable mGotDisconnected
32     bool gotDisconnected() const;
33 
34     // Returns an integer that is incremented each time the POP3 server receives some
35     // data
36     int progress() const;
37 
38 Q_SIGNALS:
39     void disconnected();
40 
41 private Q_SLOTS:
42 
43     void newConnection();
44     void dataAvailable();
45     void slotDisconnected();
46 
47 private:
48     QByteArray parseDeleteMark(const QByteArray &expectedData, const QByteArray &dataReceived);
49     QByteArray parseRetrMark(const QByteArray &expectedData, const QByteArray &dataReceived);
50     QByteArray parseResponse(const QByteArray &expectedData, const QByteArray &dataReceived);
51 
52     QList<QByteArray> mReadData;
53     QList<QByteArray> mWriteData;
54     QList<QByteArray> mAllowedDeletions;
55     QList<QByteArray> mAllowedRetrieves;
56     QList<QByteArray> mMails;
57     QTcpServer *mTcpServer = nullptr;
58     QTcpSocket *mTcpServerConnection = nullptr;
59     int mConnections;
60     int mProgress;
61     bool mGotDisconnected = false;
62 
63     // We use one big mutex to protect everything
64     // There shouldn't be deadlocks, as there are only 2 places where the functions
65     // are called: From the KTcpSocket (or QSslSocket with KIO >= 5.65) signals, which
66     // are triggered by the POP3 ioslave, and from the actual test.
67     mutable QMutex mMutex;
68 };
69 
70 class FakeServerThread : public QThread
71 {
72     Q_OBJECT
73 
74 public:
75     explicit FakeServerThread(QObject *parent);
76     void run() override;
77 
78     // Returns the FakeServer use. Be careful when using this and make sure
79     // the methods you use are actually thread-safe!!
80     // This should however be the case because the FakeServer uses one big mutex
81     // to protect everything.
82     FakeServer *server() const;
83 
84 private:
85     FakeServer *mServer = nullptr;
86 };
87 
88