summaryrefslogtreecommitdiffstats
path: root/tests/notificationtest.cpp
blob: f0d957e224026a9d5151a75116487dc57615062a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <QtTest>

#include <QString>
#include <QSignalSpy>

#include "store.h"
#include "resourceconfig.h"
#include "resourcecontrol.h"
#include "modelresult.h"
#include "log.h"
#include "test.h"
#include "testutils.h"
#include "notifier.h"
#include "notification.h"

using namespace Sink;
using namespace Sink::ApplicationDomain;

/**
 * Test of complete system using the dummy resource.
 *
 * This test requires the dummy resource installed.
 */
class NotificationTest : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase()
    {
        Sink::Test::initTest();
        ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
    }

    void cleanup()
    {
        VERIFYEXEC(Sink::Store::removeDataFromDisk("sink.dummy.instance1"));
    }

    void testSyncNotifications()
    {
        auto query = Query().resourceFilter("sink.dummy.instance1");
        query.setType<ApplicationDomain::Mail>();
        query.filter("id1");
        query.filter("id2");

        QList<Sink::Notification> statusNotifications;
        QList<Sink::Notification> infoNotifications;
        Sink::Notifier notifier("sink.dummy.instance1");
        notifier.registerHandler([&] (const Sink::Notification &n){
            SinkLogCtx(Sink::Log::Context{"dummyresourcetest"}) << "Received notification " << n;
            if (n.type == Notification::Status) {
                if (n.id == "changereplay") {
                    //We filter all changereplay notifications.
                    //Not the best way but otherwise the test becomes unstable and we currently
                    //only have the id to detect changereplay notifications.
                    return;
                }
                statusNotifications << n;
            }
            if (n.type == Notification::Info) {
                infoNotifications << n;
            }
        });

        // Ensure all local data is processed
        VERIFYEXEC(Sink::Store::synchronize(query));
        VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));

        using namespace Sink::ApplicationDomain;
        {
            QList<Status> expected = {
                Status::ConnectedStatus,
                Status::BusyStatus,
                Status::ConnectedStatus,
            };
            qInfo() << "Received notifications " << statusNotifications;
            QVERIFY2(statusNotifications.size() <= expected.size(), "More notifications than expected.");
            QTRY_COMPARE(statusNotifications.size(), expected.size());
            qInfo() << "All received notifications " << statusNotifications;
            for (auto i = 0; i < statusNotifications.size(); i++) {
                QCOMPARE(statusNotifications.at(i).code, static_cast<int>(expected.at(i)));
            }
        }
        //Changereplay
        // It can happen that we get a changereplay notification pair first and then a second one at the end,
        // we therefore currently filter all changereplay notifications (see above).
        // QCOMPARE(statusNotifications.at(3).code, static_cast<int>(Sink::ApplicationDomain::Status::BusyStatus));
        // QCOMPARE(statusNotifications.at(4).code, static_cast<int>(Sink::ApplicationDomain::Status::ConnectedStatus));

        QTRY_COMPARE(infoNotifications.size(), 2);
        QCOMPARE(infoNotifications.at(0).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncInProgress));
        QCOMPARE(infoNotifications.at(0).entities, QList<QByteArray>{} << "id1" << "id2");
        QCOMPARE(infoNotifications.at(1).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess));
        QCOMPARE(infoNotifications.at(1).entities, QList<QByteArray>{} << "id1" << "id2");

        QCOMPARE(infoNotifications.at(1).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess));
    }

    void testModelNotifications()
    {
        auto query = Query().resourceFilter("sink.dummy.instance1");
        query.setType<ApplicationDomain::Mail>();
        query.setFlags(Query::LiveQuery | Query::UpdateStatus);

        VERIFYEXEC(Sink::Store::synchronize(query));
        VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));

        auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
        QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
        QVERIFY(model->rowCount() >= 1);

        QSignalSpy changedSpy(model.data(), &QAbstractItemModel::dataChanged);
        auto mail = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Mail::Ptr>();
        auto newQuery = query;
        newQuery.filter(mail->identifier());

        QList<int> status;
        QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [&] (const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) {
            QVERIFY(begin.row() == end.row());
            if (begin.row() == 0) {
                status << model->data(begin, Store::StatusRole).value<int>();
                // qWarning() << "New status: " << status.last() << roles;
            }
        });

        //This will trigger a modification of all previous items as well.
        VERIFYEXEC(Sink::Store::synchronize(newQuery));
        VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));

        QCOMPARE(status.size(), 3);
        //Sync progress of item
        QCOMPARE(status.at(0), static_cast<int>(ApplicationDomain::SyncStatus::SyncInProgress));
        QCOMPARE(status.at(1), static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess));
        //Modification triggered during sync
        QCOMPARE(status.at(2), static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess));
    }
};

QTEST_MAIN(NotificationTest)
#include "notificationtest.moc"