File indexing completed on 2024-05-12 05:26:22

0001 #include <QTest>
0002 
0003 #include <QString>
0004 
0005 #include "dummyresource/resourcefactory.h"
0006 #include "store.h"
0007 #include "commands.h"
0008 #include "entitybuffer.h"
0009 #include "resourceconfig.h"
0010 #include "resourcecontrol.h"
0011 #include "modelresult.h"
0012 #include "pipeline.h"
0013 #include "log.h"
0014 #include "test.h"
0015 #include "adaptorfactoryregistry.h"
0016 #include "notifier.h"
0017 #include "propertyregistry.h"
0018 
0019 using namespace Sink;
0020 using namespace Sink::ApplicationDomain;
0021 
0022 /**
0023  * Test of complete system using the dummy resource.
0024  *
0025  * This test requires the dummy resource installed.
0026  */
0027 class DummyResourceTest : public QObject
0028 {
0029     Q_OBJECT
0030 
0031     QTime time;
0032 
0033     Sink::ResourceContext getContext()
0034     {
0035         return Sink::ResourceContext{"sink.dummy.instance1", "sink.dummy", Sink::AdaptorFactoryRegistry::instance().getFactories("sink.dummy")};
0036     }
0037 
0038 
0039     template <typename T>
0040     void testPropertyAccessorAvailability()
0041     {
0042         Event event("sink.dummy.instance1");
0043         VERIFYEXEC(Sink::Store::create<T>(event));
0044 
0045         // Ensure all local data is processed
0046         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
0047 
0048         auto list = Sink::Store::read<T>(Query().resourceFilter("sink.dummy.instance1"));
0049         const auto availableProperties = list.first().availableProperties();
0050         for (const auto &p : Sink::Private::PropertyRegistry::instance().registry[Sink::ApplicationDomain::getTypeName<T>()].properties.keys()) {
0051             QVERIFY2(availableProperties.contains(p), p);
0052         }
0053     }
0054 
0055 private slots:
0056     void initTestCase()
0057     {
0058         Sink::Test::initTest();
0059         auto factory = Sink::ResourceFactory::load("sink.dummy");
0060         QVERIFY(factory);
0061         ::DummyResource::removeFromDisk("sink.dummy.instance1");
0062         ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy");
0063         ResourceConfig::configureResource("sink.dummy.instance1", {{"populate", true}});
0064     }
0065 
0066     void init()
0067     {
0068         qDebug();
0069         qDebug() << "-----------------------------------------";
0070         qDebug();
0071         time.start();
0072     }
0073 
0074     void cleanup()
0075     {
0076         qDebug() << "Test took " << time.elapsed();
0077         VERIFYEXEC(Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1")));
0078     }
0079 
0080     void testProperty()
0081     {
0082         Event event;
0083         event.setProperty("uid", "testuid");
0084         QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
0085     }
0086 
0087     void testWriteToFacadeAndQueryByUid()
0088     {
0089         Event event("sink.dummy.instance1");
0090         event.setProperty("uid", "testuid");
0091         QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
0092         event.setProperty("summary", "summaryValue");
0093         Sink::Store::create<Event>(event).exec().waitForFinished();
0094 
0095         auto query = Query().resourceFilter("sink.dummy.instance1") ;
0096 
0097         // Ensure all local data is processed
0098         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0099 
0100         auto model = Sink::Store::loadModel<Event>(query.filter<Event::Uid>("testuid"));
0101         QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0102         auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0103         QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0104     }
0105 
0106     void testWriteToFacadeAndQueryByUid2()
0107     {
0108         Event event("sink.dummy.instance1");
0109         event.setProperty("summary", "summaryValue");
0110 
0111         event.setProperty("uid", "testuid");
0112         Sink::Store::create<Event>(event).exec().waitForFinished();
0113 
0114         event.setProperty("uid", "testuid2");
0115         Sink::Store::create<Event>(event).exec().waitForFinished();
0116 
0117         auto query = Query().resourceFilter("sink.dummy.instance1") ;
0118 
0119         // Ensure all local data is processed
0120         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0121 
0122         auto model = Sink::Store::loadModel<Event>(query.filter<Event::Uid>("testuid"));
0123         QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0124         auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0125 
0126         qDebug() << value->getProperty("uid").toByteArray();
0127         QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0128     }
0129 
0130     void testWriteToFacadeAndQueryBySummary()
0131     {
0132         Event event("sink.dummy.instance1");
0133 
0134         event.setProperty("uid", "testuid");
0135         event.setProperty("summary", "summaryValue1");
0136         Sink::Store::create<Event>(event).exec().waitForFinished();
0137 
0138         event.setProperty("uid", "testuid2");
0139         event.setProperty("summary", "summaryValue2");
0140         Sink::Store::create<Event>(event).exec().waitForFinished();
0141 
0142         auto query = Query().resourceFilter("sink.dummy.instance1") ;
0143 
0144         // Ensure all local data is processed
0145         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0146 
0147         auto model = Sink::Store::loadModel<Event>(query.filter<Event::Summary>("summaryValue2"));
0148         QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0149         auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0150 
0151         qDebug() << value->getProperty("uid").toByteArray();
0152         QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid2"));
0153     }
0154 
0155     void testResourceSync()
0156     {
0157         ::DummyResource resource(getContext());
0158         VERIFYEXEC(resource.synchronizeWithSource(Sink::QueryBase()));
0159         QVERIFY(!resource.error());
0160         auto processAllMessagesFuture = resource.processAllMessages().exec();
0161         processAllMessagesFuture.waitForFinished();
0162     }
0163 
0164     void testSyncAndFacade()
0165     {
0166         const auto query = Query().resourceFilter("sink.dummy.instance1");
0167 
0168         // Ensure all local data is processed
0169         VERIFYEXEC(Sink::Store::synchronize(query));
0170         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0171 
0172         auto model = Sink::Store::loadModel<Event>(query);
0173         QTRY_VERIFY(model->rowCount(QModelIndex()) >= 1);
0174         auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0175 
0176         QVERIFY(!value->getProperty("summary").toString().isEmpty());
0177         qDebug() << value->getProperty("summary").toString();
0178     }
0179 
0180     void testSyncAndFacadeMail()
0181     {
0182         auto query = Query().resourceFilter("sink.dummy.instance1");
0183         query.request<Mail::Subject>();
0184 
0185         // Ensure all local data is processed
0186         Sink::Store::synchronize(query).exec().waitForFinished();
0187         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0188 
0189         auto model = Sink::Store::loadModel<Mail>(query);
0190         QTRY_VERIFY(model->rowCount(QModelIndex()) >= 1);
0191         auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Mail::Ptr>();
0192 
0193         qWarning() << value->getSubject() << value->identifier();
0194         QVERIFY(!value->getSubject().isEmpty());
0195     }
0196 
0197     void testWriteModifyDelete()
0198     {
0199         Event event("sink.dummy.instance1");
0200         event.setProperty("uid", "testuid");
0201         QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
0202         event.setProperty("summary", "summaryValue");
0203         Sink::Store::create<Event>(event).exec().waitForFinished();
0204 
0205         auto query = Query().resourceFilter("sink.dummy.instance1").filter<Event::Uid>("testuid");
0206 
0207         // Ensure all local data is processed
0208         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0209 
0210         // Test create
0211         Event event2;
0212         {
0213             auto model = Sink::Store::loadModel<Event>(query);
0214             QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0215             auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0216 
0217             QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0218             QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue"));
0219             event2 = *value;
0220         }
0221 
0222         event2.setProperty("uid", "testuid");
0223         event2.setProperty("summary", "summaryValue2");
0224         Sink::Store::modify<Event>(event2).exec().waitForFinished();
0225 
0226         // Ensure all local data is processed
0227         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0228 
0229         // Test modify
0230         {
0231             auto model = Sink::Store::loadModel<Event>(query);
0232             QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0233             auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0234 
0235             QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0236             QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2"));
0237         }
0238 
0239         Sink::Store::remove<Event>(event2).exec().waitForFinished();
0240 
0241         // Ensure all local data is processed
0242         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1"));
0243 
0244         // Test remove
0245         {
0246             auto model = Sink::Store::loadModel<Event>(query);
0247             QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
0248             QTRY_COMPARE(model->rowCount(QModelIndex()), 0);
0249         }
0250     }
0251 
0252     void testWriteModifyDeleteLive()
0253     {
0254         auto query = Query().resourceFilter("sink.dummy.instance1");
0255         query.setFlags(Query::LiveQuery);
0256         query.filter<Event::Uid>("testuid");
0257 
0258         auto model = Sink::Store::loadModel<Event>(query);
0259         QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
0260 
0261         Event event("sink.dummy.instance1");
0262         event.setProperty("uid", "testuid");
0263         QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid"));
0264         event.setProperty("summary", "summaryValue");
0265         VERIFYEXEC(Sink::Store::create<Event>(event));
0266 
0267         // Test create
0268         Event event2;
0269         {
0270             QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0271             auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0272             QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0273             QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue"));
0274             event2 = *value;
0275         }
0276 
0277         event2.setProperty("uid", "testuid");
0278         event2.setProperty("summary", "summaryValue2");
0279         Sink::Store::modify<Event>(event2).exec().waitForFinished();
0280 
0281         // Test modify
0282         {
0283             // TODO wait for a change signal
0284             QTRY_COMPARE(model->rowCount(QModelIndex()), 1);
0285             auto value = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value<Event::Ptr>();
0286             QCOMPARE(value->getProperty("uid").toByteArray(), QByteArray("testuid"));
0287             QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2"));
0288         }
0289 
0290         Sink::Store::remove<Event>(event2).exec().waitForFinished();
0291 
0292         // Test remove
0293         {
0294             QTRY_COMPARE(model->rowCount(QModelIndex()), 0);
0295         }
0296     }
0297 
0298     /*
0299      * Ensure we have an accessor for every registered property.
0300      * The PropertyRegistry can list available properties,
0301      * and an entity loaded from disk uses the property mapper to report available properties.
0302      *
0303      * If we don't either have a serializer or an index access, then the property will not be accessible at all,
0304      * so this is a good sanity check.
0305      *
0306      * This test is resource specific because resources can in principle override how accessors are used via DomainTypeAdaptorFactory.
0307      */
0308     void testPropertyAccessorAvailability()
0309     {
0310         testPropertyAccessorAvailability<Event>();
0311         testPropertyAccessorAvailability<Mail>();
0312         testPropertyAccessorAvailability<Todo>();
0313         testPropertyAccessorAvailability<Folder>();
0314         testPropertyAccessorAvailability<Calendar>();
0315         testPropertyAccessorAvailability<Contact>();
0316         testPropertyAccessorAvailability<Addressbook>();
0317     }
0318 };
0319 
0320 QTEST_MAIN(DummyResourceTest)
0321 #include "dummyresourcetest.moc"