monitornotificationtest.cpp 9.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
    Copyright (c) 2011 Stephen Kelly <steveire@gmail.com>

    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.
*/

Laurent Montel's avatar
Laurent Montel committed
20
#include "monitor.h"
21 22 23 24

#include "fakeserverdata.h"
#include "fakesession.h"
#include "inspectablemonitor.h"
25
#include "inspectablechangerecorder.h"
Laurent Montel's avatar
Laurent Montel committed
26
#include "akonaditestfake_export.h"
Laurent Montel's avatar
Laurent Montel committed
27 28
#include <QTest>
#include <QSignalSpy>
29 30 31

using namespace Akonadi;

32
class MonitorNotificationTest : public QObject
33
{
Laurent Montel's avatar
Laurent Montel committed
34 35
    Q_OBJECT
public:
Laurent Montel's avatar
Laurent Montel committed
36
    MonitorNotificationTest(QObject *parent = nullptr)
Laurent Montel's avatar
Laurent Montel committed
37 38 39 40 41 42
        : QObject(parent)
    {
        m_sessionName = "MonitorNotificationTest fake session";
        m_fakeSession = new FakeSession(m_sessionName, FakeSession::EndJobsImmediately);
        m_fakeSession->setAsDefaultSession();
    }
43 44

private Q_SLOTS:
Laurent Montel's avatar
Laurent Montel committed
45 46 47
    void testSingleMessage();
    void testFillPipeline();
    void testMonitor();
48

Laurent Montel's avatar
Laurent Montel committed
49 50 51
    void testSingleMessage_data();
    void testFillPipeline_data();
    void testMonitor_data();
52 53

private:
Laurent Montel's avatar
Laurent Montel committed
54 55 56 57 58 59
    template<typename MonitorImpl>
    void testSingleMessage_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache);
    template<typename MonitorImpl>
    void testFillPipeline_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache);
    template<typename MonitorImpl>
    void testMonitor_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache);
60

61
private:
Laurent Montel's avatar
Laurent Montel committed
62 63
    FakeSession *m_fakeSession;
    QByteArray m_sessionName;
64 65
};

66 67
void MonitorNotificationTest::testSingleMessage_data()
{
Laurent Montel's avatar
Laurent Montel committed
68
    QTest::addColumn<bool>("useChangeRecorder");
69

Laurent Montel's avatar
Laurent Montel committed
70 71
    QTest::newRow("useChangeRecorder") << true;
    QTest::newRow("useMonitor") << false;
72 73
}

74 75
void MonitorNotificationTest::testSingleMessage()
{
Laurent Montel's avatar
Laurent Montel committed
76 77 78 79 80 81 82 83 84 85 86 87 88
    QFETCH(bool, useChangeRecorder);

    FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession);
    FakeItemCache *itemCache = new FakeItemCache(m_fakeSession);
    FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache);

    if (!useChangeRecorder) {
        testSingleMessage_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache);
    } else {
        InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this);
        changeRecorder->setChangeRecordingEnabled(false);
        testSingleMessage_impl(changeRecorder, collectionCache, itemCache);
    }
89 90 91 92 93
}

template <typename MonitorImpl>
void MonitorNotificationTest::testSingleMessage_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache)
{
Laurent Montel's avatar
Laurent Montel committed
94
    Q_UNUSED(itemCache)
95

96 97 98
    // Workaround for the QTimer::singleShot() in fake monitors to happen
    QTest::qWait(10);

Laurent Montel's avatar
Laurent Montel committed
99 100
    monitor->setSession(m_fakeSession);
    monitor->fetchCollection(true);
101

102
    Protocol::ChangeNotificationList list;
103

Laurent Montel's avatar
Laurent Montel committed
104 105
    Collection parent(1);
    Collection added(2);
106

107 108 109 110
    auto msg = Protocol::CollectionChangeNotificationPtr::create();
    msg->setParentCollection(parent.id());
    msg->setOperation(Protocol::CollectionChangeNotification::Add);
    msg->setId(added.id());
111

Laurent Montel's avatar
Laurent Montel committed
112 113 114
    QHash<Collection::Id, Collection> data;
    data.insert(parent.id(), parent);
    data.insert(added.id(), added);
115

Laurent Montel's avatar
Laurent Montel committed
116
    // Pending notifications remains empty because we don't fill the pipeline with one message.
117

Laurent Montel's avatar
Laurent Montel committed
118 119
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
120

121
    monitor->notificationConnection()->emitNotify(msg);
122

Laurent Montel's avatar
Laurent Montel committed
123 124
    QCOMPARE(monitor->pipeline().size(), 1);
    QVERIFY(monitor->pendingNotifications().isEmpty());
125

Laurent Montel's avatar
Laurent Montel committed
126 127
    collectionCache->setData(data);
    collectionCache->emitDataAvailable();
128

Laurent Montel's avatar
Laurent Montel committed
129 130
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
131 132
}

