/** short A fetching operation gets interrupted by switching to the offline mode */ void ImapMsgPartNetAccessManagerTest::testFetchResultOfflineSingle() { COMMON_METADATA_CHAT_PLAIN_AND_SIGNED netAccessManager->setModelMessage(msg1); QNetworkRequest req; req.setUrl(QUrl(QLatin1String("trojita-imap://msg/0"))); QNetworkReply *res = netAccessManager->get(req); QVERIFY(qobject_cast<Imap::Network::MsgPartNetworkReply*>(res)); cClient(t.mk("UID FETCH 1 (BODY.PEEK[1])\r\n")); QPersistentModelIndex msg1p1 = msgListA.child(0, 0).child(0, 0); QVERIFY(msg1p1.isValid()); QCOMPARE(msg1p1.data(Imap::Mailbox::RoleMessageUid), QVariant(1u)); QCOMPARE(msg1p1.data(Imap::Mailbox::RoleIsFetched), QVariant(false)); QCOMPARE(msg1p1.data(Imap::Mailbox::RoleIsUnavailable), QVariant(false)); networkPolicy->setNetworkOffline(); cClient(t.mk("LOGOUT\r\n")); cServer(t.last("OK logged out\r\n") + "* BYE eh\r\n"); QCOMPARE(msg1p1.data(Imap::Mailbox::RoleIsFetched), QVariant(false)); QCOMPARE(msg1p1.data(Imap::Mailbox::RoleIsUnavailable), QVariant(true)); #if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) QCOMPARE(res->isFinished(), true); #endif QCOMPARE(res->error(), QNetworkReply::TimeoutError); }
/** @short What happens when ENVELOPE doesn't arrive at the time that parts are already there? */ void CryptographyPGPTest::testDecryptWithoutEnvelope() { #ifdef TROJITA_HAVE_CRYPTO_MESSAGES model->setProperty("trojita-imap-delayed-fetch-part", 0); helperSyncBNoMessages(); cServer("* 1 EXISTS\r\n"); cClient(t.mk("UID FETCH 1:* (FLAGS)\r\n")); cServer("* 1 FETCH (UID 333 FLAGS ())\r\n" + t.last("OK fetched\r\n")); QCOMPARE(model->rowCount(msgListB), 1); QModelIndex msg = msgListB.child(0, 0); QVERIFY(msg.isValid()); Cryptography::MessageModel msgModel(0, msg); msgModel.registerPartHandler(std::make_shared<Cryptography::GpgMeReplacer>()); QCOMPARE(model->rowCount(msg), 0); cClient(t.mk("UID FETCH 333 (" FETCH_METADATA_ITEMS ")\r\n")); cServer("* 1 FETCH (UID 333 BODYSTRUCTURE " + bsEncrypted + ")\r\n" + t.last("OK fetched\r\n")); // notice that the ENVELOPE never arrived cEmpty(); QVERIFY(model->rowCount(msg) > 0); QModelIndex mappedMsg = msgModel.index(0,0); QVERIFY(mappedMsg.isValid()); QVERIFY(msgModel.rowCount(mappedMsg) > 0); QModelIndex data = mappedMsg.child(0, 0); QVERIFY(data.isValid()); QCOMPARE(msgModel.rowCount(data), 0); QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), false); cClientRegExp(t.mk("UID FETCH 333 \\((BODY\\.PEEK\\[2\\] BODY\\.PEEK\\[1\\]|BODY.PEEK\\[1\\] BODY\\.PEEK\\[2\\])\\)")); cServer("* 1 FETCH (UID 333 BODY[2] " + asLiteral(encValid) + " BODY[1] " + asLiteral("Version: 1\r\n") + ")\r\n" + t.last("OK fetched")); QSignalSpy qcaSuccessSpy(&msgModel, SIGNAL(rowsInserted(const QModelIndex &,int,int))); QSignalSpy qcaErrorSpy(&msgModel, SIGNAL(error(const QModelIndex &,QString,QString))); int i = 0; while (data.isValid() && data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet).toBool() && i++ < 1000) { QTest::qWait(10); } // allow for event processing, so that the model can retrieve the results QCoreApplication::processEvents(); QCOMPARE(data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet).toBool(), false); QVERIFY(qcaSuccessSpy.isEmpty()); QVERIFY(qcaErrorSpy.isEmpty()); QVERIFY(!data.data(Imap::Mailbox::RoleIsFetched).toBool()); // because the ENVELOPE hasn't arrived yet cEmpty(); QVERIFY(errorSpy->empty()); #else QSKIP("Cannot test without GpgME++ support"); #endif }
void ImapMsgPartNetAccessManagerTest::testMessageParts() { QFETCH(QByteArray, bodystructure); QFETCH(QByteArray, partId); QFETCH(QString, url); QFETCH(bool, validity); QFETCH(QByteArray, text); cServer("* 1 FETCH (UID 1 BODYSTRUCTURE (" + bodystructure + "))\r\n" + "* 2 FETCH (UID 2 BODYSTRUCTURE (" + bodystructure + "))\r\n" + t.last("OK fetched\r\n")); QVERIFY(model->rowCount(msg1) > 0); netAccessManager->setModelMessage(msg1); QNetworkRequest req; req.setUrl(QUrl(url)); QNetworkReply *res = netAccessManager->get(req); if (validity) { QVERIFY(qobject_cast<Imap::Network::MsgPartNetworkReply*>(res)); cClient(t.mk("UID FETCH 1 (BODY.PEEK[") + partId + "])\r\n"); cServer("* 1 FETCH (UID 1 BODY[" + partId + "] {" + QByteArray::number(text.size()) + "}\r\n" + text + ")\r\n" + t.last("OK fetched\r\n")); cEmpty(); QCOMPARE(text, res->readAll()); } else { QVERIFY(qobject_cast<Imap::Network::ForbiddenReply*>(res)); } #if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) QCOMPARE(res->isFinished(), true); #endif cEmpty(); QVERIFY(errorSpy->isEmpty()); }
void ImapMsgPartNetAccessManagerTest::init() { LibMailboxSync::init(); // By default, there's a 50ms delay between the time we request a part download and the time it actually happens. // That's too long for a unit test. model->setProperty("trojita-imap-delayed-fetch-part", 0); networkPolicy = new Imap::Mailbox::DummyNetworkWatcher(0, model); netAccessManager = new Imap::Network::MsgPartNetAccessManager(0); initialMessages(2); QModelIndex m1 = msgListA.child(0, 0); QVERIFY(m1.isValid()); QCOMPARE(model->rowCount(m1), 0); cClient(t.mk("UID FETCH 1:2 (" FETCH_METADATA_ITEMS ")\r\n")); //cServer() QCOMPARE(model->rowCount(msgListA), 2); msg1 = msgListA.child(0, 0); QVERIFY(msg1.isValid()); msg2 = msgListA.child(1, 0); QVERIFY(msg2.isValid()); cEmpty(); }
void ImapModelListChildMailboxesTest::testBackslashes() { model->rowCount(QModelIndex()); cClient(t.mk("LIST \"\" \"%\"\r\n")); cServer("* LIST (\\HasNoChildren) \"/\" Drafts\r\n" "* LIST (\\HasNoChildren) \"/\" {13}\r\nMail\\Papelera\r\n" "* LIST () \"/\" INBOX\r\n" + t.last("OK LIST completed\r\n")); QCOMPARE(model->rowCount(QModelIndex()), 4); QModelIndex withBackSlash = model->index(3, 0, QModelIndex()); QVERIFY(withBackSlash.isValid()); QCOMPARE(withBackSlash.data(Imap::Mailbox::RoleMailboxName).toString(), QString::fromUtf8("Mail\\Papelera")); QCOMPARE(withBackSlash.data(Imap::Mailbox::RoleUnreadMessageCount).toInt(), 0); cClient(t.mk("STATUS \"Mail\\\\Papelera\" (MESSAGES UNSEEN RECENT)\r\n")); cServer("* STATUS {13}\r\nMail\\Papelera (MESSAGES 1 RECENT 1 UNSEEN 1)\r\n" + t.last("OK status done\r\n")); QCOMPARE(withBackSlash.data(Imap::Mailbox::RoleUnreadMessageCount).toInt(), 1); cEmpty(); }
void CryptographyPGPTest::testDecryption() { QFETCH(QByteArray, bodystructure); QFETCH(QByteArray, cyphertext); QFETCH(QByteArray, plaintext); QFETCH(QString, from); QFETCH(bool, successful); // By default, there's a 50ms delay between the time we request a part download and the time it actually happens. // That's too long for a unit test. model->setProperty("trojita-imap-delayed-fetch-part", 0); helperSyncBNoMessages(); cServer("* 1 EXISTS\r\n"); cClient(t.mk("UID FETCH 1:* (FLAGS)\r\n")); cServer("* 1 FETCH (UID 333 FLAGS ())\r\n" + t.last("OK fetched\r\n")); QCOMPARE(model->rowCount(msgListB), 1); QModelIndex msg = msgListB.child(0, 0); QVERIFY(msg.isValid()); QCOMPARE(model->rowCount(msg), 0); cClient(t.mk("UID FETCH 333 (" FETCH_METADATA_ITEMS ")\r\n")); cServer(helperCreateTrivialEnvelope(1, 333, QStringLiteral("subj"), from, bodystructure) + t.last("OK fetched\r\n")); cEmpty(); QVERIFY(model->rowCount(msg) > 0); Cryptography::MessageModel msgModel(0, msg); #ifdef TROJITA_HAVE_CRYPTO_MESSAGES # ifdef TROJITA_HAVE_GPGMEPP msgModel.registerPartHandler(std::make_shared<Cryptography::GpgMeReplacer>()); # endif #endif QModelIndex mappedMsg = msgModel.index(0,0); QVERIFY(mappedMsg.isValid()); QVERIFY(msgModel.rowCount(mappedMsg) > 0); QModelIndex data = mappedMsg.child(0, 0); QVERIFY(data.isValid()); #ifdef TROJITA_HAVE_CRYPTO_MESSAGES QCOMPARE(msgModel.rowCount(data), 0); QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), false); cClientRegExp(t.mk("UID FETCH 333 \\((BODY\\.PEEK\\[2\\] BODY\\.PEEK\\[1\\]|BODY.PEEK\\[1\\] BODY\\.PEEK\\[2\\])\\)")); cServer("* 1 FETCH (UID 333 BODY[2] " + asLiteral(cyphertext) + " BODY[1] " + asLiteral("Version: 1\r\n") + ")\r\n" + t.last("OK fetched")); QSignalSpy qcaSuccessSpy(&msgModel, SIGNAL(rowsInserted(const QModelIndex &,int,int))); QSignalSpy qcaErrorSpy(&msgModel, SIGNAL(error(const QModelIndex &,QString,QString))); int i = 0; while (data.isValid() && data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet).toBool() && i++ < 1000) { QTest::qWait(10); } // allow for event processing, so that the model can retrieve the results QCoreApplication::processEvents(); if (!qcaErrorSpy.isEmpty() && successful) { qDebug() << "Unexpected failure in crypto"; for (int i = 0; i < qcaErrorSpy.size(); ++i) { qDebug() << qcaErrorSpy[i][1].toString(); qDebug() << qcaErrorSpy[i][2].toString(); } } if (successful) { QCOMPARE(qcaErrorSpy.empty(), successful); QCOMPARE(qcaSuccessSpy.empty(), !successful); } QVERIFY(data.data(Imap::Mailbox::RoleIsFetched).toBool()); cEmpty(); QVERIFY(errorSpy->empty()); #else QCOMPARE(msgModel.rowCount(data), 2); QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), true); QCOMPARE(data.child(0, 0).data(Imap::Mailbox::RolePartMimeType).toString(), QLatin1String("application/pgp-encrypted")); QCOMPARE(data.child(1, 0).data(Imap::Mailbox::RolePartMimeType).toString(), QLatin1String("application/octet-stream")); cEmpty(); QSKIP("Some tests were skipped because this build doesn't have GpgME++ support"); #endif }
void CryptographyPGPTest::testVerification() { QFETCH(QByteArray, signature); QFETCH(QByteArray, ptMimeHdr); QFETCH(QByteArray, plaintext); QFETCH(bool, successful); QFETCH(QString, from); QFETCH(QString, tldr); QFETCH(QString, longDesc); QFETCH(bool, validDisregardingTrust); QFETCH(bool, validCompletely); model->setProperty("trojita-imap-delayed-fetch-part", 0); helperSyncBNoMessages(); cServer("* 1 EXISTS\r\n"); cClient(t.mk("UID FETCH 1:* (FLAGS)\r\n")); cServer("* 1 FETCH (UID 333 FLAGS ())\r\n" + t.last("OK fetched\r\n")); QCOMPARE(model->rowCount(msgListB), 1); QModelIndex msg = msgListB.child(0, 0); QVERIFY(msg.isValid()); QCOMPARE(model->rowCount(msg), 0); cClient(t.mk("UID FETCH 333 (" FETCH_METADATA_ITEMS ")\r\n")); cServer(helperCreateTrivialEnvelope(1, 333, QStringLiteral("subj"), from, QStringLiteral("(" "(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 423 14 NIL NIL NIL NIL)" "(\"application\" \"pgp-signature\" NIL NIL NIL \"7bit\" 851 NIL NIL NIL NIL)" " \"signed\" (\"boundary\" \"=-=-=\" \"micalg\" \"pgp-sha256\" \"protocol\" \"application/pgp-signature\")" " NIL NIL NIL)")) + t.last("OK fetched\r\n")); cEmpty(); QVERIFY(model->rowCount(msg) > 0); Cryptography::MessageModel msgModel(0, msg); #ifdef TROJITA_HAVE_CRYPTO_MESSAGES # ifdef TROJITA_HAVE_GPGMEPP msgModel.registerPartHandler(std::make_shared<Cryptography::GpgMeReplacer>()); # endif #endif QModelIndex mappedMsg = msgModel.index(0,0); QVERIFY(mappedMsg.isValid()); QVERIFY(msgModel.rowCount(mappedMsg) > 0); QModelIndex data = mappedMsg.child(0, 0); QVERIFY(data.isValid()); #ifdef TROJITA_HAVE_CRYPTO_MESSAGES QCOMPARE(msgModel.rowCount(data), 0); QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), false); cClientRegExp(t.mk("UID FETCH 333 \\((BODY\\.PEEK\\[(2|1|1\\.MIME)\\] ?){3}\\)")); cServer("* 1 FETCH (UID 333 BODY[2] " + asLiteral(signature) + " BODY[1] " + asLiteral(plaintext) + " BODY[1.MIME] " + asLiteral(ptMimeHdr) + ")\r\n" + t.last("OK fetched")); QSignalSpy qcaErrorSpy(&msgModel, SIGNAL(error(const QModelIndex &,QString,QString))); int i = 0; while (data.isValid() && data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet).toBool() && qcaErrorSpy.empty() && i++ < 1000) { QTest::qWait(10); } // allow for event processing, so that the model can retrieve the results QCoreApplication::processEvents(); if (!qcaErrorSpy.isEmpty() && successful) { qDebug() << "Unexpected failure in crypto"; for (int i = 0; i < qcaErrorSpy.size(); ++i) { qDebug() << qcaErrorSpy[i][1].toString(); qDebug() << qcaErrorSpy[i][2].toString(); } } QCOMPARE(qcaErrorSpy.empty(), successful); QCOMPARE(data.data(Imap::Mailbox::RolePartCryptoTLDR).toString(), tldr); auto actualLongDesc = data.data(Imap::Mailbox::RolePartCryptoDetailedMessage).toString(); if (!actualLongDesc.startsWith(longDesc)) { QCOMPARE(actualLongDesc, longDesc); // let's reuse this for debug output, and don't be scared about the misleading implications } QCOMPARE(data.data(Imap::Mailbox::RolePartSignatureVerifySupported).toBool(), successful); QCOMPARE(data.data(Imap::Mailbox::RolePartSignatureValidDisregardingTrust).toBool(), validDisregardingTrust); QCOMPARE(data.data(Imap::Mailbox::RolePartSignatureValidTrusted).toBool(), validCompletely); QCOMPARE(data.data(Imap::Mailbox::RolePartMimeType).toByteArray(), QByteArray("multipart/signed")); QVERIFY(data.data(Imap::Mailbox::RoleIsFetched).toBool() == successful); auto partIdx = data.child(0, 0); QCOMPARE(partIdx.data(Imap::Mailbox::RolePartMimeType).toByteArray(), QByteArray("text/plain")); QCOMPARE(partIdx.data(Imap::Mailbox::RolePartUnicodeText).toString(), QString::fromUtf8(plaintext)); cEmpty(); QVERIFY(errorSpy->empty()); #else QCOMPARE(msgModel.rowCount(data), 2); QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), true); QCOMPARE(data.child(0, 0).data(Imap::Mailbox::RolePartMimeType).toString(), QLatin1String("application/pgp-encrypted")); QCOMPARE(data.child(1, 0).data(Imap::Mailbox::RolePartMimeType).toString(), QLatin1String("application/octet-stream")); cEmpty(); QSKIP("Some tests were skipped because this build doesn't have GpgME++ support"); #endif }