Merge lp:~renatofilho/address-book-service/fix-1387763-rtm into lp:address-book-service/rtm-14.09
- fix-1387763-rtm
- Merge into rtm-14.09
Proposed by
Renato Araujo Oliveira Filho
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Bill Filler | ||||
Approved revision: | 137 | ||||
Merged at revision: | 137 | ||||
Proposed branch: | lp:~renatofilho/address-book-service/fix-1387763-rtm | ||||
Merge into: | lp:address-book-service/rtm-14.09 | ||||
Diff against target: |
443 lines (+275/-41) 5 files modified
lib/addressbook.cpp (+75/-40) lib/addressbook.h (+1/-1) tests/CMakeLists.txt (+3/-0) tests/unittest/CMakeLists.txt (+54/-0) tests/unittest/contact-collection-test.cpp (+142/-0) |
||||
To merge this branch: | bzr merge lp:~renatofilho/address-book-service/fix-1387763-rtm | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Bill Filler (community) | Approve | ||
Review via email: mp+243444@code.launchpad.net |
Commit message
Avoid create sources with duplicated Id;
Remove address book sources based on source name instead of source id.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/addressbook.cpp' |
2 | --- lib/addressbook.cpp 2014-09-30 16:42:48 +0000 |
3 | +++ lib/addressbook.cpp 2014-12-02 19:11:11 +0000 |
4 | @@ -69,10 +69,12 @@ |
5 | class CreateSourceData |
6 | { |
7 | public: |
8 | + QString m_sourceId; |
9 | QString m_sourceName; |
10 | bool m_setAsPrimary; |
11 | galera::AddressBook *m_addressbook; |
12 | QDBusMessage m_message; |
13 | + ESource *m_source; |
14 | }; |
15 | |
16 | class RemoveSourceData |
17 | @@ -82,6 +84,32 @@ |
18 | QDBusMessage m_message; |
19 | }; |
20 | |
21 | +ESource* create_esource_from_data(const CreateSourceData &data, ESourceRegistry **registry) |
22 | +{ |
23 | + GError *error = NULL; |
24 | + ESource *source = e_source_new_with_uid(data.m_sourceId.toUtf8().data(), NULL, &error); |
25 | + if (error) { |
26 | + qWarning() << "Fail to create source" << error->message; |
27 | + g_error_free(error); |
28 | + return 0; |
29 | + } |
30 | + |
31 | + e_source_set_parent(source, "local-stub"); |
32 | + e_source_set_display_name(source, data.m_sourceName.toUtf8().data()); |
33 | + ESourceAddressBook *ext = E_SOURCE_ADDRESS_BOOK(e_source_get_extension(source, E_SOURCE_EXTENSION_ADDRESS_BOOK)); |
34 | + e_source_backend_set_backend_name(E_SOURCE_BACKEND(ext), "local"); |
35 | + |
36 | + *registry = e_source_registry_new_sync(NULL, &error); |
37 | + if (error) { |
38 | + qWarning() << "Fail to change default contact address book" << error->message; |
39 | + g_error_free(error); |
40 | + g_object_unref(source); |
41 | + return 0; |
42 | + } |
43 | + |
44 | + return source; |
45 | +} |
46 | + |
47 | } |
48 | |
49 | namespace galera |
50 | @@ -335,12 +363,12 @@ |
51 | return Source(); |
52 | } |
53 | |
54 | -Source AddressBook::createSource(const QString &sourceId, bool setAsPrimary, const QDBusMessage &message) |
55 | +Source AddressBook::createSource(const QString &sourceName, bool setAsPrimary, const QDBusMessage &message) |
56 | { |
57 | CreateSourceData *data = new CreateSourceData; |
58 | data->m_addressbook = this; |
59 | data->m_message = message; |
60 | - data->m_sourceName = sourceId; |
61 | + data->m_sourceName = sourceName; |
62 | data->m_setAsPrimary = setAsPrimary; |
63 | |
64 | FolksPersonaStore *store = folks_individual_aggregator_get_primary_store(m_individualAggregator); |
65 | @@ -359,22 +387,37 @@ |
66 | NULL, NULL, NULL, NULL, NULL, NULL); |
67 | |
68 | gee_collection_add_all(GEE_COLLECTION(storesIds), GEE_COLLECTION(storesKeys)); |
69 | - gee_collection_add(GEE_COLLECTION(storesIds), sourceId.toUtf8().constData()); |
70 | + gee_collection_add(GEE_COLLECTION(storesIds), sourceName.toUtf8().constData()); |
71 | folks_backend_set_persona_stores(dummy, storesIds); |
72 | |
73 | g_object_unref(storesIds); |
74 | g_object_unref(backendStore); |
75 | g_object_unref(dummy); |
76 | |
77 | - Source src(sourceId, sourceId, false, false); |
78 | + Source src(sourceName, sourceName, false, false); |
79 | QDBusMessage reply = message.createReply(QVariant::fromValue<Source>(src)); |
80 | QDBusConnection::sessionBus().send(reply); |
81 | } else if (personaStoreTypeId == "eds") { |
82 | - edsf_persona_store_create_address_book(sourceId.toUtf8().data(), |
83 | - (GAsyncReadyCallback) AddressBook::createSourceDone, |
84 | - data); |
85 | + data->m_sourceId = QUuid::createUuid().toString().remove("{").remove("}"); |
86 | + ESourceRegistry *registry = NULL; |
87 | + ESource *source = create_esource_from_data(*data, ®istry); |
88 | + if (source) { |
89 | + data->m_source = source; |
90 | + e_source_registry_commit_source(registry, |
91 | + source, |
92 | + NULL, |
93 | + (GAsyncReadyCallback) AddressBook::createSourceDone, |
94 | + data); |
95 | + } else { |
96 | + delete data; |
97 | + QDBusMessage reply = message.createReply(QVariant::fromValue<Source>(Source())); |
98 | + QDBusConnection::sessionBus().send(reply); |
99 | + } |
100 | } else { |
101 | qWarning() << "Not supported, create sources on persona store with type id:" << personaStoreTypeId; |
102 | + delete data; |
103 | + QDBusMessage reply = message.createReply(QVariant::fromValue<Source>(Source())); |
104 | + QDBusConnection::sessionBus().send(reply); |
105 | } |
106 | return Source(); |
107 | } |
108 | @@ -386,19 +429,30 @@ |
109 | bool error = false; |
110 | if (backend) { |
111 | GeeMap *storesMap = folks_backend_get_persona_stores(backend); |
112 | - if (gee_map_has_key(storesMap, sourceId.toUtf8().constData())) { |
113 | - EdsfPersonaStore *ps = EDSF_PERSONA_STORE(gee_map_get(storesMap, sourceId.toUtf8().constData())); |
114 | - |
115 | - RemoveSourceData *rData = new RemoveSourceData; |
116 | - rData->m_addressbook = this; |
117 | - rData->m_message = message; |
118 | - edsf_persona_store_remove_address_book(ps, AddressBook::removeSourceDone, rData); |
119 | + GeeCollection *stores = gee_map_get_values(storesMap); |
120 | + GeeIterator *i = gee_iterable_iterator(GEE_ITERABLE(stores)); |
121 | + RemoveSourceData *rData = 0; |
122 | + while (gee_iterator_next(i)) { |
123 | + FolksPersonaStore *ps = FOLKS_PERSONA_STORE(gee_iterator_get(i)); |
124 | + // We need to compare using source name due the missing API to handle sources diff from contacts |
125 | + if (g_strcmp0(folks_persona_store_get_display_name(ps), sourceId.toUtf8().constData()) == 0) { |
126 | + rData = new RemoveSourceData; |
127 | + rData->m_addressbook = this; |
128 | + rData->m_message = message; |
129 | + edsf_persona_store_remove_address_book(EDSF_PERSONA_STORE(ps), AddressBook::removeSourceDone, rData); |
130 | + g_object_unref(ps); |
131 | + break; |
132 | + } |
133 | g_object_unref(ps); |
134 | - } else { |
135 | + } |
136 | + |
137 | + g_object_unref(backend); |
138 | + g_object_unref(stores); |
139 | + |
140 | + if (!rData) { |
141 | qWarning() << "Source not found to remove:" << sourceId; |
142 | error = true; |
143 | } |
144 | - g_object_unref(backend); |
145 | } else { |
146 | qWarning() << "Fail to create eds backend during the source removal:" << sourceId; |
147 | error = true; |
148 | @@ -486,36 +540,18 @@ |
149 | CreateSourceData *cData = static_cast<CreateSourceData*>(data); |
150 | GError *error = 0; |
151 | Source src; |
152 | - edsf_persona_store_create_address_book_finish(res, &error); |
153 | + e_source_registry_commit_source_finish(E_SOURCE_REGISTRY(source), res, &error); |
154 | if (error) { |
155 | qWarning() << "Fail to create source" << error->message; |
156 | g_error_free(error); |
157 | } else { |
158 | - src = Source(cData->m_sourceName, cData->m_sourceName, false, cData->m_setAsPrimary); |
159 | + // set as primary if necessary |
160 | if (cData->m_setAsPrimary) { |
161 | - ESourceRegistry *r = e_source_registry_new_sync(NULL, &error); |
162 | - if (error) { |
163 | - qWarning() << "Fail to change default contact address book" << error->message; |
164 | - g_error_free(error); |
165 | - } else { |
166 | - ESource *edsSource = 0; |
167 | - GList *sources = e_source_registry_list_sources(r, E_SOURCE_EXTENSION_ADDRESS_BOOK); |
168 | - for(GList *i = sources; i != -0; i = sources->next) { |
169 | - edsSource = E_SOURCE(i->data); |
170 | - if (strcmp(cData->m_sourceName.toUtf8().constData(), e_source_get_uid(edsSource)) == 0) { |
171 | - break; |
172 | - } |
173 | - } |
174 | - if (edsSource) { |
175 | - e_source_registry_set_default_address_book(r, edsSource); |
176 | - } else { |
177 | - qWarning() << "Fail to find source:" << cData->m_sourceName; |
178 | - } |
179 | - g_list_free_full(sources, g_object_unref); |
180 | - } |
181 | - g_object_unref(r); |
182 | + e_source_registry_set_default_address_book(E_SOURCE_REGISTRY(source), cData->m_source); |
183 | } |
184 | + src = Source(cData->m_sourceId, cData->m_sourceName, false, cData->m_setAsPrimary); |
185 | } |
186 | + g_object_unref(source); |
187 | QDBusMessage reply = cData->m_message.createReply(QVariant::fromValue<Source>(src)); |
188 | QDBusConnection::sessionBus().send(reply); |
189 | delete cData; |
190 | @@ -630,7 +666,6 @@ |
191 | } |
192 | |
193 | result << Source(id, displayName, !canWrite, isPrimary); |
194 | - |
195 | g_object_unref(store); |
196 | } |
197 | |
198 | |
199 | === modified file 'lib/addressbook.h' |
200 | --- lib/addressbook.h 2014-09-30 16:23:53 +0000 |
201 | +++ lib/addressbook.h 2014-12-02 19:11:11 +0000 |
202 | @@ -70,7 +70,7 @@ |
203 | void shutdown(); |
204 | SourceList availableSources(const QDBusMessage &message); |
205 | Source source(const QDBusMessage &message); |
206 | - Source createSource(const QString &sourceId, bool setAsPrimary, const QDBusMessage &message); |
207 | + Source createSource(const QString &sourceName, bool setAsPrimary, const QDBusMessage &message); |
208 | void removeSource(const QString &sourceId, const QDBusMessage &message); |
209 | QString createContact(const QString &contact, const QString &source, const QDBusMessage &message = QDBusMessage()); |
210 | int removeContacts(const QStringList &contactIds, const QDBusMessage &message); |
211 | |
212 | === modified file 'tests/CMakeLists.txt' |
213 | --- tests/CMakeLists.txt 2013-05-21 20:11:19 +0000 |
214 | +++ tests/CMakeLists.txt 2014-12-02 19:11:11 +0000 |
215 | @@ -1,2 +1,5 @@ |
216 | +find_program(EVOLUTION_ADDRESSBOOK_FACTORY_BIN evolution-addressbook-factory |
217 | + PATHS /usr/lib/evolution/) |
218 | +set(EVOLUTION_ADDRESSBOOK_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook6") |
219 | add_subdirectory(data) |
220 | add_subdirectory(unittest) |
221 | |
222 | === modified file 'tests/unittest/CMakeLists.txt' |
223 | --- tests/unittest/CMakeLists.txt 2014-05-27 14:41:55 +0000 |
224 | +++ tests/unittest/CMakeLists.txt 2014-12-02 19:11:11 +0000 |
225 | @@ -36,6 +36,57 @@ |
226 | TIMEOUT ${CTEST_TESTING_TIMEOUT}) |
227 | endmacro() |
228 | |
229 | +macro(declare_eds_test TESTNAME) |
230 | + add_executable(${TESTNAME} |
231 | + ${ARGN} |
232 | + ${TESTNAME}.cpp |
233 | + ) |
234 | + qt5_use_modules(${TESTNAME} Core Contacts Versit Test DBus) |
235 | + |
236 | + if(TEST_XML_OUTPUT) |
237 | + set(TEST_ARGS -p -xunitxml -p -o -p test_${testname}.xml) |
238 | + else() |
239 | + set(TEST_ARGS "") |
240 | + endif() |
241 | + |
242 | + target_link_libraries(${TESTNAME} |
243 | + address-book-service-lib |
244 | + ${CONTACTS_SERVICE_LIB} |
245 | + ${GLIB_LIBRARIES} |
246 | + ${GIO_LIBRARIES} |
247 | + ${FOLKS_LIBRARIES} |
248 | + ) |
249 | + |
250 | + add_test(${TESTNAME} |
251 | + ${DBUS_RUNNER} |
252 | + --keep-env |
253 | + --task ${EVOLUTION_ADDRESSBOOK_FACTORY_BIN} --task-name "evolution-addressbook" -r |
254 | + --task ${address-book-service_BINARY_DIR}/address-book-service --wait-for=${EVOLUTION_ADDRESSBOOK_SERVICE_NAME} -r |
255 | + --task ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME} ${TEST_ARGS} --wait-for=com.canonical.pim --wait-until-complete) |
256 | + |
257 | + execute_process(COMMAND mktemp -d /tmp/${TESTNAME}_XXXX |
258 | + OUTPUT_VARIABLE TMP_HOME_DIR) |
259 | + list(APPEND TEST_ENVIRONMENT_LIST "QT_QPA_PLATFORM=minimal") |
260 | + list(APPEND TEST_ENVIRONMENT_LIST "FOLKS_BACKENDS_ALLOWED=eds") |
261 | + list(APPEND TEST_ENVIRONMENT_LIST "HOME=${TMP_HOME_DIR}") |
262 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_RUNTIME_DIR=${TMP_HOME_DIR}") |
263 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_CACHE_HOME=${TMP_HOME_DIR}/.cache") |
264 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_CONFIG_HOME=${TMP_HOME_DIR}/.config") |
265 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_CONFIG_HOME=${TMP_HOME_DIR}/.local/share") |
266 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_DOCUMENTS_DIR=${TMP_HOME_DIR}") |
267 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_DOWNLOAD_DIR=${TMP_HOME_DIR}") |
268 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_MUSIC_DIR=${TMP_HOME_DIR}") |
269 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_PICTURES_DIR=${TMP_HOME_DIR}") |
270 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_PUBLICSHARE_DIR=${TMP_HOME_DIR}") |
271 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_TEMPLATES_DIR=${TMP_HOME_DIR}") |
272 | + list(APPEND TEST_ENVIRONMENT_LIST "XDG_VIDEOS_DIR=${TMP_HOME_DIR}") |
273 | + list(APPEND TEST_ENVIRONMENT_LIST "QORGANIZER_EDS_DEBUG=On") |
274 | + |
275 | + set_tests_properties(${TESTNAME} PROPERTIES |
276 | + ENVIRONMENT ${TEST_ENVIRONMENT_LIST} |
277 | + TIMEOUT ${CTEST_TESTING_TIMEOUT}) |
278 | +endmacro() |
279 | + |
280 | include_directories( |
281 | ${CMAKE_SOURCE_DIR} |
282 | ${CMAKE_BINARY_DIR} |
283 | @@ -77,6 +128,8 @@ |
284 | declare_test(qcontacts-test True ${BASE_CLIENT_TEST_SRC}) |
285 | declare_test(qcontacts-create-source-test True ${BASE_CLIENT_TEST_SRC}) |
286 | declare_test(qcontacts-async-request-test True ${BASE_CLIENT_TEST_SRC}) |
287 | + |
288 | + declare_eds_test(contact-collection-test) |
289 | elseif() |
290 | message(STATUS "DBus test runner not found. Some tests will be disabled") |
291 | endif() |
292 | @@ -101,3 +154,4 @@ |
293 | ${FOLKS_LIBRARIES} |
294 | ) |
295 | |
296 | + |
297 | |
298 | === added file 'tests/unittest/contact-collection-test.cpp' |
299 | --- tests/unittest/contact-collection-test.cpp 1970-01-01 00:00:00 +0000 |
300 | +++ tests/unittest/contact-collection-test.cpp 2014-12-02 19:11:11 +0000 |
301 | @@ -0,0 +1,142 @@ |
302 | +/* |
303 | + * Copyright 2013 Canonical Ltd. |
304 | + * |
305 | + * This file is part of contact-service-app. |
306 | + * |
307 | + * contact-service-app is free software; you can redistribute it and/or modify |
308 | + * it under the terms of the GNU General Public License as published by |
309 | + * the Free Software Foundation; version 3. |
310 | + * |
311 | + * contact-service-app is distributed in the hope that it will be useful, |
312 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
313 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
314 | + * GNU General Public License for more details. |
315 | + * |
316 | + * You should have received a copy of the GNU General Public License |
317 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
318 | + */ |
319 | + |
320 | +#include <QObject> |
321 | +#include <QtTest> |
322 | +#include <QDebug> |
323 | +#include <QtContacts> |
324 | + |
325 | +#include "config.h" |
326 | + |
327 | +using namespace QtContacts; |
328 | + |
329 | +class ContactCollectionTest : public QObject |
330 | +{ |
331 | + Q_OBJECT |
332 | +private: |
333 | + QContactManager *m_manager; |
334 | + |
335 | +private Q_SLOTS: |
336 | + void initTestCase() |
337 | + { |
338 | + QCoreApplication::setLibraryPaths(QStringList() << QT_PLUGINS_BINARY_DIR); |
339 | + // wait for address-book-service |
340 | + QTest::qWait(1000); |
341 | + } |
342 | + |
343 | + void init() |
344 | + { |
345 | + m_manager = new QContactManager("galera"); |
346 | + } |
347 | + |
348 | + void cleanup() |
349 | + { |
350 | + delete m_manager; |
351 | + } |
352 | + |
353 | + /* |
354 | + * Test create a new collection |
355 | + */ |
356 | + void testCreateAddressBook() |
357 | + { |
358 | + QContact c; |
359 | + c.setType(QContactType::TypeGroup); |
360 | + QContactDisplayLabel label; |
361 | + QString uniqueName = QString("source@%1").arg(QUuid::createUuid().toString().remove("{").remove("}")); |
362 | + label.setLabel(uniqueName); |
363 | + c.saveDetail(&label); |
364 | + |
365 | + bool saveResult = m_manager->saveContact(&c); |
366 | + QVERIFY(saveResult); |
367 | + |
368 | + QContactDetailFilter filter; |
369 | + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); |
370 | + filter.setValue(QContactType::TypeGroup); |
371 | + |
372 | + QList<QContact> contacts = m_manager->contacts(filter); |
373 | + Q_FOREACH(const QContact &contact, contacts) { |
374 | + if ((contact.detail<QContactDisplayLabel>().label() == uniqueName) && |
375 | + (contact.id() == c.id())) { |
376 | + return; |
377 | + } |
378 | + } |
379 | + QFAIL("New collection not found"); |
380 | + } |
381 | + |
382 | + /* |
383 | + * Test remove a collection |
384 | + */ |
385 | + void testRemoveAddressBook() |
386 | + { |
387 | + // create a source |
388 | + QContact c; |
389 | + c.setType(QContactType::TypeGroup); |
390 | + QContactDisplayLabel label; |
391 | + QString uniqueName = QString("source@%1").arg(QUuid::createUuid().toString().remove("{").remove("}")); |
392 | + label.setLabel(uniqueName); |
393 | + c.saveDetail(&label); |
394 | + |
395 | + bool saveResult = m_manager->saveContact(&c); |
396 | + QVERIFY(saveResult); |
397 | + |
398 | + // try to remove new source |
399 | + // WORKAROUND: Since qcontacts does not cotains a API to remove address book we use the contact label as id |
400 | + // for addressbook. This Id must contain a "@" to be handled as address book name. |
401 | + QContactId addressBookId = QContactId::fromString(QString("qtcontacts:galera::%1").arg(uniqueName)); |
402 | + bool removeResult = m_manager->removeContact(addressBookId); |
403 | + QVERIFY(removeResult); |
404 | + |
405 | + // check if the source was removed |
406 | + QContactDetailFilter filter; |
407 | + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); |
408 | + filter.setValue(QContactType::TypeGroup); |
409 | + QList<QContact> contacts = m_manager->contacts(filter); |
410 | + Q_FOREACH(const QContact &contact, contacts) { |
411 | + if (contact.id() == c.id()) { |
412 | + QFAIL("Collection not removed"); |
413 | + } |
414 | + } |
415 | + } |
416 | + |
417 | + /* |
418 | + * Test query for collections using the contact group type |
419 | + */ |
420 | + void testQueryAddressBook() |
421 | + { |
422 | + // filter all contact groups/addressbook |
423 | + QContactDetailFilter filter; |
424 | + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); |
425 | + filter.setValue(QContactType::TypeGroup); |
426 | + |
427 | + // check result for the default source |
428 | + QList<QContact> contacts = m_manager->contacts(filter); |
429 | + Q_FOREACH(const QContact &c, contacts) { |
430 | + QCOMPARE(c.type(), QContactType::TypeGroup); |
431 | + if (c.id().toString() == QStringLiteral("qtcontacts:galera::system-address-book")) { |
432 | + QContactDisplayLabel label = c.detail(QContactDisplayLabel::Type); |
433 | + QCOMPARE(label.label(), QStringLiteral("Personal")); |
434 | + return; |
435 | + } |
436 | + } |
437 | + QFAIL("Fail to query for collections"); |
438 | + } |
439 | +}; |
440 | + |
441 | +QTEST_MAIN(ContactCollectionTest) |
442 | + |
443 | +#include "contact-collection-test.moc" |
approved