You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
670 lines
27 KiB
670 lines
27 KiB
/* |
|
SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#include "../unifiedmailboxmanager.h" |
|
#include "../unifiedmailbox.h" |
|
#include "../common.h" |
|
|
|
#include <KSharedConfig> |
|
#include <KConfigGroup> |
|
|
|
#include <AkonadiCore/SpecialCollectionAttribute> |
|
#include <AkonadiCore/CollectionFetchJob> |
|
#include <AkonadiCore/CollectionFetchScope> |
|
#include <AkonadiCore/CollectionCreateJob> |
|
#include <AkonadiCore/CollectionDeleteJob> |
|
#include <AkonadiCore/CollectionModifyJob> |
|
#include <AkonadiCore/ItemCreateJob> |
|
#include <AkonadiCore/ItemDeleteJob> |
|
#include <AkonadiCore/ItemModifyJob> |
|
#include <AkonadiCore/ItemMoveJob> |
|
#include <AkonadiCore/qtest_akonadi.h> |
|
|
|
#include <QTest> |
|
|
|
#include <memory> |
|
#include <chrono> |
|
|
|
using namespace std::chrono; |
|
using namespace std::chrono_literals; |
|
|
|
namespace { |
|
#define AKVERIFY_RET(statement, ret) \ |
|
do { \ |
|
if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__)) { \ |
|
return ret;} \ |
|
} while (false) |
|
|
|
#define AKCOMPARE_RET(actual, expected, ret) \ |
|
do { \ |
|
if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)) { \ |
|
return ret;} \ |
|
} while (false) |
|
|
|
Akonadi::Collection collectionForId(qint64 id) |
|
{ |
|
auto fetch = new Akonadi::CollectionFetchJob(Akonadi::Collection(id), Akonadi::CollectionFetchJob::Base); |
|
fetch->fetchScope().fetchAttribute<Akonadi::SpecialCollectionAttribute>(); |
|
AKVERIFY_RET(fetch->exec(), {}); |
|
const auto cols = fetch->collections(); |
|
AKCOMPARE_RET(cols.count(), 1, {}); |
|
return cols.first(); |
|
} |
|
|
|
Akonadi::Collection collectionForRid(const QString &rid) |
|
{ |
|
auto fetch = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive); |
|
fetch->fetchScope().fetchAttribute<Akonadi::SpecialCollectionAttribute>(); |
|
fetch->fetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All); |
|
AKVERIFY_RET(fetch->exec(), {}); |
|
const auto cols = fetch->collections(); |
|
auto colIt = std::find_if(cols.cbegin(), cols.cend(), [&rid](const Akonadi::Collection &col) { |
|
return col.remoteId() == rid; |
|
}); |
|
AKVERIFY_RET(colIt != cols.cend(), {}); |
|
return *colIt; |
|
} |
|
|
|
// A kingdom and a horse for std::optional! |
|
std::unique_ptr<UnifiedMailbox> createUnifiedMailbox(const QString &id, const QString &name, const QStringList &sourceRids) |
|
{ |
|
auto mailbox = std::make_unique<UnifiedMailbox>(); |
|
mailbox->setId(id); |
|
mailbox->setName(name); |
|
mailbox->setIcon(QStringLiteral("dummy-icon")); |
|
for (const auto &srcRid : sourceRids) { |
|
const auto srcCol = collectionForRid(srcRid); |
|
AKVERIFY_RET(srcCol.isValid(), {}); |
|
mailbox->addSourceCollection(srcCol.id()); |
|
} |
|
return mailbox; |
|
} |
|
|
|
class EntityDeleter |
|
{ |
|
public: |
|
~EntityDeleter() |
|
{ |
|
while (!cols.isEmpty()) { |
|
if (!(new Akonadi::CollectionDeleteJob(cols.takeFirst()))->exec()) { |
|
QFAIL("Failed to cleanup collection!"); |
|
} |
|
} |
|
while (!items.isEmpty()) { |
|
if (!(new Akonadi::ItemDeleteJob(items.takeFirst()))->exec()) { |
|
QFAIL("Failed to cleanup Item"); |
|
} |
|
} |
|
} |
|
|
|
EntityDeleter &operator<<(const Akonadi::Collection &col) |
|
{ |
|
cols.push_back(col); |
|
return *this; |
|
} |
|
|
|
EntityDeleter &operator<<(const Akonadi::Item &item) |
|
{ |
|
items.push_back(item); |
|
return *this; |
|
} |
|
|
|
private: |
|
Akonadi::Collection::List cols; |
|
Akonadi::Item::List items; |
|
}; |
|
|
|
Akonadi::Collection createCollection(const QString &name, const Akonadi::Collection &parent, EntityDeleter &deleter) |
|
{ |
|
Akonadi::Collection col; |
|
col.setName(name); |
|
col.setParentCollection(parent); |
|
col.setVirtual(true); |
|
auto createCol = new Akonadi::CollectionCreateJob(col); |
|
AKVERIFY_RET(createCol->exec(), {}); |
|
col = createCol->collection(); |
|
if (col.isValid()) { |
|
deleter << col; |
|
} |
|
return col; |
|
} |
|
} // namespace |
|
|
|
class UnifiedMailboxManagerTest : public QObject |
|
{ |
|
Q_OBJECT |
|
|
|
private Q_SLOTS: |
|
|
|
void initTestCase() |
|
{ |
|
AkonadiTest::checkTestIsIsolated(); |
|
} |
|
|
|
void testCreateDefaultBoxes() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
const auto boxesGroup = kcfg->group("UnifiedMailboxes"); |
|
UnifiedMailboxManager manager(kcfg); |
|
|
|
// Make sure the config is empty |
|
QVERIFY(boxesGroup.groupList().empty()); |
|
|
|
// Call loadBoxes and wait for it to finish |
|
bool loadingDone = false; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Check all the three boxes were created |
|
bool success; |
|
const auto verifyBox = [&manager, &success](const QString &id, int numSources) { |
|
success = false; |
|
auto boxIt = std::find_if(manager.begin(), manager.end(), |
|
[&id](const UnifiedMailboxManager::Entry &e) { |
|
return e.second->id() == id; |
|
}); |
|
QVERIFY(boxIt != manager.end()); |
|
const auto &box = boxIt->second; |
|
const auto sourceCollections = box->sourceCollections(); |
|
QCOMPARE(sourceCollections.size(), numSources); |
|
for (auto source : sourceCollections) { |
|
auto col = collectionForId(source); |
|
QVERIFY(col.isValid()); |
|
QVERIFY(col.hasAttribute<Akonadi::SpecialCollectionAttribute>()); |
|
QCOMPARE(col.attribute<Akonadi::SpecialCollectionAttribute>()->collectionType(), id.toLatin1()); |
|
} |
|
success = true; |
|
}; |
|
verifyBox(Common::InboxBoxId, 2); |
|
QVERIFY(success); |
|
verifyBox(Common::SentBoxId, 2); |
|
QVERIFY(success); |
|
verifyBox(Common::DraftsBoxId, 1); |
|
QVERIFY(success); |
|
|
|
// Check boxes were written to config - we don't check the contents of |
|
// the group, testing UnifiedMailbox serialization is done in other tests |
|
QVERIFY(boxesGroup.groupList().size() == 3); |
|
QVERIFY(boxesGroup.hasGroup(Common::InboxBoxId)); |
|
QVERIFY(boxesGroup.hasGroup(Common::SentBoxId)); |
|
QVERIFY(boxesGroup.hasGroup(Common::DraftsBoxId)); |
|
} |
|
|
|
void testAddingNewMailbox() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
const auto boxesGroup = kcfg->group("UnifiedMailboxes"); |
|
UnifiedMailboxManager manager(kcfg); |
|
Akonadi::ChangeRecorder &recorder = manager.changeRecorder(); |
|
|
|
// Nothing should be monitored as of now |
|
QVERIFY(recorder.collectionsMonitored().isEmpty()); |
|
|
|
// Create a new unified mailbox and passit to the manager |
|
auto mailbox = createUnifiedMailbox(QStringLiteral("Test1"), QStringLiteral("Test 1"), |
|
{ QStringLiteral("res1_inbox") }); |
|
QVERIFY(mailbox); |
|
const auto sourceCol = mailbox->sourceCollections().values().first(); |
|
manager.insertBox(std::move(mailbox)); |
|
|
|
// Now manager should have one unified mailbox and monitor all of its |
|
// source collections |
|
QCOMPARE(std::distance(manager.begin(), manager.end()), 1l); |
|
QCOMPARE(recorder.collectionsMonitored().size(), 1); |
|
QCOMPARE(recorder.collectionsMonitored().at(0).id(), sourceCol); |
|
QVERIFY(manager.unifiedMailboxForSource(sourceCol) != nullptr); |
|
|
|
// But nothing should bne written in the config yet |
|
QVERIFY(!boxesGroup.groupList().contains(QLatin1String("Test1"))); |
|
|
|
// Now write to the config file and check it's actually there - we don't test |
|
// the contents of the group, UnifiedMailbox serialization has its own test |
|
manager.saveBoxes(); |
|
QVERIFY(boxesGroup.hasGroup(QLatin1String("Test1"))); |
|
} |
|
|
|
void testRemoveMailbox() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
auto boxesGroup = kcfg->group("UnifiedMailboxes"); |
|
auto mailbox = createUnifiedMailbox(QStringLiteral("Test1"), QStringLiteral("Test 1"), |
|
{ QStringLiteral("res1_foo"), QStringLiteral("res2_foo") }); |
|
QVERIFY(mailbox); |
|
auto group = boxesGroup.group(mailbox->id()); |
|
mailbox->save(group); |
|
|
|
UnifiedMailboxManager manager(kcfg); |
|
Akonadi::ChangeRecorder &recorder = manager.changeRecorder(); |
|
|
|
// Nothing should be monitored right now |
|
QVERIFY(recorder.collectionsMonitored().isEmpty()); |
|
|
|
// Load the config |
|
bool loadingDone = false; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now the box should be loaded and its source collections monitored |
|
QCOMPARE(std::distance(manager.begin(), manager.end()), 1l); |
|
QCOMPARE(recorder.collectionsMonitored().count(), 2); |
|
const auto srcCols = mailbox->sourceCollections().values(); |
|
QCOMPARE(srcCols.count(), 2); |
|
QVERIFY(recorder.collectionsMonitored().contains(Akonadi::Collection(srcCols[0]))); |
|
QVERIFY(recorder.collectionsMonitored().contains(Akonadi::Collection(srcCols[1]))); |
|
|
|
// Now remove the box |
|
manager.removeBox(mailbox->id()); |
|
|
|
// Manager should have no boxes and no source collections should be monitored |
|
QVERIFY(manager.begin() == manager.end()); |
|
QVERIFY(recorder.collectionsMonitored().isEmpty()); |
|
|
|
// But the box still exists in the config |
|
QVERIFY(boxesGroup.hasGroup(mailbox->id())); |
|
|
|
// Save the new state |
|
manager.saveBoxes(); |
|
|
|
// And now it should be gone from the config file as well |
|
QVERIFY(!boxesGroup.hasGroup(mailbox->id())); |
|
} |
|
|
|
void testDiscoverBoxCollections() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
auto boxesGroup = kcfg->group("UnifiedMailboxes"); |
|
UnifiedMailboxManager manager(kcfg); |
|
EntityDeleter deleter; |
|
const auto inbox = createUnifiedMailbox(Common::InboxBoxId, QStringLiteral("Inbox"), |
|
{ QStringLiteral("res1_inbox"), QStringLiteral("res2_inbox") }); |
|
auto boxGroup = boxesGroup.group(inbox->id()); |
|
inbox->save(boxGroup); |
|
const auto sentBox = createUnifiedMailbox(Common::SentBoxId, QStringLiteral("Sent"), |
|
{ QStringLiteral("res1_sent"), QStringLiteral("res2_sent") }); |
|
boxGroup = boxesGroup.group(sentBox->id()); |
|
sentBox->save(boxGroup); |
|
|
|
const Akonadi::Collection parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto inboxBoxCol = createCollection(Common::InboxBoxId, parentCol, deleter); |
|
QVERIFY(inboxBoxCol.isValid()); |
|
|
|
const auto sentBoxCol = createCollection(Common::SentBoxId, parentCol, deleter); |
|
QVERIFY(sentBoxCol.isValid()); |
|
|
|
// Load from config |
|
bool loadingDone = false; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now the boxes should be loaded and we should be able to access them |
|
// by IDs of collections that represent them. The collections should also |
|
// be set for each box. |
|
auto box = manager.unifiedMailboxFromCollection(inboxBoxCol); |
|
QVERIFY(box != nullptr); |
|
QCOMPARE(box->collectionId(), inboxBoxCol.id()); |
|
|
|
box = manager.unifiedMailboxFromCollection(sentBoxCol); |
|
QVERIFY(box != nullptr); |
|
QCOMPARE(box->collectionId(), sentBoxCol.id()); |
|
} |
|
|
|
void testItemAddedToSourceCollection() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
UnifiedMailboxManager manager(kcfg); |
|
EntityDeleter deleter; |
|
|
|
const auto parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto inboxBoxCol = createCollection(Common::InboxBoxId, parentCol, deleter); |
|
QVERIFY(inboxBoxCol.isValid()); |
|
|
|
// Load boxes - config is empty so this will create the default Boxes and |
|
// assign the Inboxes from Knuts to it |
|
bool loadingDone = true; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now discover collections for the created boxes |
|
loadingDone = false; |
|
manager.discoverBoxCollections([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Get one of the source collections for Inbox |
|
const auto inboxSourceCol = collectionForRid(QStringLiteral("res1_inbox")); |
|
QVERIFY(inboxSourceCol.isValid()); |
|
|
|
// Setup up a monitor to to be notified when an item gets linked into |
|
// the unified mailbox collection |
|
Akonadi::Monitor monitor; |
|
monitor.setCollectionMonitored(inboxBoxCol); |
|
QSignalSpy itemLinkedSignalSpy(&monitor, &Akonadi::Monitor::itemsLinked); |
|
QVERIFY(QSignalSpy(&monitor, &Akonadi::Monitor::monitorReady).wait()); |
|
|
|
// Add a new Item into the source collection |
|
Akonadi::Item item; |
|
item.setMimeType(QStringLiteral("application/octet-stream")); |
|
item.setParentCollection(inboxSourceCol); |
|
item.setPayload(QByteArray {"Hello world!"}); |
|
auto createItem = new Akonadi::ItemCreateJob(item, inboxSourceCol, this); |
|
AKVERIFYEXEC(createItem); |
|
item = createItem->item(); |
|
deleter << item; |
|
|
|
// Then wait for ItemLinked notification as the Manager has linked the new Item |
|
// to the dest collection |
|
QTRY_COMPARE(itemLinkedSignalSpy.size(), 1); |
|
const auto linkedItems = itemLinkedSignalSpy.at(0).at(0).value<Akonadi::Item::List>(); |
|
QCOMPARE(linkedItems.size(), 1); |
|
QCOMPARE(linkedItems.at(0), item); |
|
const auto linkedCol = itemLinkedSignalSpy.at(0).at(1).value<Akonadi::Collection>(); |
|
QCOMPARE(linkedCol, inboxBoxCol); |
|
} |
|
|
|
void testItemMovedFromSourceCollection() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
UnifiedMailboxManager manager(kcfg); |
|
EntityDeleter deleter; |
|
|
|
const auto parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto inboxBoxCol = createCollection(Common::InboxBoxId, parentCol, deleter); |
|
QVERIFY(inboxBoxCol.isValid()); |
|
|
|
// Load boxes - config is empty so this will create the default Boxes and |
|
// assign the Inboxes from Knuts to it |
|
bool loadingDone = true; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now discover collections for the created boxes |
|
loadingDone = false; |
|
manager.discoverBoxCollections([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Get one of the source collections for Inbox |
|
const auto inboxSourceCol = collectionForRid(QStringLiteral("res1_inbox")); |
|
QVERIFY(inboxSourceCol.isValid()); |
|
|
|
// Setup up a monitor to to be notified when an item gets linked into |
|
// the unified mailbox collection |
|
Akonadi::Monitor monitor; |
|
monitor.setCollectionMonitored(inboxBoxCol); |
|
QSignalSpy itemLinkedSignalSpy(&monitor, &Akonadi::Monitor::itemsLinked); |
|
QSignalSpy itemUnlinkedSignalSpy(&monitor, &Akonadi::Monitor::itemsUnlinked); |
|
QVERIFY(QSignalSpy(&monitor, &Akonadi::Monitor::monitorReady).wait()); |
|
|
|
// Add a new Item into the source collection |
|
Akonadi::Item item; |
|
item.setMimeType(QStringLiteral("application/octet-stream")); |
|
item.setParentCollection(inboxSourceCol); |
|
item.setPayload(QByteArray {"Hello world!"}); |
|
auto createItem = new Akonadi::ItemCreateJob(item, inboxSourceCol, this); |
|
AKVERIFYEXEC(createItem); |
|
item = createItem->item(); |
|
deleter << item; |
|
|
|
// Waity for the item to be linked |
|
QTRY_COMPARE(itemLinkedSignalSpy.size(), 1); |
|
|
|
const auto destinationCol = collectionForRid(QStringLiteral("res1_foo")); |
|
QVERIFY(destinationCol.isValid()); |
|
|
|
// Now move the Item to an unmonitored collection |
|
auto move = new Akonadi::ItemMoveJob(item, destinationCol, this); |
|
AKVERIFYEXEC(move); |
|
|
|
QTRY_COMPARE(itemUnlinkedSignalSpy.size(), 1); |
|
const auto unlinkedItems = itemUnlinkedSignalSpy.at(0).at(0).value<Akonadi::Item::List>(); |
|
QCOMPARE(unlinkedItems.size(), 1); |
|
QCOMPARE(unlinkedItems.first(), item); |
|
const auto unlinkedCol = itemUnlinkedSignalSpy.at(0).at(1).value<Akonadi::Collection>(); |
|
QCOMPARE(unlinkedCol, inboxBoxCol); |
|
} |
|
|
|
void testItemMovedBetweenSourceCollections() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
UnifiedMailboxManager manager(kcfg); |
|
EntityDeleter deleter; |
|
|
|
const auto parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto inboxBoxCol = createCollection(Common::InboxBoxId, parentCol, deleter); |
|
QVERIFY(inboxBoxCol.isValid()); |
|
|
|
const auto draftsBoxCol = createCollection(Common::DraftsBoxId, parentCol, deleter); |
|
QVERIFY(draftsBoxCol.isValid()); |
|
|
|
// Load boxes - config is empty so this will create the default Boxes and |
|
// assign the Inboxes from Knuts to it |
|
bool loadingDone = true; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now discover collections for the created boxes |
|
loadingDone = false; |
|
manager.discoverBoxCollections([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Get one of the source collections for Inbox and Drafts |
|
const auto inboxSourceCol = collectionForRid(QStringLiteral("res1_inbox")); |
|
QVERIFY(inboxSourceCol.isValid()); |
|
const auto draftsSourceCol = collectionForRid(QStringLiteral("res1_drafts")); |
|
QVERIFY(draftsSourceCol.isValid()); |
|
|
|
// Setup up a monitor to to be notified when an item gets linked into |
|
// the unified mailbox collection |
|
Akonadi::Monitor monitor; |
|
monitor.setCollectionMonitored(inboxBoxCol); |
|
monitor.setCollectionMonitored(draftsBoxCol); |
|
QSignalSpy itemLinkedSignalSpy(&monitor, &Akonadi::Monitor::itemsLinked); |
|
QSignalSpy itemUnlinkedSignalSpy(&monitor, &Akonadi::Monitor::itemsUnlinked); |
|
QVERIFY(QSignalSpy(&monitor, &Akonadi::Monitor::monitorReady).wait()); |
|
|
|
// Add a new Item into the source Inbox collection |
|
Akonadi::Item item; |
|
item.setMimeType(QStringLiteral("application/octet-stream")); |
|
item.setParentCollection(inboxSourceCol); |
|
item.setPayload(QByteArray {"Hello world!"}); |
|
auto createItem = new Akonadi::ItemCreateJob(item, inboxSourceCol, this); |
|
AKVERIFYEXEC(createItem); |
|
item = createItem->item(); |
|
deleter << item; |
|
|
|
// Waity for the item to be linked |
|
QTRY_COMPARE(itemLinkedSignalSpy.size(), 1); |
|
itemLinkedSignalSpy.clear(); |
|
|
|
// Now move the Item to another Unified mailbox's source collection |
|
auto move = new Akonadi::ItemMoveJob(item, draftsSourceCol, this); |
|
AKVERIFYEXEC(move); |
|
|
|
QTRY_COMPARE(itemUnlinkedSignalSpy.size(), 1); |
|
const auto unlinkedItems = itemUnlinkedSignalSpy.at(0).at(0).value<Akonadi::Item::List>(); |
|
QCOMPARE(unlinkedItems.size(), 1); |
|
QCOMPARE(unlinkedItems.first(), item); |
|
const auto unlinkedCol = itemUnlinkedSignalSpy.at(0).at(1).value<Akonadi::Collection>(); |
|
QCOMPARE(unlinkedCol, inboxBoxCol); |
|
|
|
QTRY_COMPARE(itemLinkedSignalSpy.size(), 1); |
|
const auto linkedItems = itemLinkedSignalSpy.at(0).at(0).value<Akonadi::Item::List>(); |
|
QCOMPARE(linkedItems.size(), 1); |
|
QCOMPARE(linkedItems.first(), item); |
|
const auto linkedCol = itemLinkedSignalSpy.at(0).at(1).value<Akonadi::Collection>(); |
|
QCOMPARE(linkedCol, draftsBoxCol); |
|
} |
|
|
|
void testSourceCollectionRemoved() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
UnifiedMailboxManager manager(kcfg); |
|
auto &changeRecorder = manager.changeRecorder(); |
|
QSignalSpy crRemovedSpy(&changeRecorder, &Akonadi::Monitor::collectionRemoved); |
|
EntityDeleter deleter; |
|
|
|
const auto parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto inboxBoxCol = createCollection(Common::InboxBoxId, parentCol, deleter); |
|
QVERIFY(inboxBoxCol.isValid()); |
|
|
|
// Load boxes - config is empty so this will create the default Boxes and |
|
// assign the Inboxes from Knuts to it |
|
bool loadingDone = true; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now discover collections for the created boxes |
|
loadingDone = false; |
|
manager.discoverBoxCollections([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
auto inboxSourceCol = collectionForRid(QStringLiteral("res1_inbox")); |
|
QVERIFY(inboxSourceCol.isValid()); |
|
auto delJob = new Akonadi::CollectionDeleteJob(inboxSourceCol, this); |
|
AKVERIFYEXEC(delJob); |
|
|
|
// Wait for the change recorder to be notified |
|
QVERIFY(crRemovedSpy.wait()); |
|
crRemovedSpy.clear(); |
|
// and then wait a little bit more to give the Manager time to process the event |
|
QTest::qWait(0); |
|
|
|
auto inboxBox = manager.unifiedMailboxFromCollection(inboxBoxCol); |
|
QVERIFY(inboxBox); |
|
QVERIFY(!inboxBox->sourceCollections().contains(inboxSourceCol.id())); |
|
QVERIFY(!changeRecorder.collectionsMonitored().contains(inboxSourceCol)); |
|
QVERIFY(!manager.unifiedMailboxForSource(inboxSourceCol.id())); |
|
|
|
// Lets removed the other source collection now, that should remove the unified box completely |
|
inboxSourceCol = collectionForRid(QStringLiteral("res2_inbox")); |
|
QVERIFY(inboxSourceCol.isValid()); |
|
delJob = new Akonadi::CollectionDeleteJob(inboxSourceCol, this); |
|
AKVERIFYEXEC(delJob); |
|
|
|
// Wait for the change recorder once again |
|
QVERIFY(crRemovedSpy.wait()); |
|
QTest::qWait(0); |
|
|
|
QVERIFY(!manager.unifiedMailboxFromCollection(inboxBoxCol)); |
|
QVERIFY(!changeRecorder.collectionsMonitored().contains(inboxSourceCol)); |
|
QVERIFY(!manager.unifiedMailboxForSource(inboxSourceCol.id())); |
|
} |
|
|
|
void testSpecialSourceCollectionCreated() |
|
{ |
|
// TODO: this does not work yet: we only monitor collections that we are |
|
// interested in, we don't monitor other collections |
|
} |
|
|
|
void testSpecialSourceCollectionDemoted() |
|
{ |
|
// Setup |
|
auto kcfg = KSharedConfig::openConfig(QString::fromUtf8(QTest::currentTestFunction())); |
|
UnifiedMailboxManager manager(kcfg); |
|
auto &changeRecorder = manager.changeRecorder(); |
|
QSignalSpy crChangedSpy(&changeRecorder, qOverload<const Akonadi::Collection &, const QSet<QByteArray> &>(&Akonadi::Monitor::collectionChanged)); |
|
EntityDeleter deleter; |
|
|
|
const auto parentCol = collectionForRid(Common::AgentIdentifier); |
|
QVERIFY(parentCol.isValid()); |
|
|
|
const auto sentBoxCol = createCollection(Common::SentBoxId, parentCol, deleter); |
|
QVERIFY(sentBoxCol.isValid()); |
|
|
|
// Load boxes - config is empty so this will create the default Boxes and |
|
// assign the Inboxes from Knuts to it |
|
bool loadingDone = true; |
|
manager.loadBoxes([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
// Now discover collections for the created boxes |
|
loadingDone = false; |
|
manager.discoverBoxCollections([&loadingDone]() { |
|
loadingDone = true; |
|
}); |
|
QTRY_VERIFY_WITH_TIMEOUT(loadingDone, milliseconds(10s).count()); |
|
|
|
auto sentSourceCol = collectionForRid(QStringLiteral("res1_sent")); |
|
QVERIFY(sentSourceCol.isValid()); |
|
sentSourceCol.removeAttribute<Akonadi::SpecialCollectionAttribute>(); |
|
auto modify = new Akonadi::CollectionModifyJob(sentSourceCol, this); |
|
AKVERIFYEXEC(modify); |
|
|
|
// Wait for the change recorder to be notified |
|
QVERIFY(crChangedSpy.wait()); |
|
crChangedSpy.clear(); |
|
// and then wait a little bit more to give the Manager time to process the event |
|
QTest::qWait(0); |
|
|
|
auto sourceBox = manager.unifiedMailboxFromCollection(sentBoxCol); |
|
QVERIFY(sourceBox); |
|
QVERIFY(!sourceBox->sourceCollections().contains(sentSourceCol.id())); |
|
QVERIFY(!changeRecorder.collectionsMonitored().contains(sentSourceCol)); |
|
QVERIFY(!manager.unifiedMailboxForSource(sentSourceCol.id())); |
|
|
|
// Lets demote the other source collection now, that should remove the unified box completely |
|
sentSourceCol = collectionForRid(QStringLiteral("res2_sent")); |
|
QVERIFY(sentSourceCol.isValid()); |
|
sentSourceCol.attribute<Akonadi::SpecialCollectionAttribute>()->setCollectionType("drafts"); |
|
modify = new Akonadi::CollectionModifyJob(sentSourceCol, this); |
|
AKVERIFYEXEC(modify); |
|
|
|
// Wait for the change recorder once again |
|
QVERIFY(crChangedSpy.wait()); |
|
QTest::qWait(0); |
|
|
|
// There's no more Sent unified box |
|
QVERIFY(!manager.unifiedMailboxFromCollection(sentBoxCol)); |
|
|
|
// The collection is still monitored: it belongs to the Drafts special box now! |
|
QVERIFY(changeRecorder.collectionsMonitored().contains(sentSourceCol)); |
|
QVERIFY(manager.unifiedMailboxForSource(sentSourceCol.id())); |
|
} |
|
}; |
|
|
|
QTEST_AKONADIMAIN(UnifiedMailboxManagerTest) |
|
|
|
#include "unifiedmailboxmanagertest.moc"
|
|
|