133 134
void MonitorNotificationTest::testFillPipeline_data()
{
Laurent Montel's avatar
Laurent Montel committed
135
    QTest::addColumn<bool>("useChangeRecorder");
136

Laurent Montel's avatar
Laurent Montel committed
137 138
    QTest::newRow("useChangeRecorder") << true;
    QTest::newRow("useMonitor") << false;
139 140
}

141 142
void MonitorNotificationTest::testFillPipeline()
{
Laurent Montel's avatar
Laurent Montel committed
143 144 145 146 147 148 149 150 151 152 153 154 155
    QFETCH(bool, useChangeRecorder);

    FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession);
    FakeItemCache *itemCache = new FakeItemCache(m_fakeSession);
    FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache);

    if (!useChangeRecorder) {
        testFillPipeline_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache);
    } else {
        InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this);
        changeRecorder->setChangeRecordingEnabled(false);
        testFillPipeline_impl(changeRecorder, collectionCache, itemCache);
    }
156 157 158 159 160
}

template <typename MonitorImpl>
void MonitorNotificationTest::testFillPipeline_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache)
{
Laurent Montel's avatar
Laurent Montel committed
161
    Q_UNUSED(itemCache)
162

Laurent Montel's avatar
Laurent Montel committed
163 164
    monitor->setSession(m_fakeSession);
    monitor->fetchCollection(true);
165

166
    Protocol::ChangeNotificationList list;
Laurent Montel's avatar
Laurent Montel committed
167
    QHash<Collection::Id, Collection> data;
168

Laurent Montel's avatar
Laurent Montel committed
169 170 171 172
    int i = 1;
    while (i < 40) {
        Collection parent(i++);
        Collection added(i++);
173

174 175 176 177
        auto msg = Protocol::CollectionChangeNotificationPtr::create();
        msg->setParentCollection(parent.id());
        msg->setOperation(Protocol::CollectionChangeNotification::Add);
        msg->setId(added.id());
178

Laurent Montel's avatar
Laurent Montel committed
179 180
        data.insert(parent.id(), parent);
        data.insert(added.id(), added);
181

Laurent Montel's avatar
Laurent Montel committed
182 183
        list << msg;
    }
184

Laurent Montel's avatar
Laurent Montel committed
185 186
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
187

188
    Q_FOREACH (const Protocol::ChangeNotificationPtr &ntf, list) {
189
        monitor->notificationConnection()->emitNotify(ntf);
Laurent Montel's avatar
Laurent Montel committed
190
    }
191

Laurent Montel's avatar
Laurent Montel committed
192 193
    QCOMPARE(monitor->pipeline().size(), 5);
    QCOMPARE(monitor->pendingNotifications().size(), 15);
194

Laurent Montel's avatar
Laurent Montel committed
195 196
    collectionCache->setData(data);
    collectionCache->emitDataAvailable();
197

Laurent Montel's avatar
Laurent Montel committed
198 199
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
200 201
}

202
void MonitorNotificationTest::testMonitor_data()
Stephen Kelly's avatar
Stephen Kelly committed
203
{
Laurent Montel's avatar
Laurent Montel committed
204
    QTest::addColumn<bool>("useChangeRecorder");
Stephen Kelly's avatar
Stephen Kelly committed
205

Laurent Montel's avatar
Laurent Montel committed
206 207
    QTest::newRow("useChangeRecorder") << true;
    QTest::newRow("useMonitor") << false;
Stephen Kelly's avatar
Stephen Kelly committed
208 209
}

210
void MonitorNotificationTest::testMonitor()
Stephen Kelly's avatar
Stephen Kelly committed
211
{
Laurent Montel's avatar
Laurent Montel committed
212 213 214 215 216 217 218 219 220 221 222 223 224
    QFETCH(bool, useChangeRecorder);

    FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession);
    FakeItemCache *itemCache = new FakeItemCache(m_fakeSession);
    FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache);

    if (!useChangeRecorder) {
        testMonitor_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache);
    } else {
        InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this);
        changeRecorder->setChangeRecordingEnabled(false);
        testMonitor_impl(changeRecorder, collectionCache, itemCache);
    }
Stephen Kelly's avatar
Stephen Kelly committed
225 226 227
}

template <typename MonitorImpl>
228
void MonitorNotificationTest::testMonitor_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache)
Stephen Kelly's avatar
Stephen Kelly committed
229
{
Laurent Montel's avatar
Laurent Montel committed
230
    Q_UNUSED(itemCache)
Stephen Kelly's avatar
Stephen Kelly committed
231

Laurent Montel's avatar
Laurent Montel committed
232 233
    monitor->setSession(m_fakeSession);
    monitor->fetchCollection(true);
Stephen Kelly's avatar
Stephen Kelly committed
234

235
    Protocol::ChangeNotificationList list;
Stephen Kelly's avatar
Stephen Kelly committed
236

Laurent Montel's avatar
Laurent Montel committed
237 238
    Collection col2(2);
    col2.setParentCollection(Collection::root());
Stephen Kelly's avatar
Stephen Kelly committed
239

Laurent Montel's avatar
Laurent Montel committed
240
    collectionCache->insert(col2);
Stephen Kelly's avatar
Stephen Kelly committed
241

Laurent Montel's avatar
Laurent Montel committed
242
    int i = 4;
Stephen Kelly's avatar
Stephen Kelly committed
243

Laurent Montel's avatar
Laurent Montel committed
244 245
    while (i < 8) {
        Collection added(i++);
Stephen Kelly's avatar
Stephen Kelly committed
246

247 248 249 250
        auto msg = Protocol::CollectionChangeNotificationPtr::create();
        msg->setParentCollection(i % 2 ? 2 : added.id() - 1);
        msg->setOperation(Protocol::CollectionChangeNotification::Add);
        msg->setId(added.id());
Stephen Kelly's avatar
Stephen Kelly committed
251

Laurent Montel's avatar
Laurent Montel committed
252 253
        list << msg;
    }
Stephen Kelly's avatar
Stephen Kelly committed
254

Laurent Montel's avatar
Laurent Montel committed
255 256
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
Stephen Kelly's avatar
Stephen Kelly committed
257

Laurent Montel's avatar
Laurent Montel committed
258 259 260 261
    Collection col4(4);
    col4.setParentCollection(col2);
    Collection col6(6);
    col6.setParentCollection(col2);
Stephen Kelly's avatar
Stephen Kelly committed
262

Laurent Montel's avatar
Laurent Montel committed
263 264
    collectionCache->insert(col4);
    collectionCache->insert(col6);
Stephen Kelly's avatar
Stephen Kelly committed
265

Laurent Montel's avatar
Laurent Montel committed
266 267
    qRegisterMetaType<Akonadi::Collection>();
    QSignalSpy collectionAddedSpy(monitor, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)));
Stephen Kelly's avatar
Stephen Kelly committed
268

Laurent Montel's avatar
Laurent Montel committed
269
    collectionCache->emitDataAvailable();
Stephen Kelly's avatar
Stephen Kelly committed
270

Laurent Montel's avatar
Laurent Montel committed
271 272
    QVERIFY(monitor->pipeline().isEmpty());
    QVERIFY(monitor->pendingNotifications().isEmpty());
Stephen Kelly's avatar
Stephen Kelly committed
273

274
    Q_FOREACH (const Protocol::ChangeNotificationPtr &ntf, list) {
275
        monitor->notificationConnection()->emitNotify(ntf);
Laurent Montel's avatar
Laurent Montel committed
276
    }
Stephen Kelly's avatar
Stephen Kelly committed
277

Laurent Montel's avatar
Laurent Montel committed
278 279 280 281 282
    // Collection 6 is not notified, because Collection 5 has held up the pipeline
    QCOMPARE(collectionAddedSpy.size(), 1);
    QCOMPARE((int)collectionAddedSpy.takeFirst().first().value<Akonadi::Collection>().id(), 4);
    QCOMPARE(monitor->pipeline().size(), 3);
    QCOMPARE(monitor->pendingNotifications().size(), 0);
Stephen Kelly's avatar
Stephen Kelly committed
283

Laurent Montel's avatar
Laurent Montel committed
284 285
    Collection col7(7);
    col7.setParentCollection(col6);
Stephen Kelly's avatar
Stephen Kelly committed
286

Laurent Montel's avatar
Laurent Montel committed
287 288
    collectionCache->insert(col7);
    collectionCache->emitDataAvailable();
Stephen Kelly's avatar
Stephen Kelly committed
289

Laurent Montel's avatar
Laurent Montel committed
290 291 292 293
    // Collection 5 is still holding the pipeline
    QCOMPARE(collectionAddedSpy.size(), 0);
    QCOMPARE(monitor->pipeline().size(), 3);
    QCOMPARE(monitor->pendingNotifications().size(), 0);
Stephen Kelly's avatar
Stephen Kelly committed
294

Laurent Montel's avatar
Laurent Montel committed
295 296
    Collection col5(5);
    col5.setParentCollection(col4);
Stephen Kelly's avatar
Stephen Kelly committed
297

Laurent Montel's avatar
Laurent Montel committed
298 299
    collectionCache->insert(col5);
    collectionCache->emitDataAvailable();
Stephen Kelly's avatar
Stephen Kelly committed
300

Laurent Montel's avatar
Laurent Montel committed
301 302 303 304
    // Collection 5 is in cache, pipeline is flushed
    QCOMPARE(collectionAddedSpy.size(), 3);
    QCOMPARE(monitor->pipeline().size(), 0);
    QCOMPARE(monitor->pendingNotifications().size(), 0);
Stephen Kelly's avatar
Stephen Kelly committed
305 306
}

Laurent Montel's avatar
Laurent Montel committed
307
QTEST_MAIN(MonitorNotificationTest)
308
#include "monitornotificationtest.moc"