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

Add MoveHandlerTest, improve ItemMoveTest, minor MOVE fix

parent 38216a76
......@@ -24,6 +24,9 @@
#include "itemfetchjob.h"
#include "itemmovejob.h"
#include "itemfetchscope.h"
#include "collectionfetchscope.h"
#include "monitor.h"
#include "session.h"
#include <QtCore/QObject>
......@@ -49,17 +52,22 @@ private Q_SLOTS:
QTest::addColumn<Collection>("destination");
QTest::addColumn<Collection>("source");
const Collection destination(collectionIdFromPath(QStringLiteral("res3")));
Collection destination(collectionIdFromPath(QStringLiteral("res1/foo/bar")));
QVERIFY(destination.isValid());
QTest::newRow("single uid") << (Item::List() << Item(1)) << destination << Collection();
QTest::newRow("two uid") << (Item::List() << Item(2) << Item(3)) << destination << Collection();
QTest::newRow("intra-res single uid") << (Item::List() << Item(5)) << destination << Collection();
destination = Collection(collectionIdFromPath(QStringLiteral("res3")));
QVERIFY(destination.isValid());
QTest::newRow("inter-res single uid") << (Item::List() << Item(1)) << destination << Collection();
QTest::newRow("inter-res two uid") << (Item::List() << Item(2) << Item(3)) << destination << Collection();
Item r1; r1.setRemoteId(QStringLiteral("D"));
Collection ridDest;
ridDest.setRemoteId(QStringLiteral("3"));
Collection ridSource;
ridSource.setRemoteId(QStringLiteral("10"));
QTest::newRow("single rid") << (Item::List() << r1) << ridDest << ridSource;
QTest::newRow("intra-res single rid") << (Item::List() << r1) << ridDest << ridSource;
}
void testMove()
......@@ -68,8 +76,15 @@ private Q_SLOTS:
QFETCH(Collection, destination);
QFETCH(Collection, source);
//Collection source( collectionIdFromPath( "res1/foo" ) );
//QVERIFY( source.isValid() );
Session monitorSession;
Monitor monitor(&monitorSession);
monitor.setObjectName(QStringLiteral("itemmovetest"));
monitor.setCollectionMonitored(Collection::root());
monitor.fetchCollection(true); monitor.itemFetchScope().setAncestorRetrieval(ItemFetchScope::Parent);
monitor.itemFetchScope().setFetchRemoteIdentification(true);
QSignalSpy moveSpy(&monitor, &Monitor::itemsMoved);
QSignalSpy readySpy(&monitor, &Monitor::monitorReady);
readySpy.wait();
ResourceSelectJob *select = new ResourceSelectJob(QStringLiteral("akonadi_knut_resource_0"));
AKVERIFYEXEC(select); // for rid based moves
......@@ -82,12 +97,29 @@ private Q_SLOTS:
AKVERIFYEXEC(move);
ItemFetchJob *fetch = new ItemFetchJob(destination, this);
fetch->fetchScope().setAncestorRetrieval(ItemFetchScope::Parent);
fetch->fetchScope().fetchFullPayload();
AKVERIFYEXEC(fetch);
QCOMPARE(fetch->items().count(), items.count() + baseline);
foreach (const Item &movedItem, fetch->items()) {
QVERIFY(movedItem.hasPayload());
QVERIFY(!movedItem.payload<QByteArray>().isEmpty());
if (destination.id() >= 0) {
QCOMPARE(movedItem.parentCollection().id(), destination.id());
} else {
QCOMPARE(movedItem.parentCollection().remoteId(), destination.remoteId());
}
}
QTRY_COMPARE(moveSpy.count(), 1);
const Akonadi::Item::List &ntfItems = moveSpy.takeFirst().at(0).value<Akonadi::Item::List>();
QCOMPARE(ntfItems.size(), items.size());
Q_FOREACH (const Item &ntfItem, ntfItems) {
if (destination.id() >= 0) {
QCOMPARE(ntfItem.parentCollection().id(), destination.id());
} else {
QCOMPARE(ntfItem.parentCollection().remoteId(), destination.remoteId());
}
}
}
......
......@@ -30,6 +30,7 @@ set(common_SRCS
fakeclient.cpp
fakeakonadiserver.cpp
fakesearchmanager.cpp
fakeitemretrievalmanager.cpp
dbinitializer.cpp
${CMAKE_CURRENT_BINARY_DIR}/dbpopulator.cpp
)
......@@ -92,6 +93,7 @@ add_server_test(akappendhandlertest.cpp)
add_server_test(linkhandlertest.cpp)
add_server_test(listhandlertest.cpp)
add_server_test(modifyhandlertest.cpp)
add_server_test(movehandlertest.cpp)
add_server_test(createhandlertest.cpp)
add_server_test(collectionreferencetest.cpp)
add_server_test(searchtest.cpp akonadiprivate)
......
......@@ -22,6 +22,7 @@
#include "fakedatastore.h"
#include "fakesearchmanager.h"
#include "fakeclient.h"
#include "fakeitemretrievalmanager.h"
#include <QSettings>
#include <QCoreApplication>
......@@ -103,6 +104,10 @@ FakeAkonadiServer *FakeAkonadiServer::instance()
FakeAkonadiServer::FakeAkonadiServer()
: AkonadiServer()
, mDataStore(Q_NULLPTR)
, mSearchManager(Q_NULLPTR)
, mConnection(Q_NULLPTR)
, mClient(Q_NULLPTR)
, mRetrievalManager(Q_NULLPTR)
, mServerLoop(Q_NULLPTR)
, mNtfCollector(Q_NULLPTR)
, mPopulateDb(true)
......@@ -120,6 +125,7 @@ FakeAkonadiServer::~FakeAkonadiServer()
{
delete mClient;
delete mConnection;
delete mRetrievalManager;
delete mNtfCollector;
}
......@@ -216,6 +222,8 @@ bool FakeAkonadiServer::init()
PreprocessorManager::instance()->setEnabled(false);
mSearchManager = new FakeSearchManager();
mRetrievalManager = new FakeItemRetrievalManager();
const QString socketFile = basePath() + QLatin1String("/local/share/akonadi/akonadiserver.socket");
qDebug() << "==== Fake Akonadi Server started ====";
......
......@@ -42,6 +42,7 @@ class FakeSearchManager;
class FakeDataStore;
class FakeConnection;
class FakeClient;
class FakeItemRetrievalManager;
class TestScenario {
public:
......@@ -122,6 +123,7 @@ private:
FakeSearchManager *mSearchManager;
FakeConnection *mConnection;
FakeClient *mClient;
FakeItemRetrievalManager *mRetrievalManager;
QEventLoop *mServerLoop;
......
/*
Copyright (c) 2016 Daniel Vrátil <dvratil@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "fakeitemretrievalmanager.h"
#include "storage/itemretrievalrequest.h"
using namespace Akonadi::Server;
FakeItemRetrievalManager::FakeItemRetrievalManager()
: ItemRetrievalManager()
{
sInstance = this;
qRegisterMetaType<ItemRetrievalRequest*>("ItemRetrievalRequest*");
}
FakeItemRetrievalManager::~FakeItemRetrievalManager()
{
sInstance = Q_NULLPTR;
}
void FakeItemRetrievalManager::requestItemDelivery(ItemRetrievalRequest *request)
{
QMetaObject::invokeMethod(this, "requestFinished", Qt::QueuedConnection,
Q_ARG(ItemRetrievalRequest*, request));
}
/*
Copyright (c) 2016 Daniel Vrátil <dvratil@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_SERVER_FAKEITEMRETRIEVALMANAGER_H
#define AKONADI_SERVER_FAKEITEMRETRIEVALMANAGER_H
#include "storage/itemretrievalmanager.h"
namespace Akonadi {
namespace Server {
class FakeItemRetrievalManager : public ItemRetrievalManager
{
Q_OBJECT
public:
explicit FakeItemRetrievalManager();
~FakeItemRetrievalManager() Q_DECL_OVERRIDE;
void requestItemDelivery(ItemRetrievalRequest *request) Q_DECL_OVERRIDE;
};
} // namespace Server
} // namespace Akonadi
#endif
/*
Copyright (c) 2016 Daniel Vrátil <dvratil@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include <QObject>
#include <handler/move.h>
#include <storage/entity.h>
#include "fakeakonadiserver.h"
#include "aktest.h"
#include "entities.h"
#include <private/scope_p.h>
#include <private/imapset_p.h>
#include <QtTest/QTest>
using namespace Akonadi;
using namespace Akonadi::Server;
Q_DECLARE_METATYPE(Akonadi::Protocol::ItemChangeNotification::List)
Q_DECLARE_METATYPE(Akonadi::Protocol::ItemChangeNotification)
class MoveHandlerTest : public QObject
{
Q_OBJECT
public:
MoveHandlerTest()
{
try {
FakeAkonadiServer::instance()->init();
} catch (const FakeAkonadiServerException &e) {
qWarning() << "Server exception: " << e.what();
qFatal("Fake Akonadi Server failed to start up, aborting test");
}
}
~MoveHandlerTest()
{
FakeAkonadiServer::instance()->quit();
}
private Q_SLOTS:
void testMove_data()
{
const Collection srcCol = Collection::retrieveByName(QStringLiteral("Collection B"));
const Collection destCol = Collection::retrieveByName(QStringLiteral("Collection A"));
QTest::addColumn<TestScenario::List>("scenarios");
QTest::addColumn<Protocol::ItemChangeNotification::List>("expectedNotifications");
QTest::addColumn<QVariant>("newValue");
Protocol::ItemChangeNotification notificationTemplate;
notificationTemplate.setOperation(Protocol::ItemChangeNotification::Move);
notificationTemplate.setResource("akonadi_fake_resource_0");
notificationTemplate.setDestinationResource("akonadi_fake_resource_0");
notificationTemplate.setSessionId(FakeAkonadiServer::instanceName().toLatin1());
notificationTemplate.setParentCollection(srcCol.id());
notificationTemplate.setParentDestCollection(destCol.id());
{
Protocol::MoveItemsCommand cmd(1, destCol.id());
TestScenario::List scenarios;
scenarios << FakeAkonadiServer::loginScenario()
<< TestScenario::create(5, TestScenario::ClientCmd, cmd)
<< TestScenario::create(5, TestScenario::ServerCmd, Protocol::MoveItemsResponse());
Protocol::ItemChangeNotification notification = notificationTemplate;
notification.setItem({ Protocol::ItemChangeNotification::Item(1, QStringLiteral("A"), QString(), QStringLiteral("application/octet-stream")) });
QTest::newRow("move item") << scenarios << Protocol::ItemChangeNotification::List{ notification }
<< QVariant::fromValue(destCol.id());
}
{
Protocol::MoveItemsCommand cmd(QVector<qint64>{ 2, 3 }, destCol.id());
TestScenario::List scenarios;
scenarios << FakeAkonadiServer::loginScenario()
<< TestScenario::create(5, TestScenario::ClientCmd, cmd)
<< TestScenario::create(5, TestScenario::ServerCmd, Protocol::MoveItemsResponse());
Protocol::ItemChangeNotification notification = notificationTemplate;
notification.setItem({ Protocol::ItemChangeNotification::Item(2, QStringLiteral("B"), QString(), QStringLiteral("application/octet-stream")),
Protocol::ItemChangeNotification::Item(3, QStringLiteral("C"), QString(),
QStringLiteral("application/octet-stream")) });
QTest::newRow("mote items") << scenarios << Protocol::ItemChangeNotification::List{ notification }
<< QVariant::fromValue(destCol.id());
}
}
void testMove()
{
QFETCH(TestScenario::List, scenarios);
QFETCH(Protocol::ItemChangeNotification::List, expectedNotifications);
QFETCH(QVariant, newValue);
FakeAkonadiServer::instance()->setScenarios(scenarios);
FakeAkonadiServer::instance()->runTest();
auto notificationSpy = FakeAkonadiServer::instance()->notificationSpy();
if (expectedNotifications.isEmpty()) {
QVERIFY(notificationSpy->isEmpty() || notificationSpy->takeFirst().first().value<Protocol::ChangeNotification::List>().isEmpty());
return;
}
QCOMPARE(notificationSpy->count(), 1);
//Only one notify call
QCOMPARE(notificationSpy->first().count(), 1);
const Protocol::ChangeNotification::List receivedNotifications = notificationSpy->first().first().value<Protocol::ChangeNotification::List>();
QCOMPARE(receivedNotifications.size(), expectedNotifications.count());
for (int i = 0; i < expectedNotifications.size(); i++) {
QCOMPARE(Protocol::ItemChangeNotification(receivedNotifications.at(i)), expectedNotifications.at(i));
Protocol::ItemChangeNotification notification = receivedNotifications.at(i);
QCOMPARE(notification.parentDestCollection(), newValue.toInt());
Q_FOREACH (const auto &ntfItem, notification.items()) {
const PimItem item = PimItem::retrieveById(ntfItem.id);
QCOMPARE(item.collectionId(), newValue.toInt());
}
}
}
};
AKTEST_FAKESERVER_MAIN(MoveHandlerTest)
#include "movehandlertest.moc"
......@@ -34,7 +34,6 @@ using namespace Akonadi::Server;
void Move::itemsRetrieved(const QList<qint64> &ids)
{
DataStore *store = connection()->storageBackend();
Transaction transaction(store);
......@@ -51,7 +50,6 @@ void Move::itemsRetrieved(const QList<qint64> &ids)
const QVector<PimItem> items = qb.result();
if (items.isEmpty()) {
successResponse<Protocol::MoveItemsResponse>();
return;
}
......
......@@ -62,7 +62,7 @@ public:
* Added for convenience. ItemRetrievalManager takes ownership over the
* pointer and deletes it when the request is processed.
*/
void requestItemDelivery(ItemRetrievalRequest *request);
virtual void requestItemDelivery(ItemRetrievalRequest *request);
static ItemRetrievalManager *instance();
......@@ -82,7 +82,7 @@ private Q_SLOTS:
void triggerCollectionTreeSync(const QString &resource);
void retrievalJobFinished(ItemRetrievalRequest *request, const QString &errorMsg);
private:
protected:
static ItemRetrievalManager *sInstance;
AbstractItemRetrievalJobFactory *mJobFactory;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment