File indexing completed on 2024-05-12 05:17:19

0001 /*
0002    Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003    Author: Kevin Ottens <kevin@kdab.com>
0004 
0005    This program is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This program is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    General Public License for more details.
0014 
0015    You should have received a copy of the GNU General Public License
0016    along with this program; if not, write to the Free Software
0017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include <qtest.h>
0021 
0022 #include "kimap2test/fakeserver.h"
0023 #include "kimap2/session.h"
0024 #include "kimap2/selectjob.h"
0025 #include "kimap2/idlejob.h"
0026 
0027 #include <QtTest>
0028 
0029 Q_DECLARE_METATYPE(QList<int>)
0030 Q_DECLARE_METATYPE(QList<qint64>)
0031 Q_DECLARE_METATYPE(KIMAP2::IdleJob *)
0032 
0033 class IdleJobTest: public QObject
0034 {
0035     Q_OBJECT
0036 
0037 public:
0038     explicit IdleJobTest(QObject *parent = nullptr)
0039         : QObject(parent)
0040     {
0041         qRegisterMetaType<KIMAP2::IdleJob *>();
0042     }
0043 
0044 private Q_SLOTS:
0045     void shouldReactToIdle_data()
0046     {
0047         QTest::addColumn<QList<QByteArray> >("scenario");
0048         QTest::addColumn<QString>("expectedMailBox");
0049         QTest::addColumn< QList<int> >("expectedMessageCounts");
0050         QTest::addColumn< QList<int> >("expectedRecentCounts");
0051         QTest::addColumn< QList<qint64> >("expectedFlagsNotifications");
0052 
0053         QList<QByteArray> scenario;
0054         QString expectedMailBox;
0055         QList<int> expectedMessageCounts;
0056         QList<int> expectedRecentCounts;
0057         QList<qint64> expectedFlagsNotifications;
0058 
0059         scenario.clear();
0060         scenario << FakeServer::preauth()
0061                  << "C: A000001 SELECT \"INBOX/Foo\""
0062                  << "S: A000001 OK SELECT done"
0063                  << "C: A000002 IDLE"
0064                  << "S: + OK"
0065                  << "S: * 0 RECENT"
0066                  << "S: * 1 EXISTS"
0067                  << "S: * 1 RECENT"
0068                  << "S: * 2 EXISTS"
0069                  << "S: A000002 OK done idling";
0070 
0071         expectedMailBox = QStringLiteral("INBOX/Foo");
0072 
0073         expectedMessageCounts.clear();
0074         expectedRecentCounts.clear();
0075 
0076         expectedMessageCounts << 1 << 2;
0077         expectedRecentCounts << 0 << 1;
0078 
0079         QTest::newRow("normal") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0080 
0081         scenario.clear();
0082         scenario << FakeServer::preauth()
0083                  << "C: A000001 SELECT \"INBOX/Foo\""
0084                  << "S: A000001 OK SELECT done"
0085                  << "C: A000002 IDLE"
0086                  << "S: + OK"
0087                  << "S: * 0 RECENT"
0088                  << "S: * 1 RECENT"
0089                  << "S: A000002 OK done idling";
0090 
0091         expectedMailBox = QStringLiteral("INBOX/Foo");
0092 
0093         expectedMessageCounts.clear();
0094         expectedRecentCounts.clear();
0095 
0096         expectedMessageCounts << -1 << -1;
0097         expectedRecentCounts << 0 << 1;
0098 
0099         QTest::newRow("only RECENT") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0100 
0101         scenario.clear();
0102         scenario << FakeServer::preauth()
0103                  << "C: A000001 SELECT \"INBOX/Foo\""
0104                  << "S: A000001 OK SELECT done"
0105                  << "C: A000002 IDLE"
0106                  << "S: + OK"
0107                  << "S: * 1 EXISTS"
0108                  << "S: * 2 EXISTS"
0109                  << "S: A000002 OK done idling";
0110 
0111         expectedMailBox = QStringLiteral("INBOX/Foo");
0112 
0113         expectedMessageCounts.clear();
0114         expectedRecentCounts.clear();
0115 
0116         expectedMessageCounts << 1 << 2;
0117         expectedRecentCounts << -1 << -1;
0118 
0119         QTest::newRow("only EXISTS") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0120 
0121         scenario.clear();
0122         scenario << FakeServer::preauth()
0123                  << "C: A000001 SELECT \"INBOX/Foo\""
0124                  << "S: A000001 OK SELECT done"
0125                  << "C: A000002 IDLE"
0126                  << "S: + OK"
0127                  << "S: * 2 EXISTS"
0128                  << "W: 150"
0129                  << "S: * 1 RECENT"
0130                  << "S: A000002 OK done idling";
0131 
0132         expectedMailBox = QStringLiteral("INBOX/Foo");
0133 
0134         expectedMessageCounts.clear();
0135         expectedRecentCounts.clear();
0136 
0137         expectedMessageCounts << 2;
0138         expectedRecentCounts << 1;
0139 
0140         QTest::newRow("under 200ms, same notification") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0141 
0142         scenario.clear();
0143         scenario << FakeServer::preauth()
0144                  << "C: A000001 SELECT \"INBOX/Foo\""
0145                  << "S: A000001 OK SELECT done"
0146                  << "C: A000002 IDLE"
0147                  << "S: + OK"
0148                  << "S: * 2 EXISTS"
0149                  << "W: 250"
0150                  << "S: * 1 RECENT"
0151                  << "S: A000002 OK done idling";
0152 
0153         expectedMailBox = QStringLiteral("INBOX/Foo");
0154 
0155         expectedMessageCounts.clear();
0156         expectedRecentCounts.clear();
0157 
0158         expectedMessageCounts << 2 << -1;
0159         expectedRecentCounts << -1 << 1;
0160 
0161         QTest::newRow("above 200ms, two notifications") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0162 
0163         scenario.clear();
0164         scenario << FakeServer::preauth()
0165                  << "C: A000001 SELECT \"INBOX/Foo\""
0166                  << "S: A000001 OK SELECT done"
0167                  << "C: A000002 IDLE"
0168                  << "S: + OK"
0169                  << "S: * 1 FETCH (FLAGS ())"
0170                  << "W: 200"
0171                  << "S: * 2 FETCH (FLAGS (\\Seen))"
0172                  << "S: A000002 OK done idling";
0173 
0174         expectedMailBox = QStringLiteral("INBOX/Foo");
0175 
0176         expectedMessageCounts.clear();
0177         expectedRecentCounts.clear();
0178         expectedFlagsNotifications << 1 << 2;
0179 
0180         QTest::newRow("2 flags change notifications") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications;
0181     }
0182 
0183     void shouldReactToIdle()
0184     {
0185         QFETCH(QList<QByteArray>, scenario);
0186         QFETCH(QString, expectedMailBox);
0187         QFETCH(QList<int>, expectedMessageCounts);
0188         QFETCH(QList<int>, expectedRecentCounts);
0189         QFETCH(QList<qint64>, expectedFlagsNotifications);
0190 
0191         QVERIFY(expectedMessageCounts.size() == expectedRecentCounts.size());
0192 
0193         FakeServer fakeServer;
0194         fakeServer.setScenario(scenario);
0195         fakeServer.startAndWait();
0196 
0197         KIMAP2::Session session(QStringLiteral("127.0.0.1"), 5989);
0198 
0199         KIMAP2::SelectJob *select = new KIMAP2::SelectJob(&session);
0200         select->setMailBox(expectedMailBox);
0201         QVERIFY(select->exec());
0202 
0203         KIMAP2::IdleJob *idle = new KIMAP2::IdleJob(&session);
0204 
0205         QSignalSpy statsSpy(idle, SIGNAL(mailBoxStats(KIMAP2::IdleJob*,QString,int,int)));
0206         QSignalSpy flagsSpy(idle, SIGNAL(mailBoxMessageFlagsChanged(KIMAP2::IdleJob*,qint64)));
0207 
0208         bool result = idle->exec();
0209 
0210         if (result) {
0211             QCOMPARE(statsSpy.count(), expectedMessageCounts.size());
0212             QCOMPARE(flagsSpy.count(), expectedFlagsNotifications.size());
0213 
0214             for (int i = 0 ; i < statsSpy.count(); i++) {
0215                 const KIMAP2::IdleJob *job = statsSpy.at(i).at(0).value<KIMAP2::IdleJob *>();
0216                 const QString mailBox = statsSpy.at(i).at(1).toString();
0217                 const int messageCount = statsSpy.at(i).at(2).toInt();
0218                 const int recentCount = statsSpy.at(i).at(3).toInt();
0219 
0220                 QCOMPARE(job, idle);
0221                 QCOMPARE(mailBox, expectedMailBox);
0222                 QCOMPARE(messageCount, expectedMessageCounts.at(i));
0223                 QCOMPARE(recentCount, expectedRecentCounts.at(i));
0224             }
0225 
0226             for (int i = 0; i < flagsSpy.count(); i++) {
0227                 const KIMAP2::IdleJob *job = flagsSpy.at(i).at(0).value<KIMAP2::IdleJob *>();
0228                 const qint64 uid = flagsSpy.at(i).at(1).toLongLong();
0229 
0230                 QCOMPARE(job, idle);
0231                 QCOMPARE(uid, expectedFlagsNotifications.at(i));
0232             }
0233         }
0234 
0235         fakeServer.quit();
0236     }
0237 
0238     void shouldResetTimeout_data()
0239     {
0240         QTest::addColumn<QList<QByteArray> >("scenario");
0241         {
0242             QList<QByteArray> scenario;
0243             scenario << FakeServer::preauth()
0244                      << "C: A000001 SELECT \"INBOX\""
0245                      << "S: A000001 OK SELECT done"
0246                      << "C: A000002 IDLE"
0247                      << "S: + OK"
0248                      << "S: A000002 OK done idling";
0249 
0250             QTest::newRow("good") << scenario;
0251         }
0252 
0253         {
0254             QList<QByteArray> scenario;
0255             scenario << FakeServer::preauth()
0256                      << "C: A000001 SELECT \"INBOX\""
0257                      << "S: A000001 OK SELECT done"
0258                      << "C: A000002 IDLE"
0259                      << "S: + OK"
0260                      << "X";
0261 
0262             QTest::newRow("bad") << scenario;
0263         }
0264     }
0265 
0266     void shouldResetTimeout()
0267     {
0268         QFETCH(QList<QByteArray>, scenario);
0269 
0270         FakeServer fakeServer;
0271         fakeServer.setScenario(scenario);
0272         fakeServer.startAndWait();
0273 
0274         KIMAP2::Session session(QStringLiteral("127.0.0.1"), 5989);
0275         const int originalTimeout = session.timeout();
0276 
0277         KIMAP2::SelectJob *select = new KIMAP2::SelectJob(&session);
0278         select->setMailBox(QStringLiteral("INBOX"));
0279         QVERIFY(select->exec());
0280 
0281         KIMAP2::IdleJob *idle = new KIMAP2::IdleJob(&session);
0282         idle->exec();
0283 
0284         QCOMPARE(session.timeout(), originalTimeout);
0285 
0286         fakeServer.quit();
0287     }
0288 
0289 };
0290 
0291 QTEST_GUILESS_MAIN(IdleJobTest)
0292 
0293 #include "idlejobtest.moc"