diff options
Diffstat (limited to 'tests/clientapitest.cpp')
-rw-r--r-- | tests/clientapitest.cpp | 218 |
1 files changed, 165 insertions, 53 deletions
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index 665d29b..8f956ab 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp | |||
@@ -4,30 +4,60 @@ | |||
4 | 4 | ||
5 | #include "clientapi.h" | 5 | #include "clientapi.h" |
6 | #include "facade.h" | 6 | #include "facade.h" |
7 | #include "synclistresult.h" | ||
8 | #include "resourceconfig.h" | 7 | #include "resourceconfig.h" |
8 | #include "modelresult.h" | ||
9 | #include "resultprovider.h" | ||
10 | #include "facadefactory.h" | ||
9 | 11 | ||
10 | class DummyResourceFacade : public Akonadi2::StoreFacade<Akonadi2::ApplicationDomain::Event> | 12 | template <typename T> |
13 | class DummyResourceFacade : public Akonadi2::StoreFacade<T> | ||
11 | { | 14 | { |
12 | public: | 15 | public: |
16 | static std::shared_ptr<DummyResourceFacade<T> > registerFacade() | ||
17 | { | ||
18 | auto facade = std::make_shared<DummyResourceFacade<T> >(); | ||
19 | Akonadi2::FacadeFactory::instance().registerFacade<T, DummyResourceFacade<T> >("dummyresource", | ||
20 | [facade](const QByteArray &instanceIdentifier) { | ||
21 | return facade; | ||
22 | } | ||
23 | ); | ||
24 | return facade; | ||
25 | } | ||
13 | ~DummyResourceFacade(){}; | 26 | ~DummyResourceFacade(){}; |
14 | KAsync::Job<void> create(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 27 | KAsync::Job<void> create(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; |
15 | KAsync::Job<void> modify(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 28 | KAsync::Job<void> modify(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; |
16 | KAsync::Job<void> remove(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; | 29 | KAsync::Job<void> remove(const T &domainObject) Q_DECL_OVERRIDE { return KAsync::null<void>(); }; |
17 | KAsync::Job<void> load(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::ResultProvider<Akonadi2::ApplicationDomain::Event::Ptr> > &resultProvider) Q_DECL_OVERRIDE | 30 | QPair<KAsync::Job<void>, typename Akonadi2::ResultEmitter<typename T::Ptr>::Ptr > load(const Akonadi2::Query &query) Q_DECL_OVERRIDE |
18 | { | 31 | { |
19 | capturedResultProvider = resultProvider; | 32 | auto resultProvider = new Akonadi2::ResultProvider<typename T::Ptr>(); |
20 | return KAsync::start<void>([this, resultProvider, query]() { | 33 | resultProvider->onDone([resultProvider]() { |
34 | Trace() << "Result provider is done"; | ||
35 | delete resultProvider; | ||
36 | }); | ||
37 | //We have to do it this way, otherwise we're not setting the fetcher right | ||
38 | auto emitter = resultProvider->emitter(); | ||
39 | |||
40 | resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { | ||
41 | Trace() << "Running the fetcher"; | ||
21 | for (const auto &res : results) { | 42 | for (const auto &res : results) { |
22 | resultProvider->add(res); | 43 | qDebug() << "Parent filter " << query.propertyFilter.value("parent").toByteArray() << res->identifier(); |
44 | if (!query.propertyFilter.contains("parent") || query.propertyFilter.value("parent").toByteArray() == res->getProperty("parent").toByteArray()) { | ||
45 | resultProvider->add(res); | ||
46 | } | ||
23 | } | 47 | } |
48 | resultProvider->initialResultSetComplete(parent); | ||
49 | }); | ||
50 | auto job = KAsync::start<void>([query, resultProvider]() { | ||
24 | }); | 51 | }); |
52 | mResultProvider = resultProvider; | ||
53 | return qMakePair(job, emitter); | ||
25 | } | 54 | } |
26 | 55 | ||
27 | QList<Akonadi2::ApplicationDomain::Event::Ptr> results; | 56 | QList<typename T::Ptr> results; |
28 | QWeakPointer<Akonadi2::ResultProvider<Akonadi2::ApplicationDomain::Event::Ptr> > capturedResultProvider; | 57 | Akonadi2::ResultProviderInterface<typename T::Ptr> *mResultProvider; |
29 | }; | 58 | }; |
30 | 59 | ||
60 | |||
31 | /** | 61 | /** |
32 | * Test of the client api implementation. | 62 | * Test of the client api implementation. |
33 | * | 63 | * |
@@ -38,56 +68,26 @@ class ClientAPITest : public QObject | |||
38 | Q_OBJECT | 68 | Q_OBJECT |
39 | private Q_SLOTS: | 69 | private Q_SLOTS: |
40 | 70 | ||
41 | static std::shared_ptr<DummyResourceFacade> registerDummyFacade() | ||
42 | { | ||
43 | auto facade = std::make_shared<DummyResourceFacade>(); | ||
44 | Akonadi2::FacadeFactory::instance().registerFacade<Akonadi2::ApplicationDomain::Event, DummyResourceFacade>("dummyresource", | ||
45 | [facade](const QByteArray &instanceIdentifier) { | ||
46 | return facade; | ||
47 | } | ||
48 | ); | ||
49 | return facade; | ||
50 | } | ||
51 | |||
52 | void initTestCase() | 71 | void initTestCase() |
53 | { | 72 | { |
54 | Akonadi2::FacadeFactory::instance().resetFactory(); | 73 | Akonadi2::FacadeFactory::instance().resetFactory(); |
55 | ResourceConfig::clear(); | 74 | ResourceConfig::clear(); |
75 | Akonadi2::Log::setDebugOutputLevel(Akonadi2::Log::Trace); | ||
56 | } | 76 | } |
57 | 77 | ||
58 | void testLoad() | 78 | void testLoad() |
59 | { | 79 | { |
60 | auto facade = registerDummyFacade(); | 80 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Event>::registerFacade(); |
61 | facade->results << QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor>()); | 81 | facade->results << QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); |
62 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | 82 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); |
63 | 83 | ||
64 | Akonadi2::Query query; | 84 | Akonadi2::Query query; |
65 | query.resources << "dummyresource.instance1"; | 85 | query.resources << "dummyresource.instance1"; |
66 | query.liveQuery = false; | 86 | query.liveQuery = false; |
67 | 87 | ||
68 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::Event>(query)); | 88 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Event>(query); |
69 | result.exec(); | 89 | QTRY_VERIFY(model->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()); |
70 | QCOMPARE(result.size(), 1); | 90 | QCOMPARE(model->rowCount(QModelIndex()), 1); |
71 | } | ||
72 | |||
73 | //The query provider is supposed to delete itself | ||
74 | void testQueryLifetime() | ||
75 | { | ||
76 | auto facade = registerDummyFacade(); | ||
77 | facade->results << QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor>()); | ||
78 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
79 | |||
80 | Akonadi2::Query query; | ||
81 | query.resources << "dummyresource.instance1"; | ||
82 | query.liveQuery = true; | ||
83 | |||
84 | { | ||
85 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::Event>(query)); | ||
86 | result.exec(); | ||
87 | QCOMPARE(result.size(), 1); | ||
88 | } | ||
89 | //It's running in a separate thread, so we have to wait for a moment until the query provider deletes itself. | ||
90 | QTRY_VERIFY(!facade->capturedResultProvider); | ||
91 | } | 91 | } |
92 | 92 | ||
93 | //TODO: This test doesn't belong to this testsuite | 93 | //TODO: This test doesn't belong to this testsuite |
@@ -104,21 +104,133 @@ private Q_SLOTS: | |||
104 | { | 104 | { |
105 | Akonadi2::Query query; | 105 | Akonadi2::Query query; |
106 | query.propertyFilter.insert("type", "dummyresource"); | 106 | query.propertyFilter.insert("type", "dummyresource"); |
107 | async::SyncListResult<Akonadi2::ApplicationDomain::AkonadiResource::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::AkonadiResource>(query)); | 107 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::AkonadiResource>(query); |
108 | result.exec(); | 108 | QTRY_COMPARE(model->rowCount(QModelIndex()), 1); |
109 | QCOMPARE(result.size(), 1); | ||
110 | } | 109 | } |
111 | 110 | ||
112 | Akonadi2::Store::remove(res).exec().waitForFinished(); | 111 | Akonadi2::Store::remove(res).exec().waitForFinished(); |
113 | { | 112 | { |
114 | Akonadi2::Query query; | 113 | Akonadi2::Query query; |
115 | query.propertyFilter.insert("type", "dummyresource"); | 114 | query.propertyFilter.insert("type", "dummyresource"); |
116 | async::SyncListResult<Akonadi2::ApplicationDomain::AkonadiResource::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::AkonadiResource>(query)); | 115 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::AkonadiResource>(query); |
117 | result.exec(); | 116 | QTRY_VERIFY(model->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()); |
118 | QCOMPARE(result.size(), 0); | 117 | QCOMPARE(model->rowCount(QModelIndex()), 0); |
119 | } | 118 | } |
120 | } | 119 | } |
121 | 120 | ||
121 | void testModelSingle() | ||
122 | { | ||
123 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Folder>::registerFacade(); | ||
124 | facade->results << QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
125 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
126 | |||
127 | Akonadi2::Query query; | ||
128 | query.resources << "dummyresource.instance1"; | ||
129 | query.liveQuery = false; | ||
130 | |||
131 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Folder>(query); | ||
132 | QTRY_COMPARE(model->rowCount(), 1); | ||
133 | } | ||
134 | |||
135 | void testModelNested() | ||
136 | { | ||
137 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Folder>::registerFacade(); | ||
138 | auto folder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
139 | auto subfolder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
140 | subfolder->setProperty("parent", "id"); | ||
141 | facade->results << folder << subfolder; | ||
142 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
143 | |||
144 | //Test | ||
145 | Akonadi2::Query query; | ||
146 | query.resources << "dummyresource.instance1"; | ||
147 | query.liveQuery = false; | ||
148 | query.parentProperty = "parent"; | ||
149 | |||
150 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Folder>(query); | ||
151 | QTRY_VERIFY(model->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()); | ||
152 | QCOMPARE(model->rowCount(), 1); | ||
153 | model->fetchMore(model->index(0, 0)); | ||
154 | QTRY_VERIFY(model->data(model->index(0, 0), Akonadi2::Store::ChildrenFetchedRole).toBool()); | ||
155 | QCOMPARE(model->rowCount(model->index(0, 0)), 1); | ||
156 | } | ||
157 | |||
158 | void testModelSignals() | ||
159 | { | ||
160 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Folder>::registerFacade(); | ||
161 | auto folder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
162 | auto subfolder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
163 | subfolder->setProperty("parent", "id"); | ||
164 | facade->results << folder << subfolder; | ||
165 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
166 | |||
167 | //Test | ||
168 | Akonadi2::Query query; | ||
169 | query.resources << "dummyresource.instance1"; | ||
170 | query.liveQuery = false; | ||
171 | query.parentProperty = "parent"; | ||
172 | |||
173 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Folder>(query); | ||
174 | QSignalSpy spy(model.data(), SIGNAL(rowsInserted(const QModelIndex &, int, int))); | ||
175 | QVERIFY(spy.isValid()); | ||
176 | model->fetchMore(model->index(0, 0)); | ||
177 | QTRY_VERIFY(spy.count() >= 1); | ||
178 | } | ||
179 | |||
180 | void testModelNestedLive() | ||
181 | { | ||
182 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Folder>::registerFacade(); | ||
183 | auto folder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
184 | auto subfolder = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "subId", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
185 | subfolder->setProperty("parent", "id"); | ||
186 | facade->results << folder << subfolder; | ||
187 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
188 | |||
189 | //Test | ||
190 | Akonadi2::Query query; | ||
191 | query.resources << "dummyresource.instance1"; | ||
192 | query.liveQuery = true; | ||
193 | query.parentProperty = "parent"; | ||
194 | |||
195 | auto model = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Folder>(query); | ||
196 | QTRY_COMPARE(model->rowCount(), 1); | ||
197 | model->fetchMore(model->index(0, 0)); | ||
198 | QTRY_COMPARE(model->rowCount(model->index(0, 0)), 1); | ||
199 | |||
200 | auto resultProvider = facade->mResultProvider; | ||
201 | |||
202 | //Test new toplevel folder | ||
203 | { | ||
204 | QSignalSpy rowsInsertedSpy(model.data(), SIGNAL(rowsInserted(const QModelIndex &, int, int))); | ||
205 | auto folder2 = QSharedPointer<Akonadi2::ApplicationDomain::Folder>::create("resource", "id2", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
206 | resultProvider->add(folder2); | ||
207 | QTRY_COMPARE(model->rowCount(), 2); | ||
208 | QTRY_COMPARE(rowsInsertedSpy.count(), 1); | ||
209 | QCOMPARE(rowsInsertedSpy.at(0).at(0).value<QModelIndex>(), QModelIndex()); | ||
210 | } | ||
211 | |||
212 | //Test changed name | ||
213 | { | ||
214 | QSignalSpy dataChanged(model.data(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &))); | ||
215 | folder->setProperty("subject", "modifiedSubject"); | ||
216 | resultProvider->modify(folder); | ||
217 | QTRY_COMPARE(model->rowCount(), 2); | ||
218 | QTRY_COMPARE(dataChanged.count(), 1); | ||
219 | } | ||
220 | |||
221 | //Test removal | ||
222 | { | ||
223 | QSignalSpy rowsRemovedSpy(model.data(), SIGNAL(rowsRemoved(const QModelIndex &, int, int))); | ||
224 | folder->setProperty("subject", "modifiedSubject"); | ||
225 | resultProvider->remove(subfolder); | ||
226 | QTRY_COMPARE(model->rowCount(model->index(0, 0)), 0); | ||
227 | QTRY_COMPARE(rowsRemovedSpy.count(), 1); | ||
228 | } | ||
229 | |||
230 | //TODO: A modification can also be a move | ||
231 | } | ||
232 | |||
233 | |||
122 | }; | 234 | }; |
123 | 235 | ||
124 | QTEST_MAIN(ClientAPITest) | 236 | QTEST_MAIN(ClientAPITest) |