Commit b90847bd authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Restore ENABLED/QRESYNC implementation (Revert the reverts)

This reverts commit 6e1b0314.
This reverts commit d532cfe1.
This reverts commit c7c41224.
This reverts commit 36f9f6b8.
This reverts commit c3715b5e.
This reverts commit 88e3ee34.
parent b5c6f000
cmake_minimum_required(VERSION 3.5)
set(PIM_VERSION "5.15.80")
set(PIM_VERSION "5.15.81")
project(KIMAP VERSION ${PIM_VERSION})
......
......@@ -26,9 +26,11 @@ KIMAP_UNIT_TESTS(
loginjobtest
logoutjobtest
capabilitiesjobtest
closejobtest
selectjobtest
createjobtest
deletejobtest
enablejobtest
expungejobtest
fetchjobtest
renamejobtest
......
/*
SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <QTest>
#include "kimaptest/fakeserver.h"
#include "kimap/session.h"
#include "kimap/closejob.h"
#include <QTest>
class CloseJobTest: public QObject
{
Q_OBJECT
private Q_SLOTS:
void testClose_data()
{
QTest::addColumn<QList<QByteArray>>("scenario");
QTest::addColumn<quint64>("highestModSeq");
QList<QByteArray> scenario;
scenario << FakeServer::preauth()
<< "C: A000001 CLOSE"
<< "S: A000001 OK Closed";
QTest::newRow("good") << scenario << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 CLOSE"
<< "S: A000001 BAD No mailbox selected";
QTest::newRow("bad") << scenario << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 CLOSE"
<< "S: A000001 OK [HIGHESTMODSEQ 123456789] Closed.";
QTest::newRow("qresync") << scenario << 123456789ULL;
}
void testClose()
{
QFETCH(QList<QByteArray>, scenario);
QFETCH(quint64, highestModSeq);
FakeServer fakeServer;
fakeServer.setScenario(scenario);
fakeServer.startAndWait();
KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989);
auto *job = new KIMAP::CloseJob(&session);
bool result = job->exec();
QEXPECT_FAIL("bad" , "Expected failure on BAD response", Continue);
QVERIFY(result);
if (result) {
QCOMPARE(job->newHighestModSeq(), highestModSeq);
}
fakeServer.quit();
}
};
QTEST_GUILESS_MAIN(CloseJobTest)
#include "closejobtest.moc"
/*
SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <QTest>
#include "kimaptest/fakeserver.h"
#include "kimap/session.h"
#include "kimap/enablejob.h"
#include <QTest>
#include <QSignalSpy>
#include <QDebug>
Q_DECLARE_METATYPE(QList<QList<QByteArray>>)
class EnableJobTest: public QObject
{
Q_OBJECT
private Q_SLOTS:
void testEnable_data()
{
QTest::addColumn<QList<QByteArray>>("scenario");
QTest::addColumn<QStringList>("reqCapabilities");
QTest::addColumn<QStringList>("supportedCaps");
QList<QByteArray> scenario;
scenario << FakeServer::preauth()
<< "C: A000001 ENABLE CONDSTORE X-GOOD-IDEA"
<< "S: * ENABLED X-GOOD-IDEA"
<< "S: A000001 OK Enabled";
QStringList reqCapabilities = {QStringLiteral("CONDSTORE"), QStringLiteral("X-GOOD-IDEA")};
QStringList supportedCaps = {QStringLiteral("X-GOOD-IDEA")};
QTest::newRow("one feature") << scenario << reqCapabilities << supportedCaps;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 ENABLE FEATURE1 FEATURE2"
<< "S: * ENABLED FEATURE1 FEATURE2"
<< "S: A000001 OK Enabled";
reqCapabilities = QStringList{QStringLiteral("FEATURE1"), QStringLiteral("FEATURE2")};
supportedCaps = QStringList{QStringLiteral("FEATURE1"), QStringLiteral("FEATURE2")};
QTest::newRow("both features") << scenario << reqCapabilities << supportedCaps;
}
void testEnable()
{
QFETCH(QList<QByteArray>, scenario);
QFETCH(QStringList, reqCapabilities);
QFETCH(QStringList, supportedCaps);
FakeServer fakeServer;
fakeServer.setScenario(scenario);
fakeServer.startAndWait();
KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989);
auto *job = new KIMAP::EnableJob(&session);
job->setCapabilities(reqCapabilities);
QVERIFY(job->exec());
QCOMPARE(job->enabledCapabilities(), supportedCaps);
fakeServer.quit();
}
};
QTEST_GUILESS_MAIN(EnableJobTest)
#include "enablejobtest.moc"
......@@ -9,6 +9,7 @@
#include "kimaptest/fakeserver.h"
#include "kimap/session.h"
#include "kimap/expungejob.h"
#include "imapset.h"
#include <QTest>
......@@ -20,7 +21,9 @@ private Q_SLOTS:
void testDelete_data()
{
QTest::addColumn<QList<QByteArray> >("scenario");
QTest::addColumn<QList<QByteArray>>("scenario");
QTest::addColumn<KIMAP::ImapSet>("vanishedSet");
QTest::addColumn<quint64>("highestModSeq");
QList<QByteArray> scenario;
scenario << FakeServer::preauth()
......@@ -29,31 +32,43 @@ private Q_SLOTS:
<< "S: * 2 EXPUNGE"
<< "S: * 3 EXPUNGE"
<< "S: A000001 OK EXPUNGE completed";
QTest::newRow("good") << scenario;
QTest::newRow("good") << scenario << KIMAP::ImapSet{} << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 EXPUNGE"
<< "S: * 1" // missing EXPUNGE word
<< "S: A000001 OK EXPUNGE completed";
QTest::newRow("non-standard response") << scenario;
QTest::newRow("non-standard response") << scenario << KIMAP::ImapSet{} << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 EXPUNGE"
<< "S: A000001 BAD command unknown or arguments invalid";
QTest::newRow("bad") << scenario;
QTest::newRow("bad") << scenario << KIMAP::ImapSet{} << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 EXPUNGE"
<< "S: A000001 NO access denied";
QTest::newRow("no") << scenario;
QTest::newRow("no") << scenario << KIMAP::ImapSet{} << 0ULL;
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 EXPUNGE"
<< "S: * VANISHED 405,407,410:420"
<< "S: A000001 OK [HIGHESTMODSEQ 123456789] Expunged.";
KIMAP::ImapSet vanishedSet;
vanishedSet.add(KIMAP::ImapInterval{405, 407});
vanishedSet.add(KIMAP::ImapInterval{410, 420});
QTest::newRow("qresync") << scenario << vanishedSet << 123456789ULL;
}
void testDelete()
{
QFETCH(QList<QByteArray>, scenario);
QFETCH(KIMAP::ImapSet, vanishedSet);
QFETCH(quint64, highestModSeq);
FakeServer fakeServer;
fakeServer.setScenario(scenario);
......@@ -66,6 +81,10 @@ private Q_SLOTS:
QEXPECT_FAIL("bad" , "Expected failure on BAD response", Continue);
QEXPECT_FAIL("no" , "Expected failure on NO response", Continue);
QVERIFY(result);
if (result) {
QCOMPARE(job->vanishedMessages(), vanishedSet);
QCOMPARE(job->newHighestModSeq(), highestModSeq);
}
fakeServer.quit();
}
......
......@@ -12,6 +12,7 @@
#include "kimap/fetchjob.h"
#include <QTest>
#include <QSignalSpy>
Q_DECLARE_METATYPE(KIMAP::FetchJob::FetchScope)
......@@ -19,6 +20,12 @@ class FetchJobTest: public QObject
{
Q_OBJECT
public:
FetchJobTest()
{
qRegisterMetaType<KIMAP::ImapSet>();
}
private:
QStringList m_signals;
......@@ -80,10 +87,11 @@ private Q_SLOTS:
qRegisterMetaType<KIMAP::FetchJob::FetchScope>();
QTest::addColumn<bool>("uidBased");
QTest::addColumn< KIMAP::ImapSet >("set");
QTest::addColumn<KIMAP::ImapSet>("set");
QTest::addColumn<int>("expectedMessageCount");
QTest::addColumn< QList<QByteArray> >("scenario");
QTest::addColumn<QList<QByteArray>>("scenario");
QTest::addColumn<KIMAP::FetchJob::FetchScope>("scope");
QTest::addColumn<KIMAP::ImapSet>("expectedVanished");
KIMAP::FetchJob::FetchScope scope;
scope.mode = KIMAP::FetchJob::FetchScope::Flags;
......@@ -99,7 +107,7 @@ private Q_SLOTS:
<< "S: A000001 OK fetch done";
QTest::newRow("messages have empty flags (with changedsince)") << false << KIMAP::ImapSet(1, 4) << 4
<< scenario << scope;
<< scenario << scope << KIMAP::ImapSet{};
scenario.clear();
scope.changedSince = 0;
......@@ -112,7 +120,7 @@ private Q_SLOTS:
<< "S: A000001 OK fetch done";
QTest::newRow("messages have empty flags") << false << KIMAP::ImapSet(1, 4) << 4
<< scenario << scope;
<< scenario << scope << KIMAP::ImapSet{};
scenario.clear();
// kill the connection part-way through a list, with carriage returns at end
......@@ -124,7 +132,7 @@ private Q_SLOTS:
<< "S: From: John Smith <jonathanr.smith@foobarbaz.com>\r\nTo: \"amagicemailaddress@foobarbazbarfoo.com\"\r\n\t<amagicemailaddress@foobarbazbarfoo.com>\r\nDate: Mon, 11 Oct 2010 03:34:48 +0100\r\nSubject: unsubscribe\r\nMessage-ID: <ASDFFDSASDFFDS@foobarbaz.com>\r\n\r\n"
<< "X";
scope.mode = KIMAP::FetchJob::FetchScope::Headers;
QTest::newRow("connection drop") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope;
QTest::newRow("connection drop") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{};
scenario.clear();
// Important bit here if "([127.0.0.1])" which used to crash the stream parser
......@@ -134,7 +142,7 @@ private Q_SLOTS:
<< "S: ([127.0.0.1])\r\nDate: Mon, 11 Oct 2010 03:34:48 +0100\r\nSubject: unsubscribe\r\nMessage-ID: <ASDFFDSASDFFDS@foobarbaz.com>\r\n\r\n"
<< "X";
scope.mode = KIMAP::FetchJob::FetchScope::Headers;
QTest::newRow("buffer overwrite") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope;
QTest::newRow("buffer overwrite") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{};
scenario.clear();
// We're assuming a buffer overwrite here which made us miss the opening parenthesis
......@@ -144,7 +152,7 @@ private Q_SLOTS:
<< "S: * 11 FETCH {10}doh!\r\n\r\n\r\n)\r\n"
<< "X";
scope.mode = KIMAP::FetchJob::FetchScope::Headers;
QTest::newRow("buffer overwrite 2") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope;
QTest::newRow("buffer overwrite 2") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{};
scenario.clear();
scenario << FakeServer::preauth()
......@@ -155,7 +163,24 @@ private Q_SLOTS:
scope.mode = KIMAP::FetchJob::FetchScope::FullHeaders;
scope.changedSince = 123456789;
QTest::newRow("fetch full headers") << false << KIMAP::ImapSet(11, 11) << 1
<< scenario << scope;
<< scenario << scope << KIMAP::ImapSet{};
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 UID FETCH 300:500 (FLAGS UID) (CHANGEDSINCE 12345 VANISHED)"
<< "S: * VANISHED (EARLIER) 300:310,405,411"
<< "S: * 1 FETCH (UID 404 MODSEQ (65402) FLAGS (\\Seen))"
<< "S: * 2 FETCH (UID 406 MODSEQ (75403) FLAGS (\\Deleted))"
<< "S: * 4 FETCH (UID 408 MODSEQ (29738) FLAGS ($Nojunk $AutoJunk $MDNSent))"
<< "S: A000001 OK Fetch completed";
scope.mode = KIMAP::FetchJob::FetchScope::Flags;
scope.changedSince = 12345;
scope.qresync = true;
KIMAP::ImapSet vanished;
vanished.add(KIMAP::ImapInterval{300, 310});
vanished.add(KIMAP::ImapInterval{405, 411});
QTest::newRow("qresync") << true << KIMAP::ImapSet(300, 500) << 3 << scenario << scope << vanished;
}
void testFetch()
......@@ -165,6 +190,7 @@ private Q_SLOTS:
QFETCH(int, expectedMessageCount);
QFETCH(QList<QByteArray>, scenario);
QFETCH(KIMAP::FetchJob::FetchScope, scope);
QFETCH(KIMAP::ImapSet, expectedVanished);
FakeServer fakeServer;
fakeServer.setScenario(scenario);
......@@ -192,6 +218,9 @@ private Q_SLOTS:
connect(job, &KIMAP::FetchJob::messagesAvailable,
this, &FetchJobTest::onMessagesAvailable);
QSignalSpy vanishedSpy(job, &KIMAP::FetchJob::messagesVanished);
QVERIFY(vanishedSpy.isValid());
bool result = job->exec();
QEXPECT_FAIL("connection drop", "Expected failure on connection drop", Continue);
QEXPECT_FAIL("buffer overwrite", "Expected failure on confused list", Continue);
......@@ -201,6 +230,10 @@ private Q_SLOTS:
QVERIFY(m_signals.count() > 0);
QCOMPARE(m_uids.count(), expectedMessageCount);
QCOMPARE(m_msgs.count(), expectedMessageCount);
if (scope.qresync) {
QCOMPARE(vanishedSpy.size(), 1);
QCOMPARE(vanishedSpy.at(0).at(0).value<KIMAP::ImapSet>(), expectedVanished);
}
}
QVERIFY(fakeServer.isAllScenarioDone());
......
......@@ -9,22 +9,36 @@
#include <QSslConfiguration>
#include <QDebug>
// Generated on 2020-10-07 using command:
// openssl req -nodes -new -x509 -keyout key.pem -out cert.pem -days 36500
//
// The cert should be valid until 2120.
static QByteArray staticCert()
{
//a dummy certificate
return QByteArray(
"-----BEGIN CERTIFICATE-----\n\
MIIB+zCCAWQCCQDBBi7xZ2944DANBgkqhkiG9w0BAQUFADBCMQswCQYDVQQGEwJY\n\
WDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBh\n\
bnkgTHRkMB4XDTEzMTIwNTA5MDcxNVoXDTQxMDQyMjA5MDcxNVowQjELMAkGA1UE\n\
BhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBD\n\
b21wYW55IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyuZdeqTgzX2E\n\
Q+tOj8/QzT8jHOUvwleqv56hAOEbZ5pLhYPesaSqV0lADiYHKjCRVIrhJQXePf7y\n\
MrJ3zE6hbHEMoIj+ku6ttNQkfJif30wmbXxLXO+RqraYgJW730kcbi2Jyq7ciEC1\n\
SVeiIaaiV2yUFBc/ARDFBc7733Y053UCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAE\n\
BmB+mGtQzdmOAPbRYegA2ybuUARnW467qMOQpj5dV2LN+bizCbqrsz2twFKWS7oK\n\
EiC1bd6EGHnF6inFksUwODqeb+rjQ85pFBWskG51LWvX2/hoS+0x2V37vUYMxnDH\n\
rOEQiDe3oerErB0x9FMWk7VivEqO5HGEdxy7fGl3vg==\n\
"-----BEGIN CERTIFICATE-----\n\
MIIDZzCCAk+gAwIBAgIUQoBjjbd//7DD9zWfru/epnVT2vAwDQYJKoZIhvcNAQEL\n\
BQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE\n\
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDAgFw0yMDEwMDcxMzMxMTJaGA8yMTIwMDkx\n\
MzEzMzExMlowQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEc\n\
MBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQAD\n\
ggEPADCCAQoCggEBAMIu0Osija2bIINdCjuP0T+tdlQOI8l52J+z/dI45MxecEn5\n\
LAsYWhqanpgZSM5tFf4xqWaX/1/TVDB5JiLx3voWOODTtNKzFVFCzfKHuH6cBboE\n\
E4TZ+H6hTq+YyMKUDN7XqRtBIf1FBf0lMhalWdtEDtlXcsuoaGXkr671JwR34+EU\n\
6YH/8kbBQQBoL640/gxtgevGmpqfqLW0/hogF5pOhMOfwVlYo28IqaPScUGEpopf\n\
zqL+z6NwdEsNLygwq21kU0hhRnx2UgdPcZNX3dc7sUkZjxn53t6XPeVvgGXCte1o\n\
Ad6L0rMunlda+Tj02FXn7jo6G7ELj05Bg8JNB8sCAwEAAaNTMFEwHQYDVR0OBBYE\n\
FLi6xsBAkbc06veA7t+8slAUCVebMB8GA1UdIwQYMBaAFLi6xsBAkbc06veA7t+8\n\
slAUCVebMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFpcIzOl\n\
iqMK/kre/xJyE+S1UoS85rmegZDkNdEXUS6zCozL+eO2NxHxumxfD3qrdwLvXfn0\n\
y30xUlNecB30/egXrel9z7Xop70sVCfgfb/vfMmQ5KSUZC8968rgHPl5qPmjZk6X\n\
z0M9hktTRpIk43DPuz5k1qD+LsmrKzI7twGu00EenwVZa4eLN36Ju4ZRg3I0h2zH\n\
vAnuAku0F0JU9GXdbjOW/248k+jhMP1noDaLqwVkkjgzaJwHxFNiKxnG3f7anneK\n\
HxybczmNl3a6IsZN0CSUSwLfvr1Wezk2Mb7dwzhPbycP5icB/KXWgApkRZ3MKfLN\n\
aBvBMCfr7GXmLQk=\n\
-----END CERTIFICATE-----");
}
......@@ -32,21 +46,34 @@ static QByteArray staticKey()
{
//a dummy key without password
return QByteArray(
"-----BEGIN RSA PRIVATE KEY-----\n\
MIICXgIBAAKBgQDK5l16pODNfYRD606Pz9DNPyMc5S/CV6q/nqEA4RtnmkuFg96x\n\
pKpXSUAOJgcqMJFUiuElBd49/vIysnfMTqFscQygiP6S7q201CR8mJ/fTCZtfEtc\n\
75GqtpiAlbvfSRxuLYnKrtyIQLVJV6IhpqJXbJQUFz8BEMUFzvvfdjTndQIDAQAB\n\
AoGBAIdNfXLGtl5x4BzGspn2NEBaZRjkwKdxfJzRtH34nyTEYK5FVODTdQBGCaAl\n\
vctlndRp1F+y/RQMighCuN6WZM/SdkzxkGGJVzDDuMw0Cwc48aqtMA3A3x/3bQkK\n\
kk2A5sLBc1TuC4DYSP5zkoXDbvBsHHN+tGAaC348Df6of1J1AkEA7ye3W9JUN4uK\n\
2cPrnh7EKwQ2pFypeE/UNQ+LXR9h8XK90mxwiShU9sRFlNIA+pPcZ2aBxoY9m3rJ\n\
4GHitl4ajwJBANkw6xM9IdgjMD8OQonpZTHSrKki/MaSSe9eBJ+WiCkTKL+Y9aTm\n\
28sU7I+j3V38kYf5zyWXkyWmmNaQ4VaU77sCQQDMx7BM0qPEUBtb7lQxt9x3jQsQ\n\
4DtIxupJaP8HhRjDu2Fo7evKthtSlauTC+NErRl7/J1BFa9pE9IK7SZIy/lnAkB6\n\
ssga9k5IbJi1BrlQcCpbG0mvw7RJ+hsKv3KdNc12Zvx+QUuE/WbuM8Pw4gINNsKA\n\
rv/3nMnkW1m83dxvrXRBAkEAmy3nO9HXdcKtSseseLJ6h9RB/R0XE1EvG8CKvveS\n\
IiVUnppVeiLFa7ItwHOovgqvWVbePd5xl6+yBGxUXznjWA==\n\
-----END RSA PRIVATE KEY-----");
"-----BEGIN PRIVATE KEY-----\n\
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCLtDrIo2tmyCD\n\
XQo7j9E/rXZUDiPJedifs/3SOOTMXnBJ+SwLGFoamp6YGUjObRX+Malml/9f01Qw\n\
eSYi8d76Fjjg07TSsxVRQs3yh7h+nAW6BBOE2fh+oU6vmMjClAze16kbQSH9RQX9\n\
JTIWpVnbRA7ZV3LLqGhl5K+u9ScEd+PhFOmB//JGwUEAaC+uNP4MbYHrxpqan6i1\n\
tP4aIBeaToTDn8FZWKNvCKmj0nFBhKaKX86i/s+jcHRLDS8oMKttZFNIYUZ8dlIH\n\
T3GTV93XO7FJGY8Z+d7elz3lb4BlwrXtaAHei9KzLp5XWvk49NhV5+46OhuxC49O\n\
QYPCTQfLAgMBAAECggEAFdV/xkCfX5rmv/6RLPtR0vAlMvRYD8p0khiB/MZK67Pe\n\
umKbEjBNyVoDZSTKq/NWGrvoyVFj9JlliQHGSP2bTdF72cPUPDDIv9dcIt4h35KZ\n\
jj3xF+oOZ+apW1M5l69f9xqWuCrNsJW3Q6yQAj3baa0wYj3T+ZRZEMPzASAtn/HM\n\
8r/ToZ9jzObVeNAKoHy30bn5a5NwUcpdOfj84l/qJalXEMtR05FTOa+UEjbqpxjM\n\
+HR9RhlLyxXoFkBjtBowEWZcJSik7t5Vpk4brhUZTVxR1bC5zAXxtnDg2SmR9bKO\n\
4wttLEtTTrXeTkxpYMTZWt7FplUmP92RdcW8PCbe2QKBgQDl+QYUhaQdmRC1ylny\n\
2XP0lvPBHQr7jIHYcsGgit7XKMu6wSq/NGuLNT7WL1A9UDWBCdsdqXBFjR3rwhzh\n\
krbymy1H6PGPYYMQg0DeoAG7I1YTYhrp25bO0WTXVyYrhbZiQkFontUFYIbqu+Rf\n\
glVnhEXXN6wXBjY1F0qM4KjydQKBgQDYKNspAaxX/GxnydtlxXTXWSKD/kMlbAeu\n\
+AI9PRn6LckT7pKEE4Qd/gHnrlnxlqgLTJDcGgTeNutHmaHToQNSWiNltr7igzsU\n\
nABUwlNpl2NwUqttCvsGcyxhabDIjO6Iw+jbnLsWwyMzwf/5YaP8wwmznWYDGn6Y\n\
UXbyXn5JPwKBgQCzHM/qfefDkaqdG/wQk+KnFkbFGnyqTNX4ofBCvMYwp7p9OuOz\n\
Rf2Yz6CgKvuAtY7mcKmzIXuq/+zU6TubSKyqqceLoVc6iAUPgFquycpvWWc584fo\n\
qjl73USAH4VAEoVpZBcTh9l7taF/A1YsORORa0kGBXtH93OSyBAtRvDu3QKBgHZm\n\
2rU5f2eqks6/GPhEEl4rKubWDX2gEQ1cOA3HPEV3ct8CHStPbVzoV67KJ+ZXObEG\n\
vYpyjhwSRQoxMx0y4xjm2uDKGwEEFQaS9PN4hiweio9qGRBfpWTBDZxGQll4KOit\n\
Nw2kai5rsQqWx1mYjDTVuKi0HL6ycomIhfj4nYANAoGATXXc8Ekg+w7hfzLS3BTV\n\
SovH/d6/fC5B7nD5+wB7s0dD8NqqOUKvRm/HPRzMWejSOMXWQzpWSAGTheaFArTw\n\
2k6FDQ7S1lEt6jbVBtS189LtaZBnEWZQfyjKl8h6lJyVU2kBfaYoEOO31T8n20sG\n\
NdkmACeCyNMs5V3yq1vAeN4=\n\
-----END PRIVATE KEY-----");
}
SslServer::SslServer(QSsl::SslProtocol protocol, bool waitForStartTls)
......
......@@ -15,11 +15,26 @@
#include "kimap/selectjob.h"
#include <QTest>
#include <QSignalSpy>
using Messages = QMap<qint64, KIMAP::Message>;
Q_DECLARE_METATYPE(KIMAP::Message)
Q_DECLARE_METATYPE(Messages)
class SelectJobTest: public QObject
{
Q_OBJECT
public:
explicit SelectJobTest()
{
qRegisterMetaType<KIMAP::ImapSet>();
qRegisterMetaType<KIMAP::Message>();
qRegisterMetaType<QMap<qint64, KIMAP::Message>>("QMap<qint64,KIMAP::Message>");
}
private Q_SLOTS:
void testSingleSelect_data()
......@@ -35,6 +50,11 @@ private Q_SLOTS:
QTest::addColumn<quint64>("highestmodseq");
QTest::addColumn<bool>("condstoreEnabled");
QTest::addColumn<bool>("readonly");
QTest::addColumn<qint64>("lastUidvalidity");
QTest::addColumn<quint64>("lastModseq");
QTest::addColumn<KIMAP::ImapSet>("vanished");
QTest::addColumn<Messages>("modified");
QList<QByteArray> scenario;
QList<QByteArray> flags;
......@@ -53,7 +73,8 @@ private Q_SLOTS:
flags << "\\Answered" << "\\Flagged" << "\\Deleted" << "\\Seen" << "\\Draft";
permanentflags << "\\Deleted" << "\\Seen" << "\\*";
QTest::newRow("good") << scenario << flags << permanentflags << 172 << 1 << 12 << (qint64)3857529045 << (qint64)4392 << (quint64)123456789 << true << false;
QTest::newRow("good") << scenario << flags << permanentflags << 172 << 1 << 12 << 3857529045LL << 4392LL << 123456789ULL << true << false
<< -1LL << 0ULL << KIMAP::ImapSet{} << Messages{};
scenario.clear();
flags.clear();
......@@ -61,7 +82,8 @@ private Q_SLOTS:
scenario << FakeServer::preauth()
<< "C: A000001 SELECT \"INBOX\""
<< "S: A000001 BAD command unknown or arguments invalid";
QTest::newRow("bad") << scenario << flags << permanentflags << 0 << 0 << 0 << (qint64)0 << (qint64)0 << (quint64)0 << false << false;
QTest::newRow("bad") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false
<< -1LL << 0ULL << KIMAP::ImapSet{} << Messages{};
scenario.clear();
flags.clear();
......@@ -69,7 +91,40 @@ private Q_SLOTS:
scenario << FakeServer::preauth()
<< "C: A000001 SELECT \"INBOX\""
<< "S: A000001 NO select failure";
QTest::newRow("no") << scenario << flags << permanentflags << 0 << 0 << 0 << (qint64)0 << (qint64)0 << (quint64)0 << false << false;
QTest::newRow("no") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false
<< -1LL << 0ULL << KIMAP::ImapSet{} << Messages{};
scenario.clear();
scenario << FakeServer::preauth()
<< "C: A000001 SELECT \"INBOX\" (QRESYNC (67890007 90060115194045000))"
<< "S: * 314 EXISTS"
<< "S: * 15 RECENT"
<< "S: * OK [UIDVALIDITY 67890007] UIDVALIDITY"
<< "S: * OK [UIDNEXT 567] Predicted next UID"
<< "S: * OK [HIGHESTMODSEQ 90060115205545359]"
<< "S: * OK [UNSEEN 7] There are some unseen messages in the mailbox"
<< "S: * FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)"
<< "S: * OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen \\*)] Permanent flags"
<< "S: * VANISHED (EARLIER) 41,43:116,118,120:211,214:540"
<< "S: * 49 FETCH (UID 117 FLAGS (\\Seen \\Answered) MODSEQ (90060115194045001))"
<< "S: * 50 FETCH (UID 119 FLAGS (\\Draft $MDNSent) MODSEQ (90060115194045308))"
<< "S: * 100 FETCH (UID 541 FLAGS (\\Seen $Forwarded) MODSEQ (90060115194045001))"
<< "S: A000001 OK [READ-WRITE] mailbox selected";
permanentflags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen", "\\*"};
flags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen"};
KIMAP::ImapSet vanished;
vanished.add(41);
vanished.add(KIMAP::ImapInterval{43, 116});
vanished.add(118);
vanished.add(KIMAP::ImapInterval{120, 211});
vanished.add(KIMAP::ImapInterval{214, 540});
Messages modified = {
{49, KIMAP::Message{117, 0, {"\\Seen", "\\Answered"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}},
{50, KIMAP::Message{119, 0, {"\\Draft", "$MDNSent"}, {{"MODSEQ", QVariant{90060115194045308ULL}}}, {}, {}}},
{100, KIMAP::Message{541, 0, {"\\Seen", "$Forwarded"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}}
};
QTest::newRow("QResync") << scenario << flags << permanentflags << 314 << 15 << 7 << 67890007LL << 567LL << 90060115205545359ULL << false << false
<< 67890007LL << 90060115194045000ULL << vanished << modified;
}
void testSingleSelect()
......@@ -84,6 +139,10 @@ private Q_SLOTS:
QFETCH(qint64, nextUid);
QFETCH(quint64, highestmodseq);
QFETCH(bool, condstoreEnabled);
QFETCH(qint64, lastUidvalidity);
QFETCH(quint64, lastModseq);
QFETCH(KIMAP::ImapSet, vanished);
QFETCH(Messages, modified);
FakeServer fakeServer;
fakeServer.setScenario(scenario);
......@@ -94,6 +153,16 @@ private Q_SLOTS:
auto *job = new KIMAP::SelectJob(&session);
job->setCondstoreEnabled(condstoreEnabled);
job->setMailBox(QStringLiteral("INBOX"));
if (lastUidvalidity > -1 && lastModseq > 0) {
job->setQResync(lastUidvalidity, lastModseq);
}
QSignalSpy vanishedSpy(job, &KIMAP::SelectJob::vanished);
QVERIFY(vanishedSpy.isValid());
QSignalSpy modifiedSpy(job, &KIMAP::SelectJob::modified);
QVERIFY(modifiedSpy.isValid());
bool result = job->exec();
QEXPECT_FAIL("bad" , "Expected failure on BAD scenario", Continue);
QEXPECT_FAIL("no" , "Expected failure on NO scenario", Continue);
......@@ -107,6 +176,23 @@ private Q_SLOTS:
QCOMPARE(job->uidValidity(), uidValidity);
QCOMPARE(job->nextUid(), nextUid);
QCOMPARE(job->highestModSequence(), highestmodseq);