File indexing completed on 2024-05-12 05:26:24
0001 #include <QTest> 0002 0003 #include <QString> 0004 #include <QSignalSpy> 0005 0006 #include "store.h" 0007 #include "resourceconfig.h" 0008 #include "resourcecontrol.h" 0009 #include "modelresult.h" 0010 #include "log.h" 0011 #include "test.h" 0012 #include "notifier.h" 0013 #include "notification.h" 0014 0015 using namespace Sink; 0016 using namespace Sink::ApplicationDomain; 0017 0018 /** 0019 * Test of complete system using the dummy resource. 0020 * 0021 * This test requires the dummy resource installed. 0022 */ 0023 class NotificationTest : public QObject 0024 { 0025 Q_OBJECT 0026 0027 private slots: 0028 void initTestCase() 0029 { 0030 Sink::Test::initTest(); 0031 ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy"); 0032 ResourceConfig::configureResource("sink.dummy.instance1", {{"populate", true}}); 0033 } 0034 0035 void cleanup() 0036 { 0037 VERIFYEXEC(Sink::Store::removeDataFromDisk("sink.dummy.instance1")); 0038 } 0039 0040 void testSyncNotifications() 0041 { 0042 auto query = Query().resourceFilter("sink.dummy.instance1"); 0043 query.setType<ApplicationDomain::Mail>(); 0044 query.filter("id1"); 0045 query.filter("id2"); 0046 0047 QList<Sink::Notification> statusNotifications; 0048 QList<Sink::Notification> infoNotifications; 0049 Sink::Notifier notifier("sink.dummy.instance1"); 0050 notifier.registerHandler([&] (const Sink::Notification &n){ 0051 SinkLogCtx(Sink::Log::Context{"dummyresourcetest"}) << "Received notification " << n; 0052 if (n.type == Notification::Status) { 0053 if (n.id == "changereplay") { 0054 //We filter all changereplay notifications. 0055 //Not the best way but otherwise the test becomes unstable and we currently 0056 //only have the id to detect changereplay notifications. 0057 return; 0058 } 0059 statusNotifications << n; 0060 } 0061 if (n.type == Notification::Info) { 0062 infoNotifications << n; 0063 } 0064 }); 0065 0066 // Ensure all local data is processed 0067 VERIFYEXEC(Sink::Store::synchronize(query)); 0068 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); 0069 0070 using namespace Sink::ApplicationDomain; 0071 { 0072 QList<Status> expected = { 0073 Status::ConnectedStatus, 0074 Status::BusyStatus, 0075 Status::ConnectedStatus, 0076 }; 0077 qInfo() << "Received notifications " << statusNotifications; 0078 QVERIFY2(statusNotifications.size() <= expected.size(), "More notifications than expected."); 0079 QTRY_COMPARE(statusNotifications.size(), expected.size()); 0080 qInfo() << "All received notifications " << statusNotifications; 0081 for (auto i = 0; i < statusNotifications.size(); i++) { 0082 QCOMPARE(statusNotifications.at(i).code, static_cast<int>(expected.at(i))); 0083 } 0084 } 0085 //Changereplay 0086 // It can happen that we get a changereplay notification pair first and then a second one at the end, 0087 // we therefore currently filter all changereplay notifications (see above). 0088 // QCOMPARE(statusNotifications.at(3).code, static_cast<int>(Sink::ApplicationDomain::Status::BusyStatus)); 0089 // QCOMPARE(statusNotifications.at(4).code, static_cast<int>(Sink::ApplicationDomain::Status::ConnectedStatus)); 0090 0091 QTRY_COMPARE(infoNotifications.size(), 2); 0092 QCOMPARE(infoNotifications.at(0).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncInProgress)); 0093 QCOMPARE(infoNotifications.at(0).entities, QList<QByteArray>{} << "id1" << "id2"); 0094 QCOMPARE(infoNotifications.at(1).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess)); 0095 QCOMPARE(infoNotifications.at(1).entities, QList<QByteArray>{} << "id1" << "id2"); 0096 0097 QCOMPARE(infoNotifications.at(1).code, static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess)); 0098 } 0099 0100 void testModelNotifications() 0101 { 0102 auto query = Query().resourceFilter("sink.dummy.instance1"); 0103 query.setType<ApplicationDomain::Mail>(); 0104 query.setFlags(Query::LiveQuery | Query::UpdateStatus); 0105 0106 VERIFYEXEC(Sink::Store::synchronize(query)); 0107 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); 0108 0109 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); 0110 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); 0111 QVERIFY(model->rowCount() >= 1); 0112 0113 QSignalSpy changedSpy(model.data(), &QAbstractItemModel::dataChanged); 0114 auto mail = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Mail::Ptr>(); 0115 auto newQuery = query; 0116 newQuery.filter(mail->identifier()); 0117 0118 //We can make no assumptions about the amount of notifications because we collect on every dataChanged signal, even if the status did not change. 0119 QSet<int> status; 0120 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [&] (const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) { 0121 QVERIFY(begin.row() == end.row()); 0122 if (begin.row() == 0) { 0123 status << model->data(begin, Store::StatusRole).value<int>(); 0124 // qWarning() << "New status: " << status.last() << roles; 0125 } 0126 }); 0127 0128 //This will trigger a modification of all previous items as well. 0129 VERIFYEXEC(Sink::Store::synchronize(newQuery)); 0130 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); 0131 0132 QTRY_VERIFY(status.contains(static_cast<int>(ApplicationDomain::SyncStatus::SyncInProgress)) && static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess)); 0133 } 0134 0135 void testNotifier() 0136 { 0137 QList<int> status; 0138 Sink::Notifier notifier{Sink::Query{Sink::Query::LiveQuery}.resourceFilter("sink.dummy.instance2")}; 0139 notifier.registerHandler([&] (const Sink::Notification ¬ification) { 0140 if (notification.type == Notification::Info) { 0141 status << notification.code; 0142 } 0143 }); 0144 0145 auto query = Query().resourceFilter("sink.dummy.instance2"); 0146 query.setType<ApplicationDomain::Mail>(); 0147 query.setFlags(Query::LiveQuery | Query::UpdateStatus); 0148 0149 auto resource = ApplicationDomain::ApplicationDomainType::createEntity<ApplicationDomain::SinkResource>("", "sink.dummy.instance2"); 0150 resource.setResourceType("sink.dummy"); 0151 VERIFYEXEC(Store::create(resource)); 0152 0153 VERIFYEXEC(Sink::Store::synchronize(query)); 0154 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance2")); 0155 0156 QTRY_COMPARE(status.size(), 2); 0157 //Sync progress of item 0158 QCOMPARE(status.at(0), static_cast<int>(ApplicationDomain::SyncStatus::SyncInProgress)); 0159 QCOMPARE(status.at(1), static_cast<int>(ApplicationDomain::SyncStatus::SyncSuccess)); 0160 } 0161 0162 }; 0163 0164 QTEST_MAIN(NotificationTest) 0165 #include "notificationtest.moc